Webhook Events
This page documents all webhook event types sent by DirectCryptoPay.
Event Types
| Event | Description | When It Fires |
|---|---|---|
payment.confirmed |
Payment has been confirmed on-chain | Transaction reaches required confirmations |
payment.failed |
Payment has failed or expired | Transaction reverted or intent expired |
payment.confirmed
Sent when a blockchain transaction has been verified and the payment is considered complete.
{
"event": "payment.confirmed",
"timestamp": "2025-01-15T11:35:00.000Z",
"data": {
"id": "pi_abc123def456",
"status": "paid",
"amount": "49.99",
"currency": "USD",
"token": "USDC",
"chain": "polygon",
"chainId": 137,
"txHash": "0x7a3f8b2c...9f0",
"recipientAddress": "0x742d...bD18",
"senderAddress": "0xAbCd...Ef01",
"confirmedAt": "2025-01-15T11:35:00.000Z",
"metadata": {
"orderId": "ORD-12345"
}
}
}
When to Use
This is the primary event for fulfilling orders. When you receive payment.confirmed, the payment has been independently verified by the DCP backend via blockchain RPC.
payment.failed
Sent when a payment could not be completed.
{
"event": "payment.failed",
"timestamp": "2025-01-15T12:00:00.000Z",
"data": {
"id": "pi_abc123def456",
"status": "failed",
"reason": "transaction_reverted",
"amount": "49.99",
"currency": "USD",
"metadata": {
"orderId": "ORD-12345"
}
}
}
Failure Reasons
| Reason | Description |
|---|---|
transaction_reverted |
The on-chain transaction was reverted |
expired |
The payment intent expired before a transaction was submitted |
insufficient_confirmations |
Transaction did not reach required confirmations |
Headers
Every webhook request includes these headers:
| Header | Description |
|---|---|
Content-Type |
application/json |
X-Webhook-Signature |
HMAC-SHA256 hex digest of the raw body |
X-Webhook-Timestamp |
Unix timestamp (seconds) of when the webhook was sent |
User-Agent |
DirectCryptoPay-Webhook/1.0 |
Responding to Webhooks
Your endpoint should:
- Return a 2xx status code (200, 201, 202, or 204)
- Respond within 10 seconds
Any non-2xx response or timeout triggers a retry according to the retry policy.
Tip: Return 200 OK immediately and process the payment asynchronously. This ensures you never hit the 10-second timeout, even if your fulfillment logic is slow.