Skip to main content
OMS gives you a single API for moving money between fiat and stablecoins. This guide takes you from zero to a working transaction in five steps.
1

Request access and authenticate

OMS is in early access. Start by requesting access from the dashboard.

Request OMS access

Submit your details to get sandbox credentials.
Once approved, open the OMS Dashboard and navigate to API Keys. Generate a new key and store the secret immediately, it is shown only once. Keys do not expire by default, support an optional enforced expiration, and can be rotated from the dashboard at any time.
Treat your API key secret like a password. If it is ever compromised, revoke the key from the dashboard and generate a new one immediately.
You do not send the API key directly on requests. Exchange the key and secret for a short-lived bearer token at POST /auth/token, then send that token on every other call.
curl -X POST https://sandbox-api.polygon.technology/v0.10/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "{api_key}",
    "apiSecret": "{api_secret}"
  }'
curl -X POST https://api.polygon.technology/v0.10/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "{api_key}",
    "apiSecret": "{api_secret}"
  }'
{
  "accessToken": "eyJhbGc...",
  "tokenType": "bearer",
  "expiresIn": 3600,
  "expiresAt": "2026-01-15T11:00:00Z"
}
The token is valid for 60 minutes. Send the accessToken as a bearer token on every other request:
Authorization: Bearer {accessToken}
Every mutating request (POST and PATCH) also requires an Idempotency-Key header. Replaying the same key returns the original result instead of re-executing.
When a request returns 401, the token has expired. Exchange your key for a fresh one and retry. If POST /auth/token returns 429, the endpoint is rate-limited: back off before retrying using the Retry-After header.
2

Create a customer

Every wallet, transaction, and payment route in OMS belongs to a customer record. Create one before anything else. To onboard a customer who can move USD or use cash services, send the full set of identifying fields, not just a name, and request the endorsements the customer needs.
curl -X POST https://sandbox-api.polygon.technology/v0.10/customers \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cst-first-customer-001" \
  -d '{
    "type": "individual",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phone": "+12125551234",
    "birthDate": "1990-05-15",
    "nationality": "US",
    "residentialAddress": {
      "line1": "123 Main St",
      "city": "New York",
      "state": "NY",
      "country": "US",
      "zipCode": "10001"
    },
    "identifyingInformation": [
      { "type": "ssn", "issuingCountry": "US", "number": "123-45-6789" }
    ],
    "endorsements": ["basic", "cryptoCustody", "usd"]
  }'
curl -X POST https://api.polygon.technology/v0.10/customers \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cst-first-customer-001" \
  -d '{
    "type": "individual",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phone": "+12125551234",
    "birthDate": "1990-05-15",
    "nationality": "US",
    "residentialAddress": {
      "line1": "123 Main St",
      "city": "New York",
      "state": "NY",
      "country": "US",
      "zipCode": "10001"
    },
    "identifyingInformation": [
      { "type": "ssn", "issuingCountry": "US", "number": "123-45-6789" }
    ],
    "endorsements": ["basic", "cryptoCustody", "usd"]
  }'
{
  "id": "cst_01H9Xa...",
  "object": "customer",
  "type": "individual",
  "status": "active",
  "endorsements": [
    { "name": "basic", "status": "ACTIVE" },
    { "name": "cryptoCustody", "status": "ACTIVE" },
    { "name": "usd", "status": "PENDING" }
  ],
  "wallets": [],
  "createdAt": "2026-01-15T10:00:00Z"
}
Store the cst_ ID; you pass it to every wallet, quote, and transaction. Each endorsement tracks its own status in SCREAMING_CASE and must reach ACTIVE before its capability unlocks. PII fields (birthDate, residentialAddress, ipAddress, identifyingInformation) are write-only: OMS accepts them but never returns them.
The API accepts a customer with only type, but a customer created without the identifying fields below cannot be provisioned to move fiat. The record is created, yet calls that need a provisioned fiat account (cash-in or a fiat transaction) fail. For USD and cash flows, always provide:
  • A structured residentialAddress (the object above, not a free-text string)
  • phone in E.164 format
  • birthDate
  • A government ID in identifyingInformation (for US customers, an ssn or itin)
Supply these at creation, or add them later with PATCH /customers/{customerId}. Products that never touch fiat rails may not need them. Only individual is supported for type today.
In sandbox, endorsements are auto-approved so you can test without a live KYC integration. Provisioning still reads the identifying fields above, so include them in sandbox too.
3

Provision a wallet

