Loam Customer API · Preview
Developer Hub
Start here to build on the Loam Customer API.
A payment, as the API writes it
Send money with amount and currency to an approved destination. The write returns 202 with { id, state } and a Location. It needs the money.write scope, an owner grant under step-up authentication, and stays closed in preview.
curl -X POST "$LOAM_API_BASE/payments" \ -H "Authorization: Bearer $LOAM_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "destination_id": "2f4cbb59-3ab1-4b6d-8d10-9cd2236cf94e", "amount": 2500000, "currency": "USD" }'// Response
HTTP/1.1 202 Accepted
Location: /api/v1/payments/<payment-id>
{
"ok": true,
"data": {
"id": "<payment-id>",
"state": "processing"
}
}What the API covers today
Preview access is deliberately narrower than the published contract. Everything below is callable now or names the grant it is waiting on.
Open in preview
- Settled balances
GET /api/v1/balances - Payments, listed
GET /api/v1/payments - Treasury vault terms
GET /api/v1/vaults - Foreign-exchange quotes
POST /api/v1/fx/quotes
Closed in preview
- Payments to an approved destination
POST /api/v1/payments - Funds in from a bank account
POST /api/v1/onramp - Funds out to a bank account
POST /api/v1/offramp - Vault deposits and withdrawals
POST /api/v1/vaults/…
Money movement needs a human organisation owner to grant the scope under step-up authentication, set a per-transaction limit, and approve the destination in advance. Those endpoints stay closed until preview ends.
How the API behaves
OAuth 2.0
Client credentials grant
Exchange a client id and secret for a short-lived bearer token with one form-encoded request. Scopes are read from the client per request, so narrowing one applies at once.
Envelope
One shape for every route
Success is
okthendata; failure isok: falsewith a machine-readable error code.Idempotency
Retries cost nothing
Every write requires an
Idempotency-Key. The same key with the same body replays the first outcome instead of writing twice.Pagination
Cursors, not offsets
List routes return
page.next_cursor. Pass it back ascursoruntil it comes back null.
Pick a path from here: the quickstart if you want a working request in front of you first, the reference if you already know the call you need.