This quickstart walks through the core Global Accounts flow in sandbox.
You will create a customer, find the customer’s Global Account, fund it, create a withdrawal quote, sign the quote, and execute it.
Prerequisites
You need:
- Sandbox API credentials
- A platform enabled for Global Accounts
- Access to
Internal Accounts, Quotes, and Embedded Wallet Auth
export GRID_BASE_URL="https://api.lightspark.com/grid/2025-10-13"
export GRID_CLIENT_ID="YOUR_SANDBOX_CLIENT_ID"
export GRID_CLIENT_SECRET="YOUR_SANDBOX_CLIENT_SECRET"
In sandbox, customers are automatically approved for testing. Production customers must complete the required KYC or KYB checks before funds can move to or from fiat rails.
1. Create a customer
Create the customer who will receive a Global Account.
curl -X POST "$GRID_BASE_URL/customers" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"customerType": "INDIVIDUAL",
"platformCustomerId": "customer-123",
"region": "US",
"email": "jane@example.com",
"fullName": "Jane Doe",
"birthDate": "1990-01-15",
"nationality": "US"
}'
Save the returned Customer:... ID for later commands:
export CUSTOMER_ID="Customer:019542f5-b3e7-1d02-0000-000000000001"
2. Find the Global Account
Global Accounts appear in the API as internal accounts with type=EMBEDDED_WALLET.
curl -X GET "$GRID_BASE_URL/customers/internal-accounts?customerId=$CUSTOMER_ID&type=EMBEDDED_WALLET" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
Save the returned InternalAccount:... ID. You will use this account as the source or destination in quote requests.
export GLOBAL_ACCOUNT_ID="InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
3. Register a credential
Outbound movement from a Global Account requires customer authorization. For this sandbox quickstart, register an email OTP credential against the Global Account.
curl -X POST "$GRID_BASE_URL/auth/credentials" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "EMAIL_OTP",
"accountId": "'"$GLOBAL_ACCOUNT_ID"'"
}'
Save the returned AuthMethod:... ID, then verify it with the sandbox OTP code. The clientPublicKey is required by the API; in sandbox, the returned encryptedSessionSigningKey is a stub because you will use sandbox-valid-signature later.
export AUTH_METHOD_ID="AuthMethod:019542f5-b3e7-1d02-0000-000000000001"
curl -X POST "$GRID_BASE_URL/auth/credentials/$AUTH_METHOD_ID/verify" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "EMAIL_OTP",
"otp": "000000",
"clientPublicKey": "04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"
}'
For production passkey, OAuth, email OTP, and signing flows, see Authentication and Client keys.
4. Fund the account
In sandbox, use the sandbox funding endpoint to add test funds to the account.
curl -X POST "$GRID_BASE_URL/sandbox/internal-accounts/$GLOBAL_ACCOUNT_ID/fund" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"amount": 100000
}'
Grid returns the updated internal account. If webhooks are configured, Grid sends an INTERNAL_ACCOUNT.BALANCE_UPDATED event when the balance changes.
5. Create a withdrawal destination
Create or reuse an external account for the destination.
curl -X POST "$GRID_BASE_URL/customers/external-accounts" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"customerId": "'"$CUSTOMER_ID"'",
"currency": "USD",
"platformAccountId": "jane-checking",
"accountInfo": {
"accountType": "USD_ACCOUNT",
"accountNumber": "1234567890",
"routingNumber": "021000021",
"beneficiary": {
"beneficiaryType": "INDIVIDUAL",
"fullName": "Jane Doe",
"birthDate": "1990-01-15",
"nationality": "US",
"address": {
"line1": "123 Main Street",
"city": "San Francisco",
"state": "CA",
"postalCode": "94105",
"country": "US"
}
}
}
}'
Save the returned ExternalAccount:... ID.
export EXTERNAL_ACCOUNT_ID="ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"
6. Create a withdrawal quote
Create a quote with the Global Account as the source and the external account as the destination.
curl -X POST "$GRID_BASE_URL/quotes" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"source": {
"sourceType": "ACCOUNT",
"accountId": "'"$GLOBAL_ACCOUNT_ID"'"
},
"destination": {
"destinationType": "ACCOUNT",
"accountId": "'"$EXTERNAL_ACCOUNT_ID"'"
},
"lockedCurrencySide": "SENDING",
"lockedCurrencyAmount": 10000,
"description": "Withdrawal to checking"
}'
Because the quote source is a Global Account, Grid returns a payloadToSign in paymentInstructions[].accountOrWalletInfo.
Save the returned Quote:... ID.
export QUOTE_ID="Quote:019542f5-b3e7-1d02-0000-000000000006"
7. Sign and execute
Authenticate the customer, sign the payloadToSign, and execute the quote with the Grid-Wallet-Signature header.
curl -X POST "$GRID_BASE_URL/quotes/$QUOTE_ID/execute" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Idempotency-Key: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
-H "Grid-Wallet-Signature: sandbox-valid-signature"
Sandbox accepts sandbox-valid-signature so you can test the flow without implementing client-side signing first. Production requires a real signature from a verified session signing key.
8. Reconcile with webhooks
Listen for account and transaction webhooks to track balance changes, settlement, and refunds. See Webhooks for the Global Accounts webhook model.
Production checklist
Before going live:
- Complete the required KYC/KYB flow before moving funds to or from fiat rails.
- Replace
sandbox-valid-signature with a real Grid-Wallet-Signature generated from the returned payloadToSign.
- Verify webhook signatures with
X-Grid-Signature.
- Use idempotency keys for quote execution retries.
- Store
Customer:..., InternalAccount:..., ExternalAccount:..., Quote:..., and Transaction:... IDs for reconciliation and support.