Events
Every state change in your account, a collection completing, a payout failing, a refund settling, is recorded as an immutable event. The event stream is the same set of events we deliver to your webhook endpoints, available to poll or replay for 90 days.
The event stream
Events are created by the platform, never by you. Each one names the resource it is about by its public id (col_..., po_..., rf_..., stl_...) and carries a data snapshot. The stream is scoped to the merchant and environment of your API key, and each event is retained for 90 days.
The events you see here are exactly the events delivered to your webhook endpoints, signed with the X-Capay-Signature header. Polling this endpoint is your reconciliation fallback when a webhook delivery is missed; see Authentication for how to verify webhook signatures.
List events
List events for your account, newest first.
Headers
Authorization: Bearer sk_...- Your secret key. The events:read scope is required.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limitoptional | integer | Page size, from 1 to 100. Defaults to 25. |
| typeoptional | string | Return only events of this exact type, for example collection.completed. See the event types below. An unknown type simply matches nothing. |
Example request
curl "https://api.capayglobal.com/v1/events?type=collection.completed&limit=2" \ -H "Authorization: Bearer sk_test_8fK2q0Zr41Xa"
Example response
{
"status": "success",
"data": {
"object": "list",
"data": [
{
"id": "evt_2n4Kq8Zr41Xa",
"object": "event",
"type": "collection.completed",
"resource_type": "collection",
"resource_id": "col_7pQ2r9Xm4KdA",
"data": {
"id": "col_7pQ2r9Xm4KdA",
"status": "completed",
"amount": "5000",
"currency": "XAF"
},
"livemode": false,
"created_at": "2026-08-29T12:30:05.000Z"
},
{
"id": "evt_9c1Lp7Ws30Vb",
"object": "event",
"type": "collection.completed",
"resource_type": "collection",
"resource_id": "col_5aH0m3Tn8QeZ",
"data": {
"id": "col_5aH0m3Tn8QeZ",
"status": "completed",
"amount": "12000",
"currency": "XAF"
},
"livemode": false,
"created_at": "2026-08-29T11:58:41.000Z"
}
],
"has_more": true
},
"request_id": "d4c3b2a1-6f50-4e71-9a82-b0c1d2e3f4a5"
}Results are ordered by created_at descending. has_more is true whenever a full page was returned, a hint that older events may remain.
This endpoint paginates by page size only: it does not accept a starting_after cursor (the collections and payouts list endpoints do). To walk history, narrow with the type filter, keep the newest id you have seen, and de-duplicate by event id across polls.
The event object
Each entry in the list is an event object.
| Field | Type | Description |
|---|---|---|
| id | string | Event id, prefixed evt_. |
| object | string | Always "event". |
| type | string | The event type, for example collection.completed. One of the types below. |
| resource_type | string | The kind of resource this event is about: collection, payout, refund, settlement and so on. |
| resource_id | string | The public id of that resource (col_..., po_..., rf_..., stl_...). Never an internal UUID. |
| data | object | A snapshot payload for the event. This is the same body delivered to your webhook endpoint. |
| livemode | boolean | false in sandbox, true in production. |
| created_at | string | ISO 8601 timestamp of when the event was recorded. |
Event types
This is the closed list of event types the platform emits. It is also the set a webhook endpoint can subscribe to; an endpoint with no filter receives them all.
| Event type | Description |
|---|---|
| collection.pending | A collection is awaiting customer authorization, for example an OTP or a redirect. |
| collection.processing | A collection was accepted by the provider and is being processed. |
| collection.completed | A collection was captured; the funds are credited to your balance. |
| collection.failed | A collection failed and will not be captured. |
| collection.expired | A collection was not authorized before it expired. |
| collection.cancelled | A collection was cancelled before capture. |
| payout.pending | A payout is awaiting authorization or provider acceptance. |
| payout.enqueued | A payout is queued because no provider was immediately available; its funds stay reserved. |
| payout.processing | A payout was accepted by the provider and is being processed. |
| payout.completed | A payout was delivered to the recipient. |
| payout.failed | A payout failed; any reserved funds are released. |
| payout.reversed | A completed payout was reversed. |
| refund.completed | A refund settled back to the payer. |
| refund.failed | A refund failed; the reserve is released. |
| transaction.in_reconciliation | A transaction is being reconciled against the provider after a timeout. |
| transaction.reconciled | A transaction final state was confirmed by reconciliation. |
| settlement.completed | A settlement batch to your bank account completed. |
| balance.low | A balance dropped below its configured low-balance threshold. |
| provider.status_changed | A payment provider health status changed. |
| webhook_endpoint.disabled | A webhook endpoint was auto-disabled after too many consecutive delivery failures. |
| payout_batch.completed | Every payout of a batch completed. Emitted once, when the batch turns terminal. |
| payout_batch.partially_failed | A batch turned partially_completed: some payouts completed, others failed, expired or were cancelled. |
| payout_batch.failed | No payout of a batch completed (for example the reserve was refused: reason_code insufficient_balance). |
| payout_batch.cancelled | Every payout of a batch was cancelled. |
Replay an event
Re-arm delivery of a past event. Every webhook delivery for the event, including ones already delivered or exhausted, is reset to pending for an immediate retry, and the event is fanned out again to every matching active endpoint, including endpoints you have added since.
Use it after fixing a broken endpoint, or to deliver historical events to a newly created endpoint. Replay is naturally idempotent, so no Idempotency-Key is required.
Headers
Authorization: Bearer sk_...- Your secret key. The events:write scope is required.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| idrequired | string | Event public id (evt_...) or UUID, in the path. |
Example request
curl -X POST https://api.capayglobal.com/v1/events/evt_2n4Kq8Zr41Xa/replay \ -H "Authorization: Bearer sk_test_8fK2q0Zr41Xa"
Example response
{
"status": "success",
"data": {
"replayed": true,
"event": "evt_2n4Kq8Zr41Xa",
"deliveries": 2
},
"request_id": "a1b2c3d4-5e60-4f71-8a92-b0c1d2e3f4a5"
}The response confirms the replay and reports deliveries, the number of delivery rows re-armed across your matching endpoints.
Errors
Errors use the standard envelope: a machine-readable code, a human message, and a next_step. Every error carries the request_id to quote to support.
| Code | HTTP | When it is returned |
|---|---|---|
| resource_not_found | 404 | No event matches this id in this environment (replay). |
| insufficient_scope | 403 | The API key lacks the events:read (list) or events:write (replay) scope. |
| rate_limited | 429 | The app exceeded its request quota; see the X-RateLimit-* headers. |
| internal_error | 500 | Something failed on our side. Retry the request. |