Skip to main content

Event envelope (shared)

All webhook deliveries use the canonical PepayEvent envelope. WebSocket event_v1 frames use the same shape, so you can reuse handlers across webhooks and WebSockets.
{
  "id": "evt_1700000000000-123",
  "object": "event",
  "type": "invoice.updated",
  "created": 1700000000,
  "data": {
    "object": {
      "object": "invoice",
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "paid"
    }
  }
}
See WebSockets for the realtime stream that mirrors these event types.

Event types (overview)

CategoryEvent typesDescription
Invoice lifecycleinvoice.created, invoice.updatedInvoice state changes (source of truth for payments).
Payment lifecycleinvoice_payment.created, invoice_payment.updatedIndividual payment attempts and settlement status.
Commerce orderscommerce.order.created, commerce.order.updatedOrder lifecycle updates (includes linked invoice/payment context when applicable).
Test deliveriestest.pingTest event sent from the dashboard.

Invoice events

invoice.created

{
  "id": "evt_1700000001000-456",
  "object": "event",
  "type": "invoice.created",
  "created": 1700000001,
  "data": {
    "object": {
      "object": "invoice",
      "id": "inv_123",
      "status": "unpaid",
      "amount_usd": 49,
      "environment": "devnet"
    }
  }
}

invoice.updated

{
  "id": "evt_1700000002000-789",
  "object": "event",
  "type": "invoice.updated",
  "created": 1700000002,
  "data": {
    "object": {
      "object": "invoice",
      "id": "inv_123",
      "status": "paid",
      "paid_at": "2025-01-01T00:00:00.000Z",
      "environment": "mainnet"
    }
  }
}

Payment events

invoice_payment.created

{
  "id": "evt_1700000003000-111",
  "object": "event",
  "type": "invoice_payment.created",
  "created": 1700000003,
  "data": {
    "object": {
      "object": "invoice_payment",
      "id": "pay_123",
      "invoice_id": "inv_123",
      "status": "pending",
      "amount_usd": 49,
      "environment": "devnet"
    }
  }
}

invoice_payment.updated

{
  "id": "evt_1700000004000-222",
  "object": "event",
  "type": "invoice_payment.updated",
  "created": 1700000004,
  "data": {
    "object": {
      "object": "invoice_payment",
      "id": "pay_123",
      "invoice_id": "inv_123",
      "status": "confirmed",
      "environment": "mainnet"
    }
  }
}

Commerce order events

commerce.order.created

{
  "id": "evt_1700000005000-333",
  "object": "event",
  "type": "commerce.order.created",
  "created": 1700000005,
  "data": {
    "object": {
      "object": "commerce_order",
      "id": "order_123",
      "status": "placed",
      "invoice_id": "inv_123",
      "environment": "devnet"
    }
  }
}

commerce.order.updated

{
  "id": "evt_1700000006000-444",
  "object": "event",
  "type": "commerce.order.updated",
  "created": 1700000006,
  "data": {
    "object": {
      "object": "commerce_order",
      "id": "order_123",
      "status": "fulfilled",
      "invoice_id": "inv_123",
      "environment": "mainnet"
    }
  }
}

Test event

test.ping

{
  "id": "evt_1700000007000-555",
  "object": "event",
  "type": "test.ping",
  "created": 1700000007,
  "data": {
    "object": {
      "object": "ping",
      "status": "ok"
    }
  }
}

Tips for handlers

  • Treat invoice as the source of truth for payment state.
  • Dedupe by event.id (also sent as X-Pepay-Event-ID).
  • Keep handlers idempotent for at-least-once delivery.
Next: Webhook Authentication