Delivery log & replay
No support ticket needed to answer "did you send it?" — your webhook delivery history is queryable, and any delivered or failed event can be re-sent, via the API itself. This is also how you monitor your integration: the platform does not send alerts to your technical contact for exhausted deliveries or a circuit-breaker trip, so poll this endpoint (or the poll API) from your side.
Inspect deliveries
GET /api/v1/partner/webhooks/deliveries?limit=50
GET /api/v1/partner/webhooks/deliveries?status=exhausted&since=2026-08-10T00:00:00Z
| Param | Default / limit | Meaning |
|---|---|---|
limit | default 50, max 200 | Rows returned. |
status | — | Filter: pending | in_flight | delivered | exhausted. |
since | — | ISO 8601 datetime; only deliveries created at or after it. |
{
"success": true,
"deliveries": [
{
"eventId": "evt_66a1f0c2d3e4f5a6b7c8d9e0",
"sourceLoanNumber": "LN-2026-0001",
"sequence": 4,
"type": "payment.collected",
"status": "delivered",
"attempts": 1,
"nextAttemptAt": null,
"deliveredAt": "2026-08-17T09:31:02.418Z",
"lastStatusCode": 200,
"lastError": null,
"replayedAt": null,
"createdAt": "2026-08-17T09:31:01.907Z"
}
]
}
| Field | Meaning |
|---|---|
eventId | The event's id — the same value as the X-Fieldproof-Delivery header and your dedupe key. |
sourceLoanNumber, sequence, type | From the event envelope. |
status | pending (queued for a first or next attempt), in_flight (a POST is running now), delivered (you answered 2xx), exhausted (all attempts failed). |
attempts | POSTs made so far. |
nextAttemptAt | When the next attempt is due (pending rows). |
deliveredAt | When you answered 2xx. |
lastStatusCode, lastError | What your endpoint returned last time — HTTP status, or the transport error (timeout, TLS, DNS…). |
replayedAt | Set if you replayed it (below). |
createdAt | When the delivery was queued. |
exhausted = the full retry ladder failed (0s → 30s → 2m → 10m → 1h → 6h → 24h, 7 attempts, ≈31 hours). The event stays replayable for 30 days.
:::tip Monitor it
A five-minute cron that calls
GET /webhooks/deliveries?status=exhausted&since=<last check> and pages
your on-call is the alerting you should have. lastError on the newest
rows tells you why (401 → your signature check, 5xx → your handler,
timeouts → respond faster). Quote the X-Request-Id response header when
you write to [email protected].
:::
Replay
POST /api/v1/partner/webhooks/deliveries/{eventId}/replay
{ "success": true, "status": "pending", "message": "<human-readable text>" }
- Queues an immediate re-delivery of that event and resets its retry
ladder — an
exhaustedrow gets a fresh 7 attempts. - Works on
deliveredrows too (lost it after processing? replay it). Your receiver'seventIddedupe makes replays harmless by design. - If the row is already
pendingorin_flight, the response says so ("already queued") — nothing extra is scheduled. - Events that were never queued (emitted while you had no callback
configured, or before you subscribed to that type) can be replayed too: the
replay creates the delivery on demand from the event store and queues it.
This needs an active callback now — otherwise
422 CALLBACK_NOT_CONFIGURED. 404 DELIVERY_NOT_FOUND— no event with thateventIdexists for your organisation (wrong id, or another organisation's event).
A replay is an ordinary delivery — same event body and eventId, freshly
signed with a current timestamp — so your receiver needs nothing special. The
replay call itself counts toward your 60 requests/min API rate limit.
Test your endpoint
POST /api/v1/partner/webhooks/test
Fires a signed ping at your callback synchronously and returns the
result:
{
"success": true,
"delivered": true,
"statusCode": 200,
"latencyMs": 212,
"error": null,
"bodyExcerpt": "{\"ok\":true}"
}
delivered: falsewithstatusCode/errorfilled in tells you exactly what your endpoint did (a401here almost always means the signature was verified against a re-serialised body or the wrong path — see the receiver contract).- The
pingenvelope hassourceLoanNumber: nullandsequence: null— your receiver must tolerate that (full body). 422 CALLBACK_NOT_CONFIGURED— no active callback is registered for this environment (sandbox and production are configured separately).
Run it on every deploy of your receiver.