Skip to content

Payment Webhooks

Payment Webhooks

Receive instant notifications when payments are created, detected, confirmed, or encounter issues. Webhooks are the recommended way to track payment status.

Event Types

Payment Lifecycle Events

EventWhen FiredKey Fields
PAYMENT_CREATED Payment request created amount, currency, paymentId
PAYMENT_ADDRESS_ASSIGNED Crypto address allocated address, coinSymbol, chainId
PAYMENT_DETECTED Transaction seen on blockchain txHash, amount, confirmations: 0
PAYMENT_CONFIRMATION_UPDATE Confirmation count changes confirmations, required
PAYMENT_CONFIRMED Required confirmations reached txHash, confirmations
PAYMENT_SETTLED Payment fully processed settledAmount, feeAmount
PAYMENT_EXPIRED TTL expired without payment expiredAt
PAYMENT_CANCELLED Manually cancelled cancelledBy, reason
PAYMENT_ABANDONED User closed checkout abandonedAt

Exception Events

Event When Fired Key Fields
PAYMENT_EXPIRED_PARTIAL Partial payment received before expiry expected, received
PAYMENT_LATE_DETECTED Payment arrived after expiry txHash, delay
PAYMENT_REORG Transaction invalidated by chain reorg txHash (rare but critical)

Webhook Payload

All webhooks include these common fields:

Field Description
eventId Unique identifier for idempotency (evt_timestamp_hash)
eventType Type of event (e.g., PAYMENT_CONFIRMED)
timestamp ISO-8601 timestamp of event emission
paymentRequestId The payment ID in SanPay
externalId Your order reference (passed during creation)
metadata Custom data you included at payment creation
Example Payload
{
"eventId": "evt_1704556800000_abc123",
"eventType": "PAYMENT_CONFIRMED",
"timestamp": "2026-01-10T15:30:00.000Z",
"tenantId": "tenant-uuid",
"paymentRequestId": "pr_abc123",
"externalId": "ORDER-12345",
"metadata": { "orderId": "ORD-12345", "customerId": "C-789" },
"txHash": "0xabc123def456...",
"confirmations": 12
}

Request Headers

Header Example Value
Content-Type application/json
X-Event-ID evt_1704556800000_abc123
X-Event-Type PAYMENT_CONFIRMED
X-Webhook-Signature t=timestamp,v1=signature
User-Agent SanPay-Webhook/1.0

Retry Policy

We retry failed webhook deliveries with exponential backoff:

AttemptDelay
1 Immediate
2 1 minute
3 5 minutes
4 30 minutes
5 2 hours
6 24 hours

Best Practices

Respond Fast

Return 200 OK immediately. Process heavy logic asynchronously to avoid timeouts.

Handle Duplicates

Use eventId for idempotency. The same event may arrive multiple times due to retries.

Verify Signatures

Always verify the X-Webhook-Signature header before trusting the payload.

Log Everything

Store raw payloads for debugging. You may need them for reconciliation.

Handle Out-of-Order

Events may arrive out of sequence. Use timestamps and state machines.