This guide explains how to reconcile transactions between your internal systems and the Grid API using two complementary mechanisms: real-time webhooks and periodic queries.
Use webhooks for real-time updates and daily queries as a backstop to detect missed events or data drift.
Handling webhooks
Listen for transaction webhooks to track transaction status change until a terminal state is reached.
Terminal statuses: COMPLETED, REJECTED, FAILED, REFUNDED, EXPIRED.
All other statuses will progress until reaching one of the above.
- Outbound transactions: The originating account is debited at transaction creation. If the transaction ultimately fails, a refund is posted back to the originating account.
- Inbound transactions: The receiving account is credited only on success. Failures do not change balances.
Grid retries failed webhooks up to 160 times over 7 days with exponential backoff. Use the dashboard to review and remediate webhook delivery issues.
Subscribe and verify signatures
Configure your webhook endpoint and verify signatures. See Webhooks.Sample webhook payload:{
"transaction": {
"transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
"status": "COMPLETED",
"type": "OUTGOING",
"source": {
"accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
"currency": "USD"
},
"destination": {
"accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123",
"currency": "EUR"
},
"sentAmount": {
"amount": 10000,
"currency": { "code": "USD", "symbol": "$", "decimals": 2 }
},
"receivedAmount": {
"amount": 9200,
"currency": { "code": "EUR", "symbol": "€", "decimals": 2 }
},
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"platformCustomerId": "customer_12345",
"createdAt": "2025-10-03T15:00:00Z",
"settledAt": "2025-10-03T15:30:00Z",
"description": "Payment for services - Invoice #1234"
},
"timestamp": "2025-10-03T15:30:01Z",
"webhookId": "Webhook:019542f5-b3e7-1d02-0000-0000000000ab",
"type": "OUTGOING_PAYMENT"
}
Process events idempotently
Use the webhookId, transaction.id, and timestamp to ensure idempotent handling, updating your internal ledger on each status transition.
Recognize terminal states
When a transaction reaches a terminal state, finalize your reconciliation for that transaction.
Reconcile via queries
Additionally, you can list transactions for a time window and compare with your internal records.
We recommend querying days from 00:00:00.000 to 23:59:59.999 in your preferred timezone.
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/transactions?startDate=2025-10-01T00:00:00.000Z&endDate=2025-10-01T23:59:59.999Z&limit=100' \
-H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET'
Response
{
"data": [
{
"id": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
"status": "COMPLETED",
"type": "OUTGOING",
"source": {
"accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
"currency": "USD"
},
"destination": {
"accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123",
"currency": "EUR"
},
"sentAmount": {
"amount": 10000,
"currency": { "code": "USD", "symbol": "$", "decimals": 2 }
},
"receivedAmount": {
"amount": 9200,
"currency": { "code": "EUR", "symbol": "€", "decimals": 2 }
},
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"platformCustomerId": "customer_12345",
"description": "Payment for services - Invoice #1234",
"exchangeRate": 0.92,
"settledAt": "2025-10-03T15:30:00Z",
"createdAt": "2025-10-03T15:00:00Z"
}
],
"hasMore": true,
"nextCursor": "eyJpZCI6IlRyYW5zYWN0aW9uOjAxOTU0MmY1LWIzZTctMWQwMi0wMDAwLTAwMDAwMDAwMDAzMCJ9",
"totalCount": 45
}
Troubleshooting
- Missing webhook: Check delivery logs in the dashboard and ensure your endpoint returns
2xx. Retries continue for 7 days.
- Mismatched balances: Re-query the date range and verify terminal statuses; remember outbound failures are refunded, inbound failures do not change balances.
- Pagination gaps: Always follow
nextCursor until hasMore is false.