Webhooks
BchainPay sends signed JSON events via HTTP POST to a URL you configure. Use webhooks to fulfill orders, reconcile ledgers, and trigger downstream automation when payment state changes.
Event types
| Event | Fires when |
|---|---|
payment_intent.created | A new payment intent is created. |
payment_intent.address_generated | A deposit address is assigned to the intent. |
payment_intent.confirmed | The intent is confirmed (transitions to processing). |
payment_intent.payment_detected | An on-chain transaction matching the intent is detected. |
payment_intent.completed | On-chain payment is fully settled. |
payment_intent.expired | The intent expired before receiving full payment. |
payment_intent.failed | The intent failed (e.g. wallet lease expired). |
Delivery guarantees
- At-least-once delivery. BchainPay guarantees every event is delivered at least once. A
2xxresponse from your endpoint acknowledges receipt. - Retry with exponential backoff. Failed deliveries are retried up to 5 times (30 s × 2^attempt, capped at 1 hour). After all attempts are exhausted the event is dead-lettered. Failed and dead-lettered deliveries are visible in the dashboard.
Signing and verification
Every webhook carries an HMAC-SHA256 signature so you can verify it came from BchainPay and was not tampered with.
Header format:
X-Webhook-Signature: t=<unix_timestamp>,v1=<hmac_hex>Verification steps:
- Extract
t(timestamp) andv1(signature) from the header. - Build the signing payload:
${t}.${rawBody}— the timestamp, a literal dot, then the raw request body as a string. - Compute HMAC-SHA256 of the payload using your per-endpoint signing secret.
- Compare the computed HMAC (hex-encoded) against
v1using a constant-time comparison. - Reject the request if the signature does not match or if
tis more than 5 minutes away from the current server time (protects against replay attacks and clock skew).
Idempotency
BchainPay may deliver the same event more than once. Your handler must be idempotent:
- Use the event
idfield as a deduplication key. - Before processing, check whether you have already handled an event with that
id. - Store processed event IDs in your database to avoid duplicate side effects (e.g., double-fulfilling an order).
Configuring an endpoint
- In the dashboard, add an HTTPS endpoint URL.
- Select the event types you want to receive (or subscribe to all).
- Copy the per-endpoint signing secret and store it securely on your server.