Before you start: the OMS API is in early access. Every endpoint, including the ones in this guide, requires an early-access API key. Request access before you begin.Authenticate by exchanging your API key and secret for a bearer token at
POST /auth/token, then send it as Authorization: Bearer {accessToken} on every request. Every POST and PATCH also requires an Idempotency-Key header. See Get started for the full flow.Prerequisites
- A customer with a
cst_ID and theusdendorsement: the payout is funded from this customer’s wallet. - A funded OMS wallet with a
wlt_ID holding enough USDC to cover the payout. - The recipient’s details: their legal name, and their bank account information.
Step 1: Create the counterparty
POST /counterparties requires only the owning customerId and the recipient’s name. The identity fields are optional but improve compliance screening: entityType (individual or business), email, phone, dateOfBirth, taxId, nationality, and an address.
Request
address shape is streetAddress, city, postalCode, and country (required when an address is supplied), plus an optional countryArea for the state or region.
Response, 201 Created
ctp_ ID. A counterparty that fails compliance screening comes back rejected with a rejectionReason; only active counterparties can own external accounts.
Step 2: Register the counterparty’s bank account
Register the recipient’s bank withPOST /external-accounts, setting the owner to the counterparty. The per-type detail object must match the type: bankUs for US accounts, bankIban for international IBAN accounts, or bankCanada for Canadian accounts.
Request
Response, 201 Created
accountNumberLast4. The account starts pending and flips to active (usable on quotes) or failed. Wait for active before quoting against it.
Step 3: Create the quote
The quote is identical to any other bank payout: thesource is the customer’s OMS wallet, and the destination is the counterparty’s registered bank account referenced by its ext_bankUs_ ID.
party block, so you can render who is being paid without extra reads:
pricing object. The direction is inferred as cryptoToFiatAccount.
Step 4: Execute and track
Accept the quote withPOST /transactions and the quoteId:
processing and moves to completed when the bank payout settles, or failed with an error object. The payout leg surfaces granular progress in subStatus: processing.awaitingFiatOut while the payout is queued, then processing.fiatOut once it is in flight. Poll GET /transactions/{transactionId} or subscribe to transaction.cryptoToFiat.completed (and transaction.cryptoToFiat.failed); see the webhook events catalog for the full list.
To reconcile a payout run, filter GET /transactions?customerId=...: each transaction’s destination party carries the counterpartyId it paid.
Payouts are sent from named accounts: the recipient’s bank statement shows the paying customer’s own legal-entity name as the sender, not Polygon and not your platform.
Managing counterparties
GET /counterparties?customerId=...lists a customer’s counterparties (customerIdis required). Paginate withlimit,startingAfter, andendingBefore.GET /counterparties/{counterpartyId}fetches one by ID.PATCH /counterparties/{counterpartyId}partially updates identity fields; omitted fields are unchanged.DELETE /counterparties/{counterpartyId}soft-deletes. It returns409while the counterparty still owns active external accounts: delete those accounts first, then delete the counterparty.
Related
- B2B payouts: running payouts to many recipients
- Bank transfers: rails, per-type bank fields, and registration details
- External accounts: the full registration and lifecycle model
- Crypto to fiat: the underlying quote and transaction flow