Create a custodial wallet for the customer. The path carries the customer ID; the body names the asset and chain to hold. OMS derives the on-chain address and manages the keys, with no wallet SDK or user signing.
curl -X POST https://sandbox-api.polygon.technology/v0.10/customers/cst_01H9Xa.../wallets \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: wlt-first-wallet-001" \
  -d '{
    "asset": "usdc",
    "chain": "polygon"
  }'
curl -X POST https://api.polygon.technology/v0.10/customers/cst_01H9Xa.../wallets \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: wlt-first-wallet-001" \
  -d '{
    "asset": "usdc",
    "chain": "polygon"
  }'
{
  "id": "wlt_01H9Xb...",
  "object": "wallet",
  "customerId": "cst_01H9Xa...",
  "type": "internal",
  "status": "active",
  "asset": "usdc",
  "chain": "polygon",
  "address": "0xBEEF4a2c891D56e72b67a3f21d0cf94F1D7c5911",
  "blockchainAsset": {
    "protocol": "evm",
    "chainId": "137",
    "tokenId": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359"
  },
  "createdAt": "2026-01-15T10:01:00Z"
}
The address is the on-chain address. The wlt_ ID is what you pass as the source or destination in quotes and transactions. Read the current balance with GET /wallets/{walletId}/balance.
4

Run your first transaction

The cash-in flow is the quickest path for your first run: it needs no external account. The bank transfer flow shows the standard quote-to-transaction pattern for fiat payouts.
Let a customer deposit physical cash at a retail location and receive USDC in their wallet.
curl -X POST https://sandbox-api.polygon.technology/v0.10/cash-ins \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ci-first-001" \
  -d '{
    "customerId": "cst_01H9Xa...",
    "cash": {
      "locationId": "loc_01H9Xd...",
      "locationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9..."
    },
    "source": {
      "asset": "usd",
      "indicatedAmount": "100.00"
    },
    "destination": {
      "asset": "usdc",
      "network": "polygon",
      "wallet": { "id": "wlt_01H9Xb..." }
    }
  }'
curl -X POST https://api.polygon.technology/v0.10/cash-ins \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ci-first-001" \
  -d '{
    "customerId": "cst_01H9Xa...",
    "cash": {
      "locationId": "loc_01H9Xd...",
      "locationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9..."
    },
    "source": {
      "asset": "usd",
      "indicatedAmount": "100.00"
    },
    "destination": {
      "asset": "usdc",
      "network": "polygon",
      "wallet": { "id": "wlt_01H9Xb..." }
    }
  }'
OMS returns a depositInstructions.code valid for one hour. The customer presents the code at the retail location, hands over cash, and USDC lands in their wallet automatically.See the Cash-in guide for the full flow.
5

Configure webhooks

OMS fires webhooks at every meaningful state change. You can poll GET /transactions/{transactionId} instead, but webhooks are strongly recommended for production.Register an endpoint with POST /webhooks (or in the OMS Dashboard under Webhooks). OMS returns a signing secret with the whsec_ prefix once in the create response, so store it immediately.
curl -X POST https://sandbox-api.polygon.technology/v0.10/webhooks \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: whk-first-001" \
  -d '{
    "url": "https://api.yourapp.com/webhooks/oms",
    "events": []
  }'
curl -X POST https://api.polygon.technology/v0.10/webhooks \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: whk-first-001" \
  -d '{
    "url": "https://api.yourapp.com/webhooks/oms",
    "events": []
  }'
Pass an empty events array (or ["*"] / ["ALL"]) to subscribe to every event, or list specific event names to filter. Manage endpoints with GET /webhooks, PATCH /webhooks/{id} (set enabled: false to pause), and DELETE /webhooks/{id}. Every event carries the full resource object under payload, so you rarely need to poll for additional data.Some events you will see early on:
EventFires when
transaction.fiatToCrypto.completedA fiat-funded transaction delivered crypto to the destination
transaction.cryptoToFiat.completedA payout from a wallet delivered fiat to the destination
cashIn.completedA cash deposit was received and converted
externalAccount.verifiedA registered bank account passed validation and is usable on quotes
See Webhook events for the envelope and the full catalog.
Verify every webhook with the Webhook-Signature header before acting on it. The signature is an HMAC-SHA256 keyed with your signing secret; compare it in constant time and reject events with a stale timestamp.

What’s next

Cash-in

Full walkthrough of the cash deposit flow, including deposit code generation and retail location selection.

Bank transfers

Move money between bank accounts and wallets in both directions using ACH and card rails.

Payments overview

How OMS handles payments, stablecoin settlement, and compliant fiat access end to end.

API reference

Complete endpoint reference for all OMS resources.