https://sandbox-api.polygon.technology/v0.13, so no real money moves.
You need curl and sandbox API credentials. The same requests work in production against https://api.polygon.technology/v0.13 with production credentials.
1
Get sandbox credentials
OMS is in early access. Request access to receive sandbox credentials.Once approved, open the OMS Dashboard and go to API Keys. Generate a secret key and copy both the key (it starts with
Request OMS access
Submit your details to get sandbox credentials.
sk_sdbx_) and its secret. The secret is shown only once.2
Exchange your key for a bearer token
You never send the API key on ordinary requests. Exchange the key and secret for a bearer token:Notice that Every other
projectMode is sandbox. The token is valid for 60 minutes. Send it on every other request in this tutorial:POST in this tutorial also needs an Idempotency-Key header. Use a new UUID for each new request, and send the same key again only to retry that exact request.If a later request returns
401, your token has expired. Run this step again and continue. If POST /auth/token returns 429, wait for the number of seconds in the Retry-After header.3
Create a customer
Every wallet, quote, and transaction belongs to a customer. Create an individual customer with the identifying details OMS needs to provision a wallet and accept cash:You get back the customer with Copy the
201:cst_ ID; you use it in every remaining step. The birthDate, residentialAddress, and identifyingInformation you sent are write-only, so they never appear in responses. Sandbox runs the same onboarding checks as production, so wait until the customer’s status is active before you continue (poll GET /customers/{customerId} or listen for the customer.* webhooks). See Sandbox and testing if a check rejects your data.If the response is 202 with "status": "processing" instead, onboarding is still running. Wait a few seconds, then send the identical request with the same Idempotency-Key. You get 202 again while it runs and 201 with the customer once it is done.If the request fails with 400, read the cause field in the error body for the specific reason, and quote the response’s Request-Id header if you contact support. Fields the API does not recognize are ignored rather than rejected, so check spelling carefully. For business customers and the full onboarding lifecycle, see Customer onboarding.4
Create a USDC wallet
Give the customer a custodial wallet that holds USDC on Polygon. OMS manages the keys, so there is nothing for the customer to sign.Copy the
wlt_ ID. In sandbox the address lives on Polygon Amoy, the Polygon testnet.If the response is 202 instead, the wallet is still being provisioned. Poll the URL in the Location header (GET /wallets/operations/{operationId}) until its status is complete, then take the wallet ID from walletId.5
Create a cash-in
Now fund the wallet with cash. First find a retail location that accepts cash deposits:Use the cash The
provider value enabled for your project. From the results, pick a location with buyAllowed: true and copy its id (loc_...) and cashLocationReference.Create the cash-in. The customer will deposit about $100.00, and the USDC goes to the wallet you just created:cashInCode is what a real customer would show at the counter before expiresAt. The pricing amounts are estimates until cash is actually deposited. Copy the ci_ ID and the cashInCode.6
Simulate the cash deposit
In sandbox, two calls stand in for the customer at the counter. First, present the code:The response carries a OMS now treats the cash as received and creates a transaction that converts it to USDC and delivers it to the wallet.
confirmationId. Pass it to hand over the cash:7
Watch the transaction complete
Read the cash-in again:Notice that it now has a The transaction’s
transactionId (txn_...) and a status of processing or completed. Read that transaction:precursor is { "type": "cashIn", "id": "ci_01H9Xc..." }. Its status moves from processing to completed, and subStatus shows the step it is on, such as processing.initiated or completed.settled. Repeat the read every few seconds until it reaches completed.Finally, read the wallet with GET /wallets/wlt_01H9Xb.... The balances entry for usdc now shows the deposit.You have authenticated, onboarded a customer, provisioned a wallet, and completed a cash-to-crypto transaction.8
Receive webhooks instead of polling
Polling works for a first run. In your application, let OMS tell you when things change. Register a public HTTPS endpoint:The response contains
webhook and a signingKey. Store the signingKey now. Later reads do not return it. ["*"] subscribes to every event. Run another cash-in and your endpoint receives events such as these:Each event’s
data.resource is the full resource as a GET returns it, so you rarely need to read it again. Before acting on an event, verify its Webhook-Signature header (t=<timestamp>,v1=<signature>): compute HMAC-SHA256 with your signingKey over <t>.<raw body>, compare in constant time, and reject events whose timestamp is more than five minutes old. See Receiving webhooks for a full handler and Webhook events for the catalog.What’s next
Crypto to fiat
Register a bank account, quote, and pay out from the wallet to the customer’s bank.
Cash-in
Location search, code refresh, expiry, and the rest of the cash deposit flow.
Fiat to crypto
Fund wallets from bank transfers and virtual accounts.
API reference
Core concepts and the full endpoint reference.