Sandbox setup
To use the sandbox environment:- Go to app.lightspark.com, create an account, and generate your sandbox API keys from the dashboard.
- Add your sandbox API token and secret to your environment variables.
- Use the normal production base URL:
https://api.lightspark.com/grid/2025-10-13. - Authenticate using your sandbox token with HTTP Basic Auth.
USDB in its supported currencies.
Funding a Global Account
Real Global Accounts are funded by following payment instructions or by executing a quote into the account. In sandbox, you can instantly add USDB to any internal account using the sandbox funding endpoint:INCOMING_PAYMENT webhook. Use this to skip straight to a funded state when you’re testing withdrawals.
Magic values
The Grid sandbox lets you exercise Global Account auth flows without moving real money. Email OTP and SMS OTP use the fixed sandbox code000000 — HPKE-encrypt that code in the encryptedOtpBundle just like production. Passkey auth can use the same browser WebAuthn ceremony as production, and signed wallet actions can use the same session signing key and Grid-Wallet-Signature stamp as production. OAuth uses JWT-shaped sandbox OIDC tokens: sandbox skips real IdP signature verification, but still validates token claims, freshness, credential identity, and verify-time nonce binding.
Sandbox runs real HPKE end-to-end for EMAIL_OTP and SMS_OTP: clients build a real encryptedOtpBundle against the sandbox otpEncryptionTargetBundle and stamp the exact returned payloadToSign string with their TEK keypair. The only sandbox shortcut is the magic OTP code the user “receives” instead of a real email or SMS delivery.
Authentication failures return 401 UNAUTHORIZED with a reason field that names the specific check that failed. A malformed OIDC JWT can return 400 INVALID_INPUT before authentication starts.
Email and SMS OTP code
HPKE-encrypt the code000000 (together with your TEK public key) inside encryptedOtpBundle. The sandbox skips email and SMS delivery but runs real HPKE decryption and signature verification.
See Encrypt the OTP code for how to build the bundle. The flow is the same for both EMAIL_OTP and SMS_OTP:
- Call
POST /auth/credentials/{id}/challengeto getotpEncryptionTargetBundle - Generate a TEK key pair and HPKE-encrypt
{otp_code: "000000", public_key: tekPublicKeyHex}. Use the compressed public key (02or03prefix) so the same code works in production. - Submit
encryptedOtpBundletoPOST /auth/credentials/{id}/verify - Receive
202withpayloadToSignandrequestId - Sign
payloadToSignwith the TEK private key and retry withGrid-Wallet-Signature+Request-Idheaders
401 UNAUTHORIZED with reason: "Invalid OTP code".
Passkey WebAuthn ceremony
For new sandbox integrations, use the same WebAuthn calls you plan to use in production.1
Create a WebAuthn credential
Generate your own WebAuthn registration challenge and call
navigator.credentials.create().2
Register the passkey
Register the passkey with
POST /auth/credentials, passing the challenge and attestation returned by the browser.3
Request a challenge
Reauthenticate with
POST /auth/credentials/{id}/challenge, passing the compressed P-256 clientPublicKey (lowercase hex) whose private key becomes the session signing key.4
Run the browser assertion
Pass the returned
challenge into navigator.credentials.get() using the returned credentialId in allowCredentials.5
Verify the assertion
Verify with
POST /auth/credentials/{id}/verify, passing the browser assertion and echoing Request-Id from the challenge response.clientPublicKey is the session signing key.
OAuth (OIDC) token
OAuth does not use a fixed magic token in sandbox. Pass a JWT-shaped OIDC token asoidcToken. The JWT signature segment can be a dummy value, but the payload must look like a real ID token.
For POST /auth/credentials with type: "OAUTH", the sandbox token must include:
iss: a supported issuer, such ashttps://accounts.google.com,accounts.google.com, orhttps://appleid.apple.comaud: a non-empty string, or a single-element string arraysub: a non-empty subject identifier for the useriat: a numeric issued-at timestamp no more than 60 seconds before the request, with 5 seconds of clock skew allowedexp: a numeric expiration timestamp later than the request time
iss, aud, and sub. On POST /auth/credentials/{id}/verify, the fresh oidcToken must carry the same iss, aud, and sub as the credential being verified. It must also include nonce equal to the lowercase hex SHA-256 digest of clientPublicKey, hashed as the exact string sent in the verify request. That string is the compressed public key in lowercase hex: 66 characters starting with 02 or 03.
The old literal
sandbox-valid-oidc-token is no longer accepted. Use a freshly generated sandbox JWT for both OAuth credential registration and OAuth verification. Production requires a real ID token from your provider and verifies the provider signature.Wallet signature header
ForPASSKEY and OAUTH credentials and session refresh, the private key matching the clientPublicKey you supplied is the session signing key. For EMAIL_OTP, the TEK private key you generated for the encrypted OTP flow is the session signing key. Use the session signing key to build a Grid wallet signature over the exact payloadToSign string returned by Grid, then pass that full signature as the Grid-Wallet-Signature HTTP header on signed flows:
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)PATCH /internal-accounts/{id}(update wallet privacy)POST /quotes/{quoteId}/execute(when source is an embedded wallet)
This example uses the sample signer in the Grid API repo’s scripts directory. See the scripts README for setup, or replace
SIGN with your own Grid wallet-signature implementation.Webhooks
All webhook events fire normally in sandbox. Configure your webhook URL in the dashboard, perform any signed action, and your endpoint receives the sameINCOMING_PAYMENT, OUTGOING_PAYMENT, and account-state events as production.
Moving to production
When you’re ready to go live:- Generate production API tokens in the dashboard and swap them for the sandbox credentials in your environment.
- Remove sandbox magic values and unsigned sandbox OIDC tokens from your client and server code — production runs the real OTP, HPKE, WebAuthn, OIDC signature, and ECDSA flows.
- Configure production webhook endpoints.
- Test with small amounts first.
Next steps
- Implementation overview — end-to-end walkthrough of the happy path.
- Authentication — per-credential-type registration and reauthentication flows.
- Webhooks — event handling reference.