Why an Embedded Wallet?
- Self-custody. Grid never has unilateral access to move user funds, and neither do you. The customer’s device is the only party that can authorize a transaction.
- Stablecoin-denominated. Balances are held as stablecoins like Brale-issued USDB. Use the standard
/quotesAPI to convert in from fiat or out to any supported Grid bank-account rail (ACH, PIX, CLABE, UPI, IBAN, UMA, …). - Grid-native. You reuse the customer, internal-account, quote, transaction, and webhook primitives you already integrated for Payouts or P2P. The only thing that’s new is an auth + signing layer at the wallet.
- Built on Bitcoin. Embedded wallets run on Spark, a Lightning-compatible Bitcoin L2 that supports instant, low-fee Bitcoin and Stablecoin transfers. You get the benefits of running on Bitcoin, the most neutral, decentralized, and secure network for money.
Payment flow
Embedded Wallets ride on the same/quotes + /quotes/{id}/execute pattern as every other Grid payment. The only thing that’s different is that outbound transfers need a client signature.
- Incoming funds. Funding a wallet works like any other internal account. Create a quote with the Embedded Wallet as the
destination, execute it, and Grid converts the source currency into USDB and credits the wallet. No customer approval needed — incoming value is passive. - Outgoing funds. Withdrawals and transfers out require the customer to authorize them on their device. Grid returns a
payloadToSignin the quote’spaymentInstructions; the client signs those bytes with its session signing key and passes the base64 signature as theGrid-Wallet-Signatureheader on/quotes/{id}/execute. Only then does Grid release the funds.
Architecture
Three parties participate in every signed action:| Party | Role |
|---|---|
| Client | The customer’s device (browser, iOS app, or Android app). Generates the client key pair, runs WebAuthn, decrypts the session signing key, and signs outbound requests. |
| Integrator backend | Your server. Holds your Grid API credentials, brokers every call to Grid on behalf of the client, and issues WebAuthn challenges for initial passkey registration. |
| Grid | Verifies auth credentials, issues session signing keys (encrypted to the client’s public key), and enforces that every wallet action is authorized. |
Auth credentials, client keys, and session signing keys
Three distinct pieces of crypto collaborate to authorize actions on the Embedded Wallet (withdrawals, credential changes, session revocations, and wallet exports):| Piece | Where it lives | How long it lives | What it proves |
|---|---|---|---|
| Auth credential — passkey, OIDC token, or email OTP | Registered on the wallet; the passkey itself lives on the authenticator, OIDC on your IdP, OTP in the user’s inbox | Until the customer revokes it | ”I am the human who owns this wallet.” Used to authenticate the user at the start of each session. |
| Client key pair (P-256) | Generated on the client device for each verification request; private key stays in device-local secure storage | One verification request | Binds a given session signing key delivery to the exact device that asked for it — Grid encrypts the session to this public key, so only this device can decrypt. |
| Session signing key (P-256) | Issued by Grid, sealed to the client public key, decrypted and held on the device for the session’s lifetime | 15 minutes (default) | “This specific wallet action was approved on an authenticated device.” Signs the payloadToSign Grid returns on quotes, credential changes, session revocations, and wallet exports. |
payloadToSign bytes on the client → pass the signature as the Grid-Wallet-Signature header on the request that actually moves funds or changes account state. This applies to withdrawals, adding or removing credentials, revoking sessions, and exporting the wallet seed.
See Client keys & signing for the full key-management and signing reference, and Authentication for the per-credential-type flows.
Prerequisites
You also need:- A platform configured with
USDBin its supported currencies. In sandbox, USDB is enabled by default alongsideUSDandUSDC. - Sandbox or production API credentials with access to the
Embedded Wallet AuthandInternal Accountsendpoints.
Testing in sandbox. Sandbox accepts two fixed magic values so you can exercise the auth + signing flow without managing real OTP delivery or device-side keys:
- Email OTP code: always
000000for anyEMAIL_OTPcredential’sverifycall. - Wallet signature: the
Grid-Wallet-Signatureheader accepts the literal stringsandbox-valid-signaturefor any signed wallet action. TheencryptedSessionSigningKeyreturned by/verifyin sandbox is a stub and is not meant to decrypt — skip the HPKE decrypt step entirely.
Quickstart
The walkthrough below is the happy path: create a customer, find the auto-provisioned wallet, register a passkey, fund it, and withdraw to a bank account. Each step shows the HTTP request your integrator backend makes on behalf of the client.1. Create a customer
Create the customer record. An Embedded Wallet is provisioned automatically whenever a customer is created on a platform that hasUSDB in its supported currencies — you don’t need to pass it on the customer.
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.
2. Find the Embedded Wallet
When a customer is created on a USDB-enabled platform, Grid automatically provisions an Embedded Wallet alongside their other internal accounts. Fetch it by filtering the customer’s internal accounts bytype=EMBEDDED_WALLET.
InternalAccount:... id — every auth credential is scoped to it.
3. Register a passkey credential
Embedded Wallets support three authentication credential types: passkey, OAuth (OIDC), and email OTP. A passkey is a user-friendly default: biometric, phishing-resistant, and usable across the user’s devices. Registration only binds the passkey to the wallet — it doesn’t issue a session. Sessions are created on-demand, when the customer initiates an action that needs a signature (step 7). The full flow with sequence diagram is documented in Authentication; the condensed version:Your backend issues a WebAuthn challenge
Generate a random base64url
challenge, store it short-lived in your session store, and return it to the client.Client runs `navigator.credentials.create()` / platform equivalent
The browser or OS prompts the user for a biometric, returns an
attestation. The client posts the attestation back to your backend.4. Fund the wallet
Embedded Wallets 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:INTERNAL_ACCOUNT.BALANCE_UPDATED webhook when the balance updates. The wallet now holds 1,000.00 USDB.
5. Add an external bank account
Add the destination the customer wants to withdraw to. This is a standard external account — nothing Embedded Wallet-specific.201 Created with the new ExternalAccount:... id.
6. Create a withdrawal quote
Create a quote with the Embedded Wallet as the source. Grid returns apayloadToSign in the quote’s payment instructions — this is what the client will sign to authorize the transfer.
7. Authenticate and sign
The customer has an outstanding quote with apayloadToSign. Now we need a session signing key to sign it with — this is when the passkey actually gets used. The flow is challenge → assertion → verify → decrypt → sign.
Your backend requests a fresh challenge
challenge and requestId to the client.Client generates a key pair and runs the WebAuthn assertion
The client generates a fresh P-256 client key pair, then prompts the authenticator with the Grid-issued challenge:Post the assertion plus
clientPublicKey (uncompressed hex) back to your backend.Your backend verifies the assertion with Grid to mint a session
encryptedSessionSigningKey and expiresAt to the client.Client decrypts the session signing key and signs the payload
The client decrypts
encryptedSessionSigningKey with the matching client private key, then signs the quote’s payloadToSign with the resulting session signing key. Return the base64 signature to your backend./challenge + /verify round-trip.
8. Execute the quote
Call/execute with the signature in the Grid-Wallet-Signature header.
OUTGOING_PAYMENT) as it settles — see Transaction lifecycle.
Where to next
Client keys & signing
Generate the P-256 key pair, decrypt the session signing key, and sign payloads on Web, iOS, and Android.
Authentication
OAuth and Email OTP flows, passkey reauthentication, and the full WebAuthn parameter mapping.
Sessions
List active sessions and revoke a session (sign-out).
Exporting a wallet
Let a customer take their wallet seed off Grid.