Skip to content

Delivery & retries

This page describes what happens after an external service POSTs to your webhook URL: the responses Alfe returns, how duplicates are handled, and how events reach an agent that isn’t currently online.

Alfe replies to the sending service as soon as it has accepted (or rejected) the delivery:

Status Meaning
200 OK The event was accepted. The body includes a deliveryId.
401 Unauthorized The X-Alfe-Signature-256 header was missing or the signature didn’t match.
404 Not Found No active webhook exists at that URL (unknown or deactivated).
502 Bad Gateway The event was authentic but couldn’t be accepted for delivery; the sender should retry.

A successful response looks like:

{ "received": true, "deliveryId": "whd_01J9Z…" }

Because most providers treat any 2xx as success and retry on 5xx, these codes line up with how GitHub, Stripe, Svix and similar services already behave.

When an event is accepted:

  • If your agent is online, the event is delivered to it immediately.
  • If your agent is offline, the event is stored and delivered when the agent reconnects — so a brief restart or network blip doesn’t lose events. You can review these in the webhook’s delivery history.

Either way, the sending service gets its 200 OK promptly; it doesn’t wait for your agent to finish processing.

There is one deliberate exception: if an event is authentic but Alfe cannot store it for a currently-offline agent, it returns 502 instead of a 200. Returning an error here means the sending service will retry, rather than Alfe silently accepting an event it couldn’t hold — which would look like success to the sender while the agent never sees it.

Webhook providers deliver at least once, which means the same event can arrive more than once — a provider retries because it didn’t see your 200 in time, or you replay a delivery from its dashboard. Alfe deduplicates these when the provider stamps a stable delivery identifier on the request.

Alfe recognizes the common identifier headers, including:

  • X-GitHub-Delivery (GitHub)
  • Stripe-Signature (Stripe — its per-event value)
  • Svix-Id (Svix and Svix-based providers)
  • Idempotency-Key
  • X-Slack-Request-Id (Slack)
  • Twilio, Amazon SNS, CloudEvents (ce-id), and other common headers

When a repeat of an already-seen identifier arrives, Alfe short-circuits it and responds with a duplicate acknowledgement instead of delivering the event to your agent a second time:

{ "received": true, "duplicate": true, "externalDeliveryId": "" }

If a provider sends no recognizable delivery identifier, Alfe can’t tell a retry apart from a genuinely new event, so it passes it through. In that case, design your agent’s handling to be idempotent — safe to run twice for the same logical event. A good practice is to key your own processing on a stable field inside the payload (an event id, an object id, a version number).

Whether your agent handles events directly or you run your own receiver in front of it, a few habits keep delivery robust:

  • Respond fast, work later. Acknowledge quickly and do slow work asynchronously. Providers have short timeouts and will retry if you’re slow — which produces duplicates.
  • Make handling idempotent. Assume any event can arrive more than once and make repeated processing harmless.
  • Verify before you trust. If you run your own receiver, check the signature first — see Verifying signatures.
  • Expect retries on errors. If you return a 5xx, expect the provider to send the event again later.