Skip to main content
Sandbox lets you test the Global Accounts integration before moving real funds.

Sandbox behavior

In sandbox:
  • Customers can be automatically approved for test flows
  • You can fund internal accounts with sandbox endpoints
  • Email OTP verification uses 000000
  • Signed account actions can use sandbox-valid-signature
  • Webhooks mirror the production event model

Magic values

The Grid sandbox accepts a small set of magic values that bypass real auth and credential checks for Global Account flows, so you can exercise the full request shape without standing up Turnkey, WebAuthn, or an OIDC provider. These values are sandbox-only — production enforces real signature verification, WebAuthn assertion, and OIDC nonce binding. A wrong magic value (or any other value) returns 401 UNAUTHORIZED with a reason field that names the specific check that failed.

Email OTP code

Pass 000000 as the body otp on POST /auth/credentials/{id}/verify when the credential type is EMAIL_OTP. The sandbox skips OTP delivery and accepts this value as a valid response to the issued challenge.
curl -X POST "$GRID_BASE_URL/auth/credentials/AuthMethod:abc123/verify" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Request-Id: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
  -d '{
    "type": "EMAIL_OTP",
    "otp": "000000",
    "clientPublicKey": "04f45f2a..."
  }'
Any other code returns 401 UNAUTHORIZED with reason: "Invalid OTP code".

Passkey assertion signature

Pass sandbox-valid-passkey-signature as assertion.signature on POST /auth/credentials/{id}/verify when the credential type is PASSKEY. The sandbox accepts the rest of the assertion as-is and skips the WebAuthn signature check.
curl -X POST "$GRID_BASE_URL/auth/credentials/AuthMethod:abc123/verify" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Request-Id: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
  -d '{
    "type": "PASSKEY",
    "assertion": {
      "credentialId": "...",
      "clientDataJson": "...",
      "authenticatorData": "...",
      "signature": "sandbox-valid-passkey-signature"
    },
    "clientPublicKey": "04f45f2a..."
  }'
Any other signature returns 401 UNAUTHORIZED with reason: "Invalid passkey signature". clientPublicKey is still required — the magic value bypasses the credential check, not the HPKE plumbing that seals the session signing key to the public key you supply.

OAuth (OIDC) token

Pass sandbox-valid-oidc-token as the body oidcToken on both POST /auth/credentials (OAUTH create) and POST /auth/credentials/{id}/verify (OAUTH).
curl -X POST "$GRID_BASE_URL/auth/credentials/AuthMethod:abc123/verify" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Request-Id: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
  -d '{
    "type": "OAUTH",
    "oidcToken": "sandbox-valid-oidc-token",
    "clientPublicKey": "04f45f2a..."
  }'
Any other token returns 401 UNAUTHORIZED with reason: "Invalid OIDC token".
OAUTH create still requires a JWT-shaped token. On the initial POST /auth/credentials (OAUTH create), the oidcToken must be a structurally valid JWT (header.payload.signature) so Grid can decode the iss claim and resolve the provider name. The literal sandbox-valid-oidc-token works on verify but not on create — for create, sign your own dummy JWT with any payload that includes a recognized iss claim. The sandbox bypasses signature verification, not JWT structure parsing.

Wallet signature header

Pass sandbox-valid-signature as the Grid-Wallet-Signature HTTP header on any signed-retry flow:
  • POST /auth/credentials (add-additional-credential signed retry)
  • DELETE /auth/credentials/{id} (revoke credential)
  • DELETE /auth/sessions/{id} (revoke session)
  • POST /internal-accounts/{id}/export (export wallet)
  • POST /quotes/{quoteId}/execute (when source is an embedded wallet)
curl -X POST "$GRID_BASE_URL/quotes/Quote:abc123/execute" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
  -H "Grid-Wallet-Signature: sandbox-valid-signature"
Any other header value returns 401 UNAUTHORIZED with reason: "Invalid Grid-Wallet-Signature".

Sandbox funding

Use the sandbox funding endpoint to add test funds to a Global Account:
curl -X POST "$GRID_BASE_URL/sandbox/internal-accounts/InternalAccount:019542f5-b3e7-1d02-0000-000000000002/fund" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000
  }'
The response is the updated internal account. Use INTERNAL_ACCOUNT.BALANCE_UPDATED webhooks to test balance reconciliation.

Suggested test path

  1. Create a sandbox customer.
  2. Find the customer’s Global Account by filtering internal accounts with type=EMBEDDED_WALLET.
  3. Fund the account with the sandbox funding endpoint.
  4. Create a test external account.
  5. Create a withdrawal quote.
  6. Execute with Grid-Wallet-Signature: sandbox-valid-signature.
  7. Confirm webhooks arrive and update your internal state.