BchainPayBchainPay

Event types

BchainPay delivers webhook events as JSON to the endpoint URLs you configure in the dashboard. Each delivery is an envelope containing the event metadata and the full resource snapshot at the time of the event.

Event envelope

Every webhook POST body has this shape:

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event_type": "payment_intent.completed",
  "created_at": "2026-04-27T12:08:11Z",
  "data": { /* full payment intent resource */ }
}
FieldTypeDescription
idstringUnique event identifier (UUID). Use for dedup.
event_typestringDot-separated event type (see table below).
created_atstringISO 8601 timestamp of when the event was created.
dataobjectFull API resource snapshot at the moment the event was produced.

Event types

TypeFires when
payment_intent.createdPOST /v1/payment-intents succeeds and a new intent is persisted.
payment_intent.address_generatedPOST /v1/payment-intents/:id/generate-address assigns a deposit address.
payment_intent.confirmedPOST /v1/payment-intents/:id/confirm succeeds and monitoring begins.
payment_intent.payment_detectedAn on-chain transaction matching the intent is detected.
payment_intent.completedBlockchain payment reaches the required confirmation threshold.
payment_intent.expiredThe intent passes its expiry time without completing.
payment_intent.failedThe intent fails (e.g. wallet lease expires before payment arrives).

Example payload — payment_intent.completed

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event_type": "payment_intent.completed",
  "created_at": "2026-04-27T12:08:11Z",
  "data": {
    "id": "f8d9a1b2-c3d4-5678-abcd-ef9012345678",
    "status": "completed",
    "merchant_id": "11111111-2222-3333-4444-555555555555",
    "amount_cents": 4999,
    "received_amount_cents": 4999,
    "remaining_amount_cents": 0,
    "currency": "USD",
    "settlement_currency": "USDC",
    "network": "ethereum",
    "token": "USDC",
    "blockchain_address": "0x7d2e...01ab",
    "reference": "INV-2026-001",
    "metadata": {},
    "created_at": "2026-04-27T12:00:00Z",
    "updated_at": "2026-04-27T12:08:11Z"
  }
}

Delivery semantics

  • At-least-once — the same event may be delivered more than once.
  • Failed deliveries (any non-2xx response) are retried up to 5 times with exponential backoff (30 s × 2^attempt, capped at 1 hour). After 5 failed attempts the event is dead-lettered.
  • Failed and dead-lettered deliveries are visible in the dashboard.

Idempotent processing

Because delivery is at-least-once, your handler must be idempotent. Use the id field as a deduplication key — store processed event IDs and skip any id you have already handled.

// pseudocode
if (await db.eventAlreadyProcessed(event.id)) {
  return res.status(200).end(); // ack duplicate
}
await processEvent(event);
await db.markEventProcessed(event.id);
Last updated Edit on GitHub