{"openapi":"3.1.0","info":{"title":"Loam settlement API","version":"1.0.0","summary":"Read settlement data, request FX quotes, and move funds from your own systems.","description":"Read balances, send payments to approved destinations, add funds from operator-supplied\nbank accounts, and deposit into or withdraw from treasury vaults.\n\n## Get access\n\nAn organisation owner creates one in Settings → API clients, after confirming with an authenticator app. Loam shows\nits `client_secret` once, at creation, and never again. Rotating the client issues a new\nsecret; the previous one keeps working for up to 24 hours, and stops sooner if you\nrotate again, so integrations can switch over. If a secret leaked, revoke the client\nto invalidate both secrets immediately. Only an organisation owner can rotate a client, after confirming with an authenticator app. Owners and admins can revoke one; only an owner can revoke a client that holds `money.write`. The `client_id` stays visible in that table. The API answers on the host you sign in to, under `/api/v1`. Your\norganisation owner approves payment destinations there and grants `money.write` under\nstep-up authentication with per-transaction limits. Onramp funding-account IDs\n(`source_id`) come from your operator. Exchange the client credentials at\n`POST /oauth/token`, then send the returned bearer token with each request.\n\n## Scopes and limits\n\n`read` allows every GET endpoint available to your client. `write` allows non-money\nchanges available from your operator. `money.write` allows payments, bank transfers,\nvault deposits and vault withdrawals. Rate limits are set by your operator; follow\n`Retry-After` when it is returned.\n"},"servers":[{"url":"https://{operatorHost}/api/v1","description":"Replace `operatorHost` with the host you sign in to.","variables":{"operatorHost":{"default":"api.operator.example","description":"The operator deployment host that issued the API client credential."}}}],"tags":[{"name":"Authentication","description":"Create a short-lived access token from the client credentials supplied by your operator. Use that token as a bearer token for every other request."},{"name":"Trades","description":"A trade records an exchange involving your organisation. List trades, retrieve one by ID, and fetch the invoices issued for either side of a trade."},{"name":"Payments","description":"A payment records money sent from your organisation to an approved destination. List or retrieve payments, submit a new payment, and poll its status until it completes."},{"name":"FX","description":"Request platform-derived, short-lived foreign-exchange quotes and retrieve them by ID."},{"name":"Treasury","description":"View your settled balances and the terms of available treasury vaults. Deposit funds into a vault, withdraw them, and poll each request until it completes."},{"name":"Marketplace","description":"Listings describe assets available to trade; offers are your proposals against those listings. Browse listings, inspect your offers, and create an offer for a listing."},{"name":"Funding","description":"On-ramp transfers move funds from an operator-supplied funding account (source_id) into your Loam balance. Start an on-ramp transfer and poll its status until it completes. Off-ramp creation stays closed until destination screening and travel-rule certification are complete."}],"security":[{"oauth2":["read"]}],"paths":{"/oauth/token":{"post":{"tags":["Authentication"],"operationId":"issueAccessToken","summary":"Exchange client credentials for an access token","description":"Exchange `client_id` and `client_secret` for a short-lived access token using the\nOAuth 2 client credentials grant. Send the request as\n`application/x-www-form-urlencoded`; HTTP Basic authentication is not supported. Use\n`scope` to request a space-delimited subset of the scopes granted to the client.\n","security":[],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/OAuthTokenRequest"},"example":{"grant_type":"client_credentials","client_id":"loam_ck_01J8YQ7N2M4P6R8T0V2X4Z6A8C","client_secret":"secret_supplied_once_by_your_operator"}}}},"responses":{"200":{"description":"Access token issued.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"},"example":{"access_token":"access_token_value","token_type":"Bearer","expires_in":3600,"scope":"read money.write"}}}},"400":{"description":"The request is invalid or uses an unsupported grant type.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"},"examples":{"InvalidRequest":{"value":{"error":"invalid_request"}},"UnsupportedGrantType":{"value":{"error":"unsupported_grant_type"}},"InvalidScope":{"value":{"error":"invalid_scope"}}}}}},"401":{"description":"The client credentials are invalid or revoked.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"},"WWW-Authenticate":{"$ref":"#/components/headers/WwwAuthenticate"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"},"example":{"error":"invalid_client"}}}},"403":{"description":"API access is disabled for this operator or organisation.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"},"example":{"error":"unauthorized_client"}}}},"429":{"$ref":"#/components/responses/OAuthTooManyRequests"},"503":{"$ref":"#/components/responses/OAuthServiceUnavailable"}}}},"/trades":{"get":{"tags":["Trades"],"operationId":"listTrades","summary":"List your organisation's trades","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of trades.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradePage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/trades/{trade_id}":{"get":{"tags":["Trades"],"operationId":"getTrade","summary":"Fetch one trade","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/TradeId"}],"responses":{"200":{"description":"The trade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradeEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/trades/{trade_id}/invoices":{"get":{"tags":["Trades"],"operationId":"listInvoicesForTrade","summary":"List invoices for a trade","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/TradeId"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of the trade's invoices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/payments":{"get":{"tags":["Payments"],"operationId":"listPayments","summary":"List your organisation's payments","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of payments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Payments"],"operationId":"sendPayment","summary":"Send a payment to an approved destination","x-loam-required-scope":"money.write","security":[{"oauth2":["money.write"]}],"x-loam-money-authorization":"outbound-to-approved-destination","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPaymentRequest"},"example":{"destination_id":"2f4cbb59-3ab1-4b6d-8d10-9cd2236cf94e","amount":2500000,"currency":"USD"}}}},"responses":{"202":{"$ref":"#/components/responses/WriteAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/payments/{payment_id}":{"get":{"tags":["Payments"],"operationId":"getPayment","summary":"Fetch one payment","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/PaymentId"}],"responses":{"200":{"description":"The payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/balances":{"get":{"tags":["Treasury"],"operationId":"listBalances","summary":"List your organisation's balances","description":"Stablecoin-only. The projection excludes fiat treasury rows; every returned balance is a held stablecoin.","x-loam-required-scope":"read","responses":{"200":{"description":"The organisation's treasury balances.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/fx/quotes":{"get":{"tags":["FX"],"operationId":"listFxQuotes","summary":"List your organisation's foreign-exchange quotes","description":"No `idempotency_key` filter is available; recover a lost quote by re-quoting.","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of foreign-exchange quotes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FxQuotePage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["FX"],"operationId":"createFxQuote","summary":"Request a platform-derived foreign-exchange quote","description":"Mints a short-lived quote by fanning out to the operator's currently assured FX\nproviders. The rate, target amount, fee and expiry are provider-derived; the caller\nsupplies only the source amount and stablecoin-to-stablecoin currency pair. Creating a\nquote does not move money — execution is a separate capability and is not exposed by\nthis operation.\n\nA quote is minted only when enough of the operator's connected FX vendors price the pair,\nso availability depends on vendor coverage and a valid request can still be refused. `202`\nis the outcome only when the pair is priced. A valid pair that cannot be priced right now\nanswers `503` with `transient_error`: no connected vendor quotes it, fewer vendors quote it\nthan the platform requires for that direction, or every vendor failed to answer in time.\nRepeating the same request does not change that outcome until vendor coverage changes. A\npair that no vendor lists answers `400` with `invalid_input`. As of 2026-10-04 the only\nlisted stablecoin pair, `USDC` to `EURC`, is quoted by a single vendor, below the minimum of\ntwo vendors required for that direction, so it answers `503`.\n","x-loam-required-scope":"write","security":[{"oauth2":["write"]}],"x-loam-money-authorization":"no-money-movement","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFxQuoteRequest"},"example":{"from_currency":"USDC","to_currency":"EURC","amount":100000000}}}},"responses":{"202":{"$ref":"#/components/responses/FxQuoteAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/fx/quotes/{quote_id}":{"get":{"tags":["FX"],"operationId":"getFxQuote","summary":"Fetch one foreign-exchange quote","description":"Returns a quote visible to the calling organisation. Provider identity and the\nvendor's locked-rate handle are internal routing details and are never published.\n","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/FxQuoteId"}],"responses":{"200":{"description":"The foreign-exchange quote.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FxQuoteEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/vaults":{"get":{"tags":["Treasury"],"operationId":"listVaults","summary":"List your operator's treasury vaults","description":"List the vaults you can hold a position in, with each vault's state, currency, fees and lockup terms. Only an `active` vault accepts deposits; `paused` and `closed` vaults accept withdrawals only. A closed vault is listed only while your organisation still holds a position in it. Every vault endpoint answers `404` while your operator has treasury vaults switched off.","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of vaults.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/listings":{"get":{"tags":["Marketplace"],"operationId":"listListings","summary":"List your listings and published marketplace listings","description":"Returns the caller's own-organisation listings regardless of state, plus every\npublished listing on the operator. The projection intentionally carries no\nseller-identifying field, so the published-marketplace leg exposes no seller\nidentity by design.\n","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of listings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/offers":{"get":{"tags":["Marketplace"],"operationId":"listOffers","summary":"List your organisation's offers","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A cursor page of offers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Marketplace"],"operationId":"createOffer","summary":"Create an offer for a listing","x-loam-required-scope":"write","security":[{"oauth2":["write"]}],"x-loam-money-authorization":"no-money-movement","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOfferRequest"},"example":{"listing_id":"94415e8e-1eb5-468a-b1d4-aa9a0473ec63","offered_price":{"minor_units":2500000,"currency":"USD"}}}}},"responses":{"202":{"$ref":"#/components/responses/WriteAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/offers/{offer_id}":{"get":{"tags":["Marketplace"],"operationId":"getOffer","summary":"Fetch one offer","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/OfferId"}],"responses":{"200":{"description":"The offer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/onramp":{"get":{"tags":["Funding"],"operationId":"listOnramps","summary":"List your organisation's inbound bank transfers","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IdempotencyKeyFilter"}],"responses":{"200":{"description":"A cursor page of on-ramp requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnrampPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Funding"],"operationId":"createOnramp","summary":"Add funds from an operator-supplied funding account","description":"Start a transfer from an operator-supplied funding account (source_id) into your Loam balance.","x-loam-required-scope":"money.write","security":[{"oauth2":["money.write"]}],"x-loam-money-authorization":"no-external-destination","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOnrampRequest"},"example":{"source_id":"7c501bfe-ffef-4670-9b8d-ed731e8ee3b2","amount":2500000,"currency":"USD"}}}},"responses":{"202":{"$ref":"#/components/responses/WriteAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/onramp/{onramp_id}":{"get":{"tags":["Funding"],"operationId":"getOnramp","summary":"Check an inbound bank transfer","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/OnrampId"}],"responses":{"200":{"description":"The on-ramp request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnrampEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/offramp":{"get":{"tags":["Funding"],"operationId":"listOfframps","summary":"List your organisation's outbound bank transfers","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IdempotencyKeyFilter"}],"responses":{"200":{"description":"A cursor page of off-ramp requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfframpPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Funding"],"operationId":"createOfframp","summary":"Send funds to an approved bank account (not yet available)","description":"Not yet available. Every request with a valid body is currently refused with `403 forbidden` until destination screening and travel-rule certification are complete. The request shape is published so you can build against it; once the operation opens it starts a transfer from your Loam balance to an approved bank account and returns `202`.","x-loam-required-scope":"money.write","security":[{"oauth2":["money.write"]}],"x-loam-money-authorization":"outbound-to-approved-destination","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOfframpRequest"},"example":{"destination_id":"2f4cbb59-3ab1-4b6d-8d10-9cd2236cf94e","amount":2500000,"currency":"USD"}}}},"responses":{"202":{"$ref":"#/components/responses/WriteAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Always returned while this operation is not yet available; also returned for a missing scope or permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"forbidden"}}}},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/offramp/{offramp_id}":{"get":{"tags":["Funding"],"operationId":"getOfframp","summary":"Check an outbound bank transfer","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/OfframpId"}],"responses":{"200":{"description":"The off-ramp request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfframpEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/vaults/{vault_id}/deposits":{"get":{"tags":["Treasury"],"operationId":"listVaultDeposits","summary":"List deposits for a vault","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IdempotencyKeyFilter"}],"responses":{"200":{"description":"A cursor page of vault deposit requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultDepositPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Treasury"],"operationId":"createVaultDeposit","summary":"Deposit into a vault","description":"Start a deposit into the selected vault.","x-loam-required-scope":"money.write","security":[{"oauth2":["money.write"]}],"x-loam-money-authorization":"no-external-destination","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVaultDepositRequest"},"example":{"amount":2500000}}}},"responses":{"202":{"$ref":"#/components/responses/VaultDepositAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/vaults/{vault_id}/deposits/{deposit_id}":{"get":{"tags":["Treasury"],"operationId":"getVaultDeposit","summary":"Check a vault deposit","description":"Get the current state and the vault-token amount credited by the deposit.","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/DepositId"}],"responses":{"200":{"description":"The vault deposit request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultDepositEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/vaults/{vault_id}/withdrawals":{"get":{"tags":["Treasury"],"operationId":"listVaultWithdrawals","summary":"List withdrawals for a vault","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IdempotencyKeyFilter"}],"responses":{"200":{"description":"A cursor page of vault withdrawal requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultWithdrawalPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["Treasury"],"operationId":"createVaultWithdrawal","summary":"Withdraw from a vault","description":"Start a withdrawal from the selected vault.","x-loam-required-scope":"money.write","security":[{"oauth2":["money.write"]}],"x-loam-money-authorization":"no-external-destination","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVaultWithdrawalRequest"},"example":{"amount":2500000}}}},"responses":{"202":{"$ref":"#/components/responses/VaultWithdrawalAccepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/vaults/{vault_id}/withdrawals/{withdrawal_id}":{"get":{"tags":["Treasury"],"operationId":"getVaultWithdrawal","summary":"Check a vault withdrawal","description":"Get the current state and the final token amount after any early-exit penalty.","x-loam-required-scope":"read","parameters":[{"$ref":"#/components/parameters/VaultId"},{"$ref":"#/components/parameters/WithdrawalId"}],"responses":{"200":{"description":"The vault withdrawal request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultWithdrawalEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"Exchange the client credentials you created in Settings → API clients for an access token.","flows":{"clientCredentials":{"tokenUrl":"/api/v1/oauth/token","scopes":{"read":"Read trades, invoices, payments, balances, vaults, listings, offers and transfers.","write":"Create offers.","money.write":"Send payments to approved destinations, onramp from operator-supplied funding accounts, and deposit into or withdraw from vaults."}}}}},"headers":{"NoStore":{"description":"Prevents the access token from being cached.","schema":{"type":"string"}},"NoCache":{"description":"Prevents the access token from being cached by older HTTP clients.","schema":{"type":"string"}},"WwwAuthenticate":{"description":"Bearer challenge returned with every `401` response.","schema":{"type":"string"}},"AcceptedLocation":{"description":"Resource path relative to the API host. Poll it for the current state.","schema":{"type":"string"}}},"parameters":{"Limit":{"name":"limit","in":"query","required":false,"description":"Maximum items in the page. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Cursor":{"name":"cursor","in":"query","required":false,"description":"Pass the previous response's `next_cursor` to fetch the next page. Use the value\nexactly as returned.\n","schema":{"type":"string","maxLength":512}},"IdempotencyKeyFilter":{"name":"idempotency_key","in":"query","required":false,"description":"Return only the transfer created by this API client with this idempotency key.","schema":{"type":"string","minLength":16,"maxLength":255}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Use a unique value for each write request. To retry a request, send the same value\nwith the same body. Reusing a value with a different body returns `409`. UUID v4\nvalues are recommended.\n","schema":{"type":"string","minLength":16,"maxLength":255}},"TradeId":{"name":"trade_id","in":"path","required":true,"description":"Trade ID returned by `GET /trades`.","schema":{"type":"string","format":"uuid"}},"PaymentId":{"name":"payment_id","in":"path","required":true,"description":"Payment ID returned by `GET /payments` or `POST /payments`.","schema":{"type":"string","format":"uuid"}},"OfferId":{"name":"offer_id","in":"path","required":true,"description":"Offer ID returned by `GET /offers` or `POST /offers`.","schema":{"type":"string","format":"uuid"}},"FxQuoteId":{"name":"quote_id","in":"path","required":true,"description":"Foreign-exchange quote id returned by `POST /fx/quotes`.","schema":{"type":"string","format":"uuid"}},"OnrampId":{"name":"onramp_id","in":"path","required":true,"description":"Transfer ID returned by `POST /onramp`.","schema":{"type":"string","format":"uuid"}},"OfframpId":{"name":"offramp_id","in":"path","required":true,"description":"Transfer ID returned by `POST /offramp`.","schema":{"type":"string","format":"uuid"}},"DepositId":{"name":"deposit_id","in":"path","required":true,"description":"Deposit ID returned by `POST /vaults/{vault_id}/deposits`. Use it exactly as\nreturned; do not parse or modify it.\n","schema":{"type":"string","minLength":1,"maxLength":255}},"WithdrawalId":{"name":"withdrawal_id","in":"path","required":true,"description":"Withdrawal ID returned by `POST /vaults/{vault_id}/withdrawals`. Use it exactly as\nreturned; do not parse or modify it.\n","schema":{"type":"string","minLength":1,"maxLength":255}},"VaultId":{"name":"vault_id","in":"path","required":true,"description":"Vault ID returned by `GET /vaults`.","schema":{"type":"string","format":"uuid"}}},"responses":{"WriteAccepted":{"description":"Accepted for processing. Poll the resource in `Location` for its current state.","headers":{"Location":{"$ref":"#/components/headers/AcceptedLocation"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteAcceptedEnvelope"}}}},"FxQuoteAccepted":{"description":"The provider-derived quote was durably minted. `Location` names its by-id read.\n","headers":{"Location":{"$ref":"#/components/headers/AcceptedLocation"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FxQuoteEnvelope"}}}},"VaultDepositAccepted":{"description":"Deposit request accepted for processing.","headers":{"Location":{"$ref":"#/components/headers/AcceptedLocation"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultDepositAcceptedEnvelope"}}}},"VaultWithdrawalAccepted":{"description":"Withdrawal request accepted for processing.","headers":{"Location":{"$ref":"#/components/headers/AcceptedLocation"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultWithdrawalAcceptedEnvelope"}}}},"BadRequest":{"description":"The request body or parameters are invalid; body-referenced destination_id values outside the caller's organisation and unpublished cross-organisation listing_id values produce the same 400 invalid_input response as an absent id of the corresponding kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"invalid_input"}}}},"Unauthorized":{"description":"The bearer token is missing, malformed, expired or revoked.","headers":{"WWW-Authenticate":{"$ref":"#/components/headers/WwwAuthenticate"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"unauthorized"}}}},"Forbidden":{"description":"The client lacks the required scope or permission, or a payment destination was revoked. A same-key retry of a money write may be refused: read the original write back instead of retrying with a new key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"Forbidden":{"value":{"ok":false,"error":"forbidden"}},"DestinationRevoked":{"value":{"ok":false,"error":"destination_revoked"}}}}}},"NotFound":{"description":"The addressed resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"not_found"}}}},"Conflict":{"description":"`conflict` has five causes: an idempotency key reused with a different body; a\nduplicate of the same request while the first is still processing; a state change\nthe resource does not permit; a stale request that the reconciliation sweep closed\nbefore the client replayed it; or a request body that violates a resource rule.\n\nResource-rule conflicts include an offered currency that does not match the parent\nlisting and an offer on a listing owned by the caller's organisation. A state-change\nconflict may succeed later with the same body; a resource-rule conflict will not, so\nthe client must change the body.\n\nOnly a duplicate received while the first request is processing carries\n`Retry-After`; the other four causes are not retryable and omit it.\n\nA payment whose amount the payer's available balance cannot cover answers\n`insufficient_balance` instead: payments in progress hold funds until they settle, so\nthe same request can succeed once the organisation is funded.\n","headers":{"Retry-After":{"description":"Present only while the first request is still processing: seconds to wait before\nreplaying the same key to read that request's terminal state.\n","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"Conflict":{"value":{"ok":false,"error":"conflict"}},"InsufficientBalance":{"value":{"ok":false,"error":"insufficient_balance"}}}}}},"TooManyRequests":{"description":"Too many requests. Retry after the number of seconds in `Retry-After`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"rate_limited"}}}},"ServiceUnavailable":{"description":"`transient_error` — the server cannot fulfil the request right now. Retry the request;\nfor an idempotent write, this response never implies the write did not happen, so reuse\nthe same `Idempotency-Key`. When a failure releases the claim, the same-key retry re-executes\nand the write stays single-shot (on `POST /payments` a write that already committed is\nreplayed, not repeated — prefer the same key there). When a failure holds the claim, the\nsame-key retry returns `409 conflict` with `Retry-After` until the stale-claim sweep\nforce-completes the claim to a terminal `409` and never re-executes; recover by reading — the\nby-id read from the `Location` of any `202`; otherwise the collection read where one exists.\nFor `/trades`, `/payments`, and `/offers`, match client-side on the request's own fields (amount, currency, counterparty/destination) within the retry window; this is not exact under concurrent identical writes.\nFor ramp writes, use `GET /onramp?idempotency_key=<key>` or\n`GET /offramp?idempotency_key=<key>`, scoped to the calling API client. For vault writes,\nuse the client-scoped collection reads filtered by\n`idempotency_key`: `GET /vaults/{vault_id}/deposits?idempotency_key=<key>` or\n`GET /vaults/{vault_id}/withdrawals?idempotency_key=<key>`. A lost `/fx/quotes` write is\ndisposable: request a new quote with a new key.\nA persistent `503` response on a read can indicate a server-side projection-integrity fault;\nany persistent `503` response on a read should be escalated to the operator.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"ok":false,"error":"transient_error"}}}},"OAuthTooManyRequests":{"description":"The token request rate limit was exceeded.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"},"example":{"error":"rate_limited"}}}},"OAuthServiceUnavailable":{"description":"The token service is temporarily unavailable.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Pragma":{"$ref":"#/components/headers/NoCache"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"},"example":{"error":"temporarily_unavailable"}}}}},"schemas":{"OAuthTokenRequest":{"type":"object","description":"Credentials supplied by your Loam operator.","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"const":"client_credentials","description":"Must be `client_credentials`."},"client_id":{"type":"string","description":"The API client identifier: `loam_ck_` followed by a 26-character ULID."},"client_secret":{"type":"string","format":"password","writeOnly":true,"description":"The API client secret, shown exactly once at creation."},"scope":{"type":"string","description":"Optional space-delimited subset of the scopes granted to the client. Omitting the parameter grants the client's full current scope set; sending it present but empty or whitespace-only returns 400 invalid_scope."}}},"OAuthTokenResponse":{"type":"object","description":"Access token and its granted scopes.","required":["access_token","token_type","expires_in","scope"],"properties":{"access_token":{"type":"string","description":"Bearer access token for API requests."},"token_type":{"const":"Bearer","description":"Always `Bearer`."},"expires_in":{"type":"integer","minimum":1,"maximum":3600,"description":"Lifetime in seconds, up to 3600."},"scope":{"type":"string","description":"Space-delimited scopes granted to this access token."}},"additionalProperties":false},"OAuthError":{"type":"object","description":"OAuth 2 error response.","required":["error"],"properties":{"error":{"type":"string","description":"OAuth 2 error code.","enum":["invalid_request","invalid_client","unauthorized_client","unsupported_grant_type","invalid_scope","rate_limited","temporarily_unavailable"]},"error_description":{"type":"string","maxLength":256,"description":"Human-readable detail for the OAuth 2 error."},"error_uri":{"type":"string","format":"uri"}},"additionalProperties":false},"ErrorCode":{"type":"string","description":"Machine-readable error code. Use the HTTP status for broad handling and this value\nwhen your client needs a specific recovery path.\n","enum":["invalid_input","unauthorized","forbidden","destination_revoked","not_found","conflict","insufficient_balance","rate_limited","transient_error"]},"ErrorEnvelope":{"type":"object","description":"Error response for API resources.","required":["ok","error"],"properties":{"ok":{"const":false},"error":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Optional customer-facing detail for a vault booking gate."}},"additionalProperties":false},"WriteAcceptedEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["id","state"],"properties":{"id":{"type":"string","description":"Identifier for the accepted resource. Use it exactly as returned."},"state":{"type":"string","description":"Resource-specific state when the request was accepted. Poll `Location` and use that resource's state enum for later values."}},"additionalProperties":false}},"additionalProperties":false},"Amount":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"An integer amount in the currency's smallest unit. For example, `1050` with `USD` means `10.50 USD`."},"SignedMinorAmount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"A signed integer amount used only for an FX fee, where a negative amount is a rebate."},"PositiveAmount":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"A positive integer amount in the currency's smallest unit. For example, `1050` with `USD` means `10.50 USD`."},"CurrencyCode":{"type":"string","pattern":"^[A-Z]{3,4}$","description":"Uppercase currency code, such as `USD`, `EUR`, `USDC` or `EURC`. Use a currency enabled\nby your Loam operator. FX quote requests currently accept only stablecoin-to-stablecoin\npairs; fiat codes remain available for ramp legs and invoice or price denomination.\n"},"StablecoinCurrencyCode":{"type":"string","enum":["USDC","EURC"],"description":"Uppercase stablecoin currency code. A narrower allow-list than `CurrencyCode`, used only\nwhere a field must be stablecoin-to-stablecoin, such as an FX quote request.\n"},"PageMeta":{"type":"object","required":["next_cursor"],"properties":{"next_cursor":{"type":["string","null"],"description":"Cursor for the next page, or `null` on the last page."}},"additionalProperties":false},"Trade":{"type":"object","description":"A trade visible to your organisation.","required":["id","state","counterparty_organisation_id","amount","currency","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["created","contract_pending","contract_signed","payment_pending","settled","completed","cancelled"],"description":"Current trade state."},"counterparty_organisation_id":{"type":["string","null"],"format":"uuid","description":"Other organisation in the trade, or `null` until one is assigned."},"amount":{"$ref":"#/components/schemas/Amount"},"currency":{"$ref":"#/components/schemas/CurrencyCode"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"Invoice":{"type":"object","description":"An invoice for the calling organisation's side of a trade.","required":["id","trade_id","invoice_number","state","direction","amount","currency","issued_at","due_at","paid_at","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"trade_id":{"type":"string","format":"uuid","description":"The trade associated with this invoice."},"invoice_number":{"type":"string"},"issued_at":{"type":"string","format":"date-time"},"due_at":{"type":["string","null"],"format":"date-time"},"state":{"type":"string","enum":["created","ready_to_be_paid","paid","cancelled"],"description":"Current invoice state."},"direction":{"type":"string","enum":["incoming","outgoing"],"description":"Whether the invoice is receivable or payable from your organisation's side."},"amount":{"$ref":"#/components/schemas/Amount"},"currency":{"$ref":"#/components/schemas/CurrencyCode"},"paid_at":{"type":["string","null"],"format":"date-time","description":"Set if and only if `state` is `paid`."},"created_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"Vault":{"type":"object","description":"A published vault. `state` says which requests it accepts. Account balances are returned by `GET /balances`.","required":["id","name","currency","state","fees_apy_basis_points","lockup_terms"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":255},"currency":{"$ref":"#/components/schemas/CurrencyCode","description":"Currency accepted by this vault. Deposit and withdrawal amounts use this\ncurrency's smallest unit.\n"},"state":{"type":"string","enum":["active","paused","closed"],"description":"`active` accepts deposits and withdrawals; `paused` and `closed` accept withdrawals only."},"fees_apy_basis_points":{"type":"integer","minimum":0,"description":"Annual fee in basis points."},"lockup_terms":{"description":"`null` for a liquid vault. A `fixed_lockup` vault can charge an early-exit\npenalty before `min_lock_days`; `withdrawal_window_days` is never greater than\n`min_lock_days`.\n","oneOf":[{"type":"object","required":["kind","min_lock_days","withdrawal_window_days","early_exit_penalty_bps"],"properties":{"kind":{"const":"fixed_lockup"},"min_lock_days":{"type":"integer","minimum":0},"withdrawal_window_days":{"type":"integer","minimum":0},"early_exit_penalty_bps":{"type":"integer","minimum":0,"maximum":10000},"maturity_at":{"type":["string","null"],"format":"date-time"}},"additionalProperties":false},{"type":"object","required":["kind"],"properties":{"kind":{"const":"withdrawal_queue"},"expected_queue_days":{"type":"integer","minimum":0},"queue_position":{"type":"integer","minimum":0}},"additionalProperties":false},{"type":"null"}]}},"additionalProperties":false},"VaultDepositState":{"type":"string","description":"Current vault deposit state. If it is `failed`, give the deposit ID to your operator for diagnosis.","enum":["initial","awaiting_funding","funded","settling","consumed_by_lockup","completed","cancelled","failed"]},"VaultWithdrawalState":{"type":"string","description":"Current vault withdrawal state. If it is `failed`, give the withdrawal ID to your operator for diagnosis.","enum":["initial","processing","completed","cancelled","failed"]},"OnrampState":{"type":"string","description":"Current inbound-transfer state. If it is `failed`, give the transfer ID to your operator for diagnosis.","enum":["pending","waiting_for_deposit","processing","processed","failed","cancelled"]},"OfframpState":{"type":"string","description":"Current outbound-transfer state. If it is `failed`, give the transfer ID to your operator for diagnosis.","enum":["pending","intermediate_credentials_set","waiting_for_crypto_transfer_approval","crypto_transfer_in_progress","crypto_transfer_completed","funds_sent","failed","cancelled"]},"PositiveDecimalString":{"type":"string","pattern":"^(0\\.[0-9]*[1-9][0-9]*|[1-9][0-9]*(\\.[0-9]+)?)$","maxLength":60,"description":"A positive decimal string used for high-precision crypto amounts and provider-derived FX rates where JSON numbers cannot preserve enough precision."},"CryptoCurrencyCode":{"type":"string","pattern":"^[A-Z0-9]{3,12}$","description":"Uppercase token symbol used by `crypto_currency` fields, with 3–12 letters or digits."},"Onramp":{"type":"object","description":"An inbound bank transfer. At least one complete fiat or crypto amount pair is present.","required":["id","state","payment_intent_id","fiat_amount","fiat_currency","crypto_amount","crypto_currency","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"$ref":"#/components/schemas/OnrampState"},"payment_intent_id":{"type":["string","null"],"format":"uuid","description":"Payment ID created for this transfer, or `null` until one exists."},"fiat_amount":{"oneOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}],"description":"The fiat amount in the currency's smallest unit."},"fiat_currency":{"oneOf":[{"$ref":"#/components/schemas/CurrencyCode"},{"type":"null"}]},"crypto_amount":{"oneOf":[{"$ref":"#/components/schemas/PositiveDecimalString"},{"type":"null"}],"description":"The crypto amount as a decimal string that preserves precision."},"crypto_currency":{"oneOf":[{"$ref":"#/components/schemas/CryptoCurrencyCode"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"additionalProperties":false,"anyOf":[{"properties":{"fiat_amount":{"$ref":"#/components/schemas/Amount"},"fiat_currency":{"$ref":"#/components/schemas/CurrencyCode"}},"required":["fiat_amount","fiat_currency"]},{"properties":{"crypto_amount":{"$ref":"#/components/schemas/PositiveDecimalString"},"crypto_currency":{"$ref":"#/components/schemas/CryptoCurrencyCode"}},"required":["crypto_amount","crypto_currency"]}]},"Offramp":{"type":"object","description":"An outbound bank transfer. At least one complete fiat or crypto amount pair is present.","required":["id","state","payment_intent_id","fiat_amount","fiat_currency","crypto_amount","crypto_currency","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"$ref":"#/components/schemas/OfframpState"},"payment_intent_id":{"type":["string","null"],"format":"uuid","description":"Payment ID created for this transfer, or `null` until one exists."},"fiat_amount":{"oneOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}],"description":"The fiat amount in the currency's smallest unit."},"fiat_currency":{"oneOf":[{"$ref":"#/components/schemas/CurrencyCode"},{"type":"null"}]},"crypto_amount":{"oneOf":[{"$ref":"#/components/schemas/PositiveDecimalString"},{"type":"null"}],"description":"The crypto amount as a decimal string that preserves precision."},"crypto_currency":{"oneOf":[{"$ref":"#/components/schemas/CryptoCurrencyCode"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"additionalProperties":false,"anyOf":[{"properties":{"fiat_amount":{"$ref":"#/components/schemas/Amount"},"fiat_currency":{"$ref":"#/components/schemas/CurrencyCode"}},"required":["fiat_amount","fiat_currency"]},{"properties":{"crypto_amount":{"$ref":"#/components/schemas/PositiveDecimalString"},"crypto_currency":{"$ref":"#/components/schemas/CryptoCurrencyCode"}},"required":["crypto_amount","crypto_currency"]}]},"VaultDeposit":{"type":"object","description":"A vault deposit with the submitted amount and the vault tokens credited.","required":["id","vault_id","state","amount","token_amount","funded_at","completed_at","created_at"],"properties":{"id":{"type":"string","description":"Vault deposit request ID."},"vault_id":{"type":"string","format":"uuid"},"state":{"$ref":"#/components/schemas/VaultDepositState"},"amount":{"$ref":"#/components/schemas/Amount"},"token_amount":{"$ref":"#/components/schemas/Amount","description":"Vault tokens credited using the vault's exchange rate."},"funded_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"VaultWithdrawal":{"type":"object","description":"A vault withdrawal with the requested amount and final token amount. The final\namount can be lower when an early-exit penalty applies.\n","required":["id","vault_id","state","amount","token_amount","actual_token_amount","completed_at","created_at"],"properties":{"id":{"type":"string","description":"Vault withdrawal request ID."},"vault_id":{"type":"string","format":"uuid"},"state":{"$ref":"#/components/schemas/VaultWithdrawalState"},"amount":{"$ref":"#/components/schemas/Amount"},"token_amount":{"$ref":"#/components/schemas/Amount"},"actual_token_amount":{"oneOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}],"description":"Final token amount after any early-exit penalty, or `null` while processing."},"completed_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"OnrampEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/Onramp"}},"additionalProperties":false},"OfframpEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/Offramp"}},"additionalProperties":false},"VaultDepositEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/VaultDeposit"}},"additionalProperties":false},"VaultWithdrawalEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/VaultWithdrawal"}},"additionalProperties":false},"VaultDepositAcceptedEnvelope":{"type":"object","description":"Accepted vault deposit request.","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["id","state"],"properties":{"id":{"type":"string","description":"Deposit request ID. Pass it unchanged to `GET /vaults/{vault_id}/deposits/{deposit_id}`."},"state":{"$ref":"#/components/schemas/VaultDepositState"}},"additionalProperties":false}},"additionalProperties":false},"VaultWithdrawalAcceptedEnvelope":{"type":"object","description":"Accepted vault withdrawal request.","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["id","state"],"properties":{"id":{"type":"string","description":"Withdrawal request ID. Pass it unchanged to `GET /vaults/{vault_id}/withdrawals/{withdrawal_id}`."},"state":{"$ref":"#/components/schemas/VaultWithdrawalState"}},"additionalProperties":false}},"additionalProperties":false},"Payment":{"type":"object","description":"A payment record. At least one complete fiat or crypto amount pair is present.","required":["id","state","source_kind","fiat_amount","fiat_currency","crypto_amount","crypto_currency","trade_id","created_at","updated_at","settled_at","failed_at"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["created","awaiting_approval","processing","settled","failed","withdrawn","rejected"],"description":"Current payment state. If it is `failed` or `rejected`, give the payment ID to your operator for diagnosis."},"source_kind":{"type":"string","enum":["trade","wallet_transfer","onramp_request","offramp_request","vault_deposit_request","vault_withdrawal_request"],"description":"Origin of the payment. Clients must tolerate new values."},"fiat_amount":{"oneOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}],"description":"The fiat amount in the currency's smallest unit."},"fiat_currency":{"oneOf":[{"$ref":"#/components/schemas/CurrencyCode"},{"type":"null"}]},"crypto_amount":{"oneOf":[{"$ref":"#/components/schemas/PositiveDecimalString"},{"type":"null"}],"description":"The crypto amount as a decimal string that preserves precision."},"crypto_currency":{"oneOf":[{"$ref":"#/components/schemas/CryptoCurrencyCode"},{"type":"null"}]},"trade_id":{"type":["string","null"],"format":"uuid","description":"Trade settled by this payment. Present only when `source_kind` is `trade`."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"settled_at":{"type":["string","null"],"format":"date-time"},"failed_at":{"type":["string","null"],"format":"date-time"}},"additionalProperties":false,"anyOf":[{"properties":{"fiat_amount":{"$ref":"#/components/schemas/Amount"},"fiat_currency":{"$ref":"#/components/schemas/CurrencyCode"}},"required":["fiat_amount","fiat_currency"]},{"properties":{"crypto_amount":{"$ref":"#/components/schemas/PositiveDecimalString"},"crypto_currency":{"$ref":"#/components/schemas/CryptoCurrencyCode"}},"required":["crypto_amount","crypto_currency"]}],"allOf":[{"if":{"properties":{"source_kind":{"const":"trade"}},"required":["source_kind"]},"then":{"properties":{"trade_id":{"type":"string","format":"uuid"}},"required":["trade_id"]},"else":{"properties":{"trade_id":{"type":"null"}}}}]},"Balance":{"type":"object","description":"Settled balance for one treasury account and currency.","required":["account_id","balance","currency","last_settled_at"],"properties":{"account_id":{"type":"string","description":"Treasury account identifier."},"balance":{"$ref":"#/components/schemas/Amount"},"currency":{"$ref":"#/components/schemas/StablecoinCurrencyCode"},"last_settled_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"Listing":{"type":"object","description":"A marketplace listing available to your organisation.","required":["id","state","unit_price","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["draft","published","paused","archived"],"description":"Current listing state."},"unit_price":{"type":"object","description":"Price per listed unit.","required":["minor_units","currency"],"properties":{"minor_units":{"$ref":"#/components/schemas/Amount"},"currency":{"$ref":"#/components/schemas/CurrencyCode"}},"additionalProperties":false},"created_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"Offer":{"type":"object","description":"An offer made against a marketplace listing.","required":["id","listing_id","state","offered_price","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"listing_id":{"type":"string","format":"uuid","description":"Listing identifier returned by `GET /listings`."},"state":{"type":"string","enum":["pending","accepted","rejected","withdrawn"],"description":"Current offer state."},"offered_price":{"type":"object","description":"Offered unit price.","required":["minor_units","currency"],"properties":{"minor_units":{"$ref":"#/components/schemas/Amount"},"currency":{"$ref":"#/components/schemas/CurrencyCode"}},"additionalProperties":false},"created_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"TradeEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/Trade"}},"additionalProperties":false},"PaymentEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/Payment"}},"additionalProperties":false},"OfferEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/Offer"}},"additionalProperties":false},"TradePage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Trade"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"InvoicePage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"PaymentPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"ListingPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Listing"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"OfferPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Offer"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"OnrampPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Onramp"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"FxQuotePage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/FxQuote"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"OfframpPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Offramp"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"VaultDepositPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/VaultDeposit"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"VaultWithdrawalPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/VaultWithdrawal"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"VaultPage":{"type":"object","required":["ok","data","page"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Vault"}},"page":{"$ref":"#/components/schemas/PageMeta"}},"additionalProperties":false},"BalanceList":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Balance"}}},"additionalProperties":false},"CreateFxQuoteRequest":{"type":"object","description":"The caller selects a registered stablecoin-to-stablecoin currency pair and a strictly\npositive source amount. Rate, target amount, fee, provider, tenant identity and expiry\nare all server-derived.\n","required":["from_currency","to_currency","amount"],"properties":{"from_currency":{"$ref":"#/components/schemas/StablecoinCurrencyCode"},"to_currency":{"$ref":"#/components/schemas/StablecoinCurrencyCode"},"amount":{"$ref":"#/components/schemas/PositiveAmount"}},"additionalProperties":false},"FxQuoteState":{"type":"string","description":"The persisted quote lifecycle state. A mirror, not a definition.","enum":["active","consumed","expired"]},"FxQuote":{"type":"object","description":"A short-lived, provider-derived foreign-exchange quote. Provider identity and its\nopaque locked-rate handle are deliberately not published.\n","required":["id","from_amount","from_currency","to_amount","to_currency","rate_decimal","fee_amount","fee_currency","expires_at","state"],"properties":{"id":{"type":"string","format":"uuid"},"from_amount":{"$ref":"#/components/schemas/PositiveAmount"},"from_currency":{"$ref":"#/components/schemas/CurrencyCode"},"to_amount":{"$ref":"#/components/schemas/PositiveAmount"},"to_currency":{"$ref":"#/components/schemas/CurrencyCode"},"rate_decimal":{"$ref":"#/components/schemas/PositiveDecimalString"},"fee_amount":{"$ref":"#/components/schemas/SignedMinorAmount"},"fee_currency":{"$ref":"#/components/schemas/CurrencyCode"},"expires_at":{"type":"string","format":"date-time"},"state":{"$ref":"#/components/schemas/FxQuoteState"}},"additionalProperties":false},"FxQuoteEnvelope":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/FxQuote"}},"additionalProperties":false},"CreateOfferRequest":{"type":"object","description":"Offers bind the full listing quantity; quantity is not caller-selectable. The\noffered currency must equal the parent listing's currency, and an organisation\ncannot offer on its own listing. Violating either is rejected permanently with 409\n`conflict`, so the request must not be replayed unchanged.\n","required":["listing_id","offered_price"],"properties":{"listing_id":{"type":"string","format":"uuid","description":"Listing identifier returned by `GET /listings`."},"offered_price":{"type":"object","description":"Offered unit price. Offer creation accepts fiat currency codes only.","required":["minor_units","currency"],"properties":{"minor_units":{"$ref":"#/components/schemas/PositiveAmount"},"currency":{"type":"string","pattern":"^[A-Z]{3}$"}},"additionalProperties":false}},"additionalProperties":false},"SendPaymentRequest":{"type":"object","description":"`destination_id` is the live money-authorization binding to the caller's approved\n`ApiClientDestination`. For this operation its `counterparty_org` destination reference\nis passed directly to the payment wrapper. A raw bank account or wallet address is\ndeliberately not accepted.\n","required":["destination_id","amount","currency"],"properties":{"destination_id":{"type":"string","format":"uuid","description":"Destination identifier approved by your organisation owner in Settings → API clients."},"amount":{"$ref":"#/components/schemas/PositiveAmount"},"currency":{"$ref":"#/components/schemas/CurrencyCode"},"purpose_of_payment_code":{"type":"string","description":"Optional payment-purpose classification. Your operator will tell you if a corridor requires it.","enum":["agri_goods_export","agri_goods_import","advance_payment","service_fee","intra_group_transfer","other"]}},"additionalProperties":false},"CreateOnrampRequest":{"type":"object","description":"Transfer funds from an operator-supplied funding account (source_id) into your Loam balance.","required":["source_id","amount","currency"],"properties":{"source_id":{"type":"string","format":"uuid","description":"Operator-supplied funding account identifier (source_id). Currency must equal the currency of the source_id account; otherwise the response is 403 forbidden."},"amount":{"$ref":"#/components/schemas/PositiveAmount","description":"The amount to add, expressed in the currency's smallest unit."},"currency":{"$ref":"#/components/schemas/CurrencyCode","description":"Currency must equal the currency of the source_id account; otherwise the response is 403 forbidden."}},"additionalProperties":false},"CreateOfframpRequest":{"type":"object","description":"Not yet available. Transfer funds from your Loam balance to an approved bank account once destination screening and travel-rule certification are complete.","required":["destination_id","amount","currency"],"properties":{"destination_id":{"type":"string","format":"uuid","description":"Reserved bank destination identifier for off-ramp transfers. Not yet usable. Off-ramp creation remains closed until destination screening and travel-rule certification are complete."},"amount":{"$ref":"#/components/schemas/PositiveAmount","description":"The amount to send, expressed in the currency's smallest unit."},"currency":{"$ref":"#/components/schemas/CurrencyCode"}},"additionalProperties":false},"CreateVaultDepositRequest":{"type":"object","description":"Amount to deposit, using the selected vault's currency.","required":["amount"],"properties":{"amount":{"$ref":"#/components/schemas/PositiveAmount","description":"The amount to deposit in the vault currency's smallest unit."}},"additionalProperties":false},"CreateVaultWithdrawalRequest":{"type":"object","description":"Amount to withdraw, using the selected vault's currency.","required":["amount"],"properties":{"amount":{"$ref":"#/components/schemas/PositiveAmount","description":"The amount to withdraw in the vault currency's smallest unit."}},"additionalProperties":false}}}}