Webhooks
Deliveries and retries
Every dispatch is recorded as a delivery you can inspect, retry, or replay. This is how you diagnose a receiver that stopped accepting events — and how you recover the ones it missed.
Delivery lifecycle
Repeated delivery failures pause a subscription automatically; paused subscriptions dead-letter incoming events until resumed. Use the delivery, retry, and replay endpoints to inspect and recover.
A delivery moves through four states: pending while queued, delivered once the target accepts it, failed after an attempt that did not succeed, and dead_lettered once retries are exhausted or the subscription is paused.
A paused subscription still costs you events
Inspecting deliveries
Delivery history carries the attempt count, the last HTTP response code the target returned, and the exact payload that was sent — enough to tell a receiver bug from a network problem. It is also where you read a payload that arrived truncated.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Optional | Delivery id — a UUID, and the value sent as the X-Inkfree-Delivery header. |
subscriptionId | string | Optional | Subscription this delivery belongs to. |
eventId | string | Optional | Id of the event being delivered. |
eventType | string | Optional | Event type, e.g. envelope.completed, or inkfree.test for test dispatches. |
payload | string | Optional | Raw JSON body sent to the target URL. Read the full payload here when a delivery arrived truncated. |
status | string | Optional | Current state of the delivery.pendingdeliveredfaileddead_lettered |
attempts | integer | Optional | Number of attempts made so far. |
lastResponseCode | integer | Optional | HTTP status returned by the target on the last attempt. |
nextAttemptAt | string | Optional | When the next retry is scheduled, formatted MM/dd/yyyy HH:mm:ss. |
lastAttemptAt | string | Optional | When the last attempt was made, formatted MM/dd/yyyy HH:mm:ss. |
version | string | Optional | Payload schema version. |
curl "https://api-uat.softsages.com/core/api/v1/inkfree/webhooks/whk_123/deliveries" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"For a quick health check across all subscriptions, read the counters instead:
curl "https://api-uat.softsages.com/core/api/v1/inkfree/webhooks/metrics" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"account": "acme",
"app": "inkfree",
"by_subscription": {
"whk_123": {
"pending": 0,
"delivered": 412,
"failed": 3,
"dead_lettered": 1
}
}
}Recovering
Three endpoints replay events, and they differ in what payload they send. Retry and bulk replay reuse the stored payload; the arbitrary-payload replay sends exactly the body you pass, which is what you want when reproducing a specific case against a receiver under test.
- POST
/api/v1/inkfree/deliveries/{deliveryId}/retryRetry one delivery - POST
/api/v1/inkfree/webhooks/{id}/replay/bulkBulk replay deliveries - POST
/api/v1/inkfree/webhooks/replayReplay an arbitrary payload
A retry gets a new delivery id
X-Inkfree-Deliveryit has not seen before. Deduplicate on the event's own id if you need to suppress the repeat — see Deduplication.Bulk replay is the recovery path after an outage on your side. It defaults to dead_lettered deliveries from the last 24 hours, clamps since_hours to 1–720, and replays at most 500 deliveries per call — run it repeatedly to work through a larger backlog.
curl -X POST "https://api-uat.softsages.com/core/api/v1/inkfree/webhooks/whk_123/replay/bulk" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"status": "dead_lettered",
"since_hours": 48
}'{
"subscription_id": "whk_123",
"status_filter": "dead_lettered",
"since": "2026-01-13T10:30:00",
"replayed": 17
}Testing a receiver
Send a synthetic inkfree.test event. It creates a real delivery record and exercises the full signing and delivery path, so it is the reliable way to confirm your signature verification works before going live.
curl -X POST "https://api-uat.softsages.com/core/api/v1/inkfree/webhooks/whk_123/test" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"delivery_id": "8f14e45f-ea6d-4b1f-9b3a-1c2d3e4f5a6b",
"message": "Test webhook queued."
}Full reference for all of these: Webhook operations.