Outgoing payment status webhook
Webhook that is called when an outgoing payment's status changes. A side's railDetails carries the rail-level status of that leg; for example, a payout the receiving bank returns arrives as OUTGOING_PAYMENT.FAILED with destination.railDetails.status set to RETURNED, and the payout is refunded to its source. A returned payout stays FAILED even if the originating bank later dishonors the return: the refund has already been posted, so the funds are reconciled manually. The dishonor is still reported: OUTGOING_PAYMENT.FAILED is sent again with railDetails.status set to RETURN_DISHONORED and dishonoredAt set. This endpoint should be implemented by clients of the Grid API.
Authentication
The webhook includes a signature in the X-Grid-Signature header that allows you to verify that the webhook was sent by Grid. To verify the signature:
- Get the Grid public key provided to you during integration
- Decode the base64 signature from the header
- Create a SHA-256 hash of the request body
- Verify the signature using the public key and the hash
If the signature verification succeeds, the webhook is authentic. If not, it should be rejected.
This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded.
Payload
Example payload
{
"id": "Webhook:019542f5-b3e7-1d02-0000-000000000007",
"timestamp": "2025-08-15T14:32:00Z",
"data": {
"id": "Transaction:019542f5-b3e7-1d02-0000-000000000004",
"destination": {
"destinationType": "ACCOUNT",
"currency": "EUR",
"accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123",
"railDetails": {
"transactionHash": "h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx",
"network": "SOLANA"
},
"onChainTransaction": {
"transactionHash": "h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx",
"network": "SOLANA"
}
},
"ruleBasedAccountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000011",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"platformCustomerId": "18d3e5f7b4a9c2",
"settledAt": "2025-08-15T14:30:00Z",
"createdAt": "2025-08-15T14:25:18Z",
"updatedAt": "2025-08-15T14:30:00Z",
"receiptDeliveryConfirmedAt": "2025-08-15T14:31:00Z",
"agentId": "Agent:019542f5-b3e7-1d02-0000-000000000042",
"description": "Payment for invoice #1234",
"sentAmount": {
"amount": 12550,
"currency": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"decimals": 2
}
},
"exchangeRate": 1.08,
"quoteId": "Quote:019542f5-b3e7-1d02-0000-000000000006",
"refund": {
"reference": "UMA-Q12345-REFUND",
"initiatedAt": "2025-08-15T14:30:00Z",
"settledAt": "2025-08-15T14:35:00Z",
"status": "COMPLETED",
"reason": "TRANSACTION_FAILED"
},
"counterpartyInformation": {
"FULL_NAME": "John Sender",
"BIRTH_DATE": "1985-06-15",
"NATIONALITY": "DE"
},
"source": {
"sourceType": "ACCOUNT",
"currency": "USD",
"accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
"railDetails": {
"transactionHash": "h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx",
"network": "SOLANA"
},
"onChainTransaction": {
"transactionHash": "h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx",
"network": "SOLANA"
}
},
"receivedAmount": {
"amount": 12550,
"currency": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"decimals": 2
}
},
"fees": 10,
"platformFees": 5,
"reconciliationInstructions": {
"reference": "UMA-Q12345-REF",
"transactionHash": "0x9f2c6b6f4b6c8f2a8d9e0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566"
},
"paymentInstructions": [
{
"accountOrWalletInfo": {
"accountType": "USD_ACCOUNT",
"paymentRails": [
"ACH",
"WIRE"
],
"accountNumber": "1234567890",
"routingNumber": "021000021",
"bankName": "Chase Bank",
"reference": "UMA-Q12345-REF"
},
"instructionsNotes": "Include reference UMA-Q12345-REF in memo"
},
{
"accountOrWalletInfo": {
"accountType": "SPARK_WALLET",
"assetType": "BTC",
"address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu",
"invoice": "lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs"
}
}
],
"rateDetails": {
"counterpartyMultiplier": 1.08,
"counterpartyFixedFee": 10,
"gridApiMultiplier": 0.925,
"gridApiFixedFee": 10,
"gridApiVariableFeeRate": 0.003,
"gridApiVariableFeeAmount": 30
},
"paymentRail": "ACH",
"railSelectionMode": "AUTO"
}
}Response
Webhook received successfully
Changes
Webhooks have no change history: a webhook is keyed by its event name rather than a path and method, so no recorded change can name it.