Customers who hold a Global Account must be KYC/KYB verified before any account funds can move from or to fiat rails. This quickstart picks up after KYC is complete.In sandbox, customers are automatically KYC approved on creation so you can skip straight to account setup.
You also need:
A platform configured with USDB in its supported currencies. In sandbox, USDB is enabled by default alongside USD and USDC.
Sandbox or production API credentials with access to the Embedded Wallet Auth and Internal Accounts endpoints.
The walkthrough below is the happy path: create a customer, find the auto-provisioned account and its default email OTP credential, fund it, and withdraw to a bank account. Each step shows the HTTP request your integrator backend makes on behalf of the client.
Create the customer record. A Global Account is provisioned automatically whenever a customer is created on a platform that has USDB in its supported currencies — you don’t need to pass it on the customer.
Response:201 Created with the new Customer:... id. In sandbox, the customer is KYC-approved immediately; in production you would now run them through the KYC / KYB flow before any funds can move.
When a customer is created on a USDB-enabled platform, Grid automatically provisions a Global Account alongside their other internal accounts. Fetch it by filtering the customer’s internal accounts by type=EMBEDDED_WALLET.
curl -X GET "$GRID_BASE_URL/internal-accounts?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001&type=EMBEDDED_WALLET" \ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
Global Accounts are initialized with an EMAIL_OTP credential tied to the customer email on file. Fetch the auth methods for the account and keep the AuthMethod:... id for the signing step later in this walkthrough.
curl -X GET "$GRID_BASE_URL/auth/credentials?accountId=InternalAccount:019542f5-b3e7-1d02-0000-000000000002" \ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
You can add passkeys or OAuth credentials later, but adding credentials is itself a signed action. Start with the default email OTP credential to mint the first session signing key.
Global Accounts behave like any other internal account on the way in — incoming funds do not need the customer’s signature. In sandbox, use the sandbox funding endpoint to skip straight to a funded state:
amount is in the smallest unit of the account’s currency. USDB has 6 decimals, so 1000000000 is 1,000.00 USDB.You will receive an INCOMING_PAYMENT webhook when the balance updates. The account now holds 1,000.00 USDB.
To fund from another currency (USD ACH, USDC on-chain, etc.), create a quote with destination.destinationType: "ACCOUNT" pointing at the Global Account’s InternalAccount id. The quote’s sourceCurrency can be any supported platform currency; Grid will convert into USDB on execute.
Create a quote with the Global Account as the source. Grid returns a payloadToSign in the quote’s payment instructions — this is what the client will sign to authorize the transfer.
lockedCurrencyAmount is in the smallest unit of the locked side’s currency. Here the sending currency is USDB (6 decimals), so 10000000 is 10.00 USDB.Response:
The customer has an outstanding quote with a payloadToSign. Now we need a session signing key to sign it with. The flow is keypair → OTP challenge → verify → decrypt → sign.
1
Your backend requests a fresh OTP
Ask Grid to send a fresh OTP email for the default EMAIL_OTP credential.
curl -X POST "$GRID_BASE_URL/auth/credentials/AuthMethod:019542f5-b3e7-1d02-0000-000000000001/challenge" \ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
The client generates a fresh P-256 client key pair and posts the public key plus the OTP value to your backend. Grid uses the public key to seal the session signing key to that device.
3
Your backend verifies the OTP with Grid to mint a session
Return encryptedSessionSigningKey and expiresAt to the client.
4
Client decrypts the session signing key and stamps the payload
The client decryptsencryptedSessionSigningKey with the matching client private key, then stamps the quote’s payloadToSign with the resulting session signing key. Return the full Turnkey API-key stamp to your backend.
Stamp the payloadToSign bytes exactly as Grid returned them. Do not parse, re-serialize, trim, or normalize the JSON — the stamp must cover the same bytes Grid’s verifier hashes.
The session signing key is now valid for 15 minutes, so subsequent account actions within that window (for example, a second withdrawal) can reuse it without another /challenge + /verify round-trip.