Skip to content

What is sent and how it is retried

The request to your endpoint (method, headers, body), the states of a delivery, the retry schedule, and disabling.

5 minute readWebhooksUpdated: 10/25/2026

On this page

Before you start

For
Anyone who implements a receiver or investigates a missing delivery.
Prerequisite
For the delivery log in the portal, the Owner or Manager role. For redelivering, the Owner role.

The request your endpoint receives, the states of a delivery, the retry schedule, and disabling, for reference when you build and operate a receiver.

The request to your endpoint

Every delivery is a POST to the address of the endpoint. The body is the payload of the event as JSON, serialized compactly (without spaces and line breaks). Only the payload travels. The time of the event, its identifier, and the trigger are not in the body.

Component Value
Method POST
Content-Type application/json
X-Signature HMAC-SHA256 over the raw body, with the signing secret of the endpoint, base64url encoded
X-Event-Type The event type, for example composition.scene.published
X-Delivery-Id The ID of the delivery (whd_ and 26 characters). A retry carries the same one
Body The payload of the event as JSON, the fields from the event tables
Timeout 10 seconds for connection and response

This is what a delivery of the event composition.scene.published looks like (body wrapped for readability, in reality it arrives on one line):

POST /hooks/signage HTTP/1.1
Host: warenwirtschaft.example.com
Content-Type: application/json
X-Signature: 3q2-7wE5c1nXm0Zk8YbT4vLpQ9sRd6HfJgUaWi2xO7A
X-Event-Type: composition.scene.published
X-Delivery-Id: whd_01KXZACW98SENDNG0000000001

{
  "sceneId": "scn_01KJPX8NH0SZENE00000000001",
  "tenantId": "tnt_01KERPXZM0ADERAPTHEKE00001",
  "sceneVersionId": "scv_01KV5K0JE0VERSN00000000003",
  "versionNumber": 4,
  "contentHash": "b2f80a41d76c395ee0138b5a4c9d27f6103e8ab7592c4df081a63be95d7c024f",
  "appVersionPins": {},
  "publishedById": "usr_01KFB7QPW0TEAM000000000002",
  "at": "2026-07-20T08:31:05.000Z"
}

The expected response

Your response Effect
Status 2xx within 10 seconds The delivery counts as delivered. The failure counter of the endpoint resets to zero
5xx, 408, or 429 Temporary failure: retry according to the schedule below
No response within 10 seconds, connection error Like a temporary failure: retry
Any other 4xx Permanent failure: no retry, the delivery has failed for good

On a failure, the response text is stored truncated (at most 4 kB) in the delivery log. On a successful delivery, only the status code is recorded. A short, descriptive text helps when you check later, but it is not required.

Delivery states

State in the API In the portal Meaning
pending Pending Sending is in progress or imminent
delivered Delivered Your server responded with 2xx. deliveredAt is set
failed Failed Temporary failure. nextRetryAt gives the next attempt
dead dead Failed for good: fifth failure or a 4xx response. deadAt is set

The path is pending → delivered or failed. From failed, every further attempt leads back through pending to delivered, failed, or dead. For the state dead, the portal has no label of its own, and the delivery log shows the value itself. The label Retrying exists in the portal but is not assigned to any state.

Retry schedule

The platform retries only on 5xx, 408, 429, timeouts, and network errors. There are at most five attempts per delivery. The wait after the nth failure is 1 minute · 2ⁿ, with ±20% jitter. A job that runs every five minutes picks up due retries, up to 100 per run, so the actual wait is up to five minutes longer than the target value.

Attempt Wait after failure On another failure
1 2 minutes ±20% Attempt 2
2 4 minutes ±20% Attempt 3
3 8 minutes ±20% Attempt 4
4 16 minutes ±20% Attempt 5
5 — Failed for good (dead)

A 4xx response other than 408 and 429 ends the delivery immediately, regardless of the attempt counter.

Redeliver by hand

In the delivery log of the endpoint, every delivery with the status Failed has the Retry button. For a delivery in the state dead, the portal shows no button. You trigger a redelivery through the API:

curl -X POST "$SZENERA_API/v1/webhooks/whk_01KPR20K40WEBHK00000000001/deliveries/whd_01KXZACW98SENDNG0000000001/retry" \
  -H "Authorization: Bearer $TOKEN"

The response (status 201) is the delivery with the outcome of the new attempt. The new attempt is signed with the currently valid secret of the endpoint and carries the same X-Delivery-Id. If the endpoint is inactive, nothing is sent, and the response carries the delivery unchanged. The API does not check the state: even a delivery that was already delivered can be sent again this way. Your receiver then sees the same ID a second time.

Disabling an endpoint

Every failure raises the consecutiveFailures counter of the endpoint, and every success resets it to zero. If the counter is above 20, the endpoint becomes inactive (active: false), and the platform records notifications.webhook.endpoint.disabled. An hourly job makes up for what the counter missed at sending time. An inactive endpoint receives no new deliveries. In the portal it shows Inactive with the note “last failure …”. To turn it back on, use Activate or PATCH /v1/webhooks/{id} with {"active": true}. This does not take effect immediately: for each event type, the platform remembers for up to an hour whether an active endpoint has subscribed to it. After activating, or after adding events, it can therefore take up to an hour until the first delivery of a newly subscribed type arrives. Newly created endpoints take effect immediately.

The delivery log through the API

curl "$SZENERA_API/v1/webhooks/whk_01KPR20K40WEBHK00000000001/deliveries?limit=50" \
  -H "Authorization: Bearer $TOKEN"

The response is a page with items and nextCursor (if there is more). The next call gets cursor=<nextCursor>. limit is between 1 and 200, and 50 if omitted.

{
  "items": [
    {
      "id": "whd_01KXZACW98SENDNG0000000001",
      "tenantId": "tnt_01KERPXZM0ADERAPTHEKE00001",
      "endpointId": "whk_01KPR20K40WEBHK00000000001",
      "eventType": "composition.scene.published",
      "payloadSignature": "3q2-7wE5c1nXm0Zk8YbT4vLpQ9sRd6HfJgUaWi2xO7A",
      "status": "delivered",
      "attemptCount": 1,
      "responseCode": 200,
      "responseBody": null,
      "nextRetryAt": null,
      "dispatchedAt": "2026-07-20T08:31:05.000Z",
      "deliveredAt": "2026-07-20T08:31:06.000Z",
      "deadAt": null,
      "createdAt": "2026-07-20T08:31:05.000Z"
    }
  ],
  "nextCursor": "d2hkOjIwMjYtMDctMTk"
}
Field Meaning
id ID of the delivery, the same as in X-Delivery-Id
endpointId, tenantId Endpoint and organization
eventType The event type
payloadSignature The signature that was sent as X-Signature
status pending, delivered, failed, or dead
attemptCount Number of attempts so far
responseCode, responseBody Response from your server. responseCode is null if there was none. responseBody is filled only for failed attempts (truncated to 4 kB) and after a successful delivery is null or still carries the text of the last failed attempt
nextRetryAt Next scheduled attempt, only for failed
dispatchedAt, deliveredAt, deadAt, createdAt Times of the last send, the delivery, the final failure, and creation

The body that was sent is not in the list.

Permissions

Action Permission Roles
Read the delivery log webhook.delivery.list Owner, Manager
Redeliver webhook.delivery.retry Owner

These permissions apply to signed-in accounts. An API key (ak_…) cannot carry them. The calls need the access token of a sign-in, see Authentication.