Skip to content

Retries and schedule

An event is delivered when your endpoint answers 2xx within 15 seconds. Anything else — another status, a timeout, a refused connection — is retried. Redirects are not followed.

Attempt After the previous one
2 10 seconds
3 30 seconds
4–7 1, 2, 5, 10 minutes
8–10 15, 30 minutes, 1 hour
then every hour, until 24 hours have passed since the first attempt

A Retry-After longer than the next wait is honoured, up to an hour. After 24 hours the delivery is failed. 410 Gone fails the delivery at once and turns the endpoint off.

Events, deliveries and attempts are kept 30 days.

A delivered or failed delivery can be sent again — same event, same webhook-id, a fresh schedule — after you fixed your endpoint:

examples/curl/webhooks/deliveries/get.sh
#!/usr/bin/env bash
# One delivery: the exact body sent and every attempt.
set -euo pipefail
. "$(dirname "$0")/../../signed-request.sh"
delivery_id=$(mka_required DELIVERY_ID)
mka_request GET "/v1/webhook-deliveries/$delivery_id"
examples/curl/webhooks/deliveries/retry.sh
#!/usr/bin/env bash
# Send a delivered or failed event again, under the same event ID.
set -euo pipefail
. "$(dirname "$0")/../../signed-request.sh"
delivery_id=$(mka_required DELIVERY_ID)
mka_request POST "/v1/webhook-deliveries/$delivery_id/retry"

A delivery still on its schedule is 409 delivery_not_retryable.

While the endpoint is off, events wait and go out once it is on again — nothing is lost.

examples/curl/webhooks/endpoint/set-status.sh
#!/usr/bin/env bash
# Turn the endpoint off (ENABLED=false) or on; events wait while it is off.
set -euo pipefail
. "$(dirname "$0")/../../signed-request.sh"
body=$(cat <<JSON
{
"enabled": ${ENABLED:-true}
}
JSON
)
mka_request POST "/v1/webhook-endpoint/status" "$body"
examples/curl/webhooks/endpoint/roll-secret.sh
#!/usr/bin/env bash
# Replace the signing secret; the old one keeps signing for an hour.
set -euo pipefail
. "$(dirname "$0")/../../signed-request.sh"
body=$(cat <<JSON
{
"expire_current_in": 3600
}
JSON
)
mka_request POST "/v1/webhook-endpoint/secret/roll" "$body"

The answer carries the new secret once. Until previous_secret_expires_at — expire_current_in seconds, a day at most, 0 for at once — every event is signed with both secrets, so you switch your servers without losing a delivery. Rolling again before then drops the older one.

examples/curl/webhooks/endpoint/delete.sh
#!/usr/bin/env bash
# Remove the endpoint; events stop going anywhere.
set -euo pipefail
. "$(dirname "$0")/../../signed-request.sh"
mka_request DELETE "/v1/webhook-endpoint"

Deliveries on their way fail. A new endpoint gets a new secret.