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.