Skip to main content

Retry Policy

Talonic retries failed webhook deliveries with up to 4 attempts, exponential backoff of roughly 2s, 4s, and 8s, and a 30-second timeout on every attempt.

The webhook retry policy determines what happens when your endpoint fails to acknowledge a delivery. Talonic makes up to 4 delivery attempts per webhook: one immediate attempt plus up to 3 retries with exponential backoff of roughly 2, 4, and 8 seconds. An attempt succeeds when your endpoint returns a 2xx status code within the 30-second per-attempt timeout.

  1. Attempt 1: immediate
  2. Attempt 2: after ~2 seconds
  3. Attempt 3: after ~4 seconds
  4. Attempt 4 (final): after ~8 seconds

Non-2xx responses and timeouts trigger a retry. Redirects (3xx) are deliberately not followed: the delivery treats them as failures, because following a redirect would send the signed payload to a URL that was never validated. Point your webhook configuration directly at the final endpoint URL.

After the final failed attempt, the delivery is marked as failed and logged. You can inspect delivery outcomes, HTTP status codes, and error messages in the dashboard delivery log. The X-Talonic-Delivery header carries the same delivery ID across every retry of a delivery, so use it as an idempotency key to deduplicate on your end.

Because the whole retry window spans a couple of minutes at most, treat webhooks as a trigger rather than the source of truth: acknowledge fast with a 2xx, enqueue the work, and fetch authoritative state from the API (for example GET /v1/extractions/:id). If your endpoint was down during an event, re-fetch the affected resources via the REST API rather than waiting for a redelivery.

Return a 2xx before doing heavy work. If your handler processes the payload synchronously and exceeds the 30-second timeout, the attempt counts as failed and you will receive the same delivery again, even though your processing may have succeeded.

Fast-ack handler with delivery deduplication

const processed = new Set(); // use a persistent store in production

app.post('/webhooks/talonic', express.raw({ type: 'application/json' }), (req, res) => {
  const deliveryId = req.headers['x-talonic-delivery'];

  // 1. Deduplicate: the delivery ID is stable across every retry attempt.
  if (processed.has(deliveryId)) return res.status(200).send('duplicate');
  processed.add(deliveryId);

  // 2. Acknowledge immediately — never do heavy work before responding.
  res.status(200).send('ok');

  // 3. Process asynchronously after the response is sent.
  const event = JSON.parse(req.body);
  queue.enqueue({ deliveryId, event });
});

If your endpoint consistently fails, check for firewall rules blocking outbound Talonic traffic, TLS certificate issues, redirect responses from your framework (for example a trailing-slash redirect), or handler latency above 30 seconds. Pair retry handling with [Signature Verification](webhook-security) to reject spoofed payloads early and cheaply.

Recovering missed deliveries

When an endpoint outage outlasts the retry window, the events themselves are not lost — only the deliveries are. The [Event Feed](events-feed) at GET /v1/events reads the same rows webhooks fan out from, so a periodic sweep of the feed closes any gap left by downtime. Store the numeric id of the last event you processed and page forward from there.

Sweep the event feed after downtime

curl -s "https://api.talonic.com/v1/events?limit=50" \
  -H "Authorization: Bearer tlnc_your_api_key"

# Compare data[].id against the last ID your handler processed —
# event IDs are monotonically increasing, so any higher ID is a missed event.

Frequently asked questions

How many times does Talonic retry failed webhooks?+
Talonic makes up to 4 delivery attempts in total: one immediate attempt plus up to 3 retries with exponential backoff of roughly 2, 4, and 8 seconds. After the final failed attempt the delivery is marked as failed and logged.
What counts as a successful webhook delivery?+
Any 2xx HTTP response returned within the 30-second per-attempt timeout. Non-2xx responses, 3xx redirects (which are not followed), and timeouts all count as failed attempts and trigger a retry.
How do I avoid processing the same webhook event twice?+
Use the X-Talonic-Delivery header as an idempotency key. It stays identical across all retries of the same delivery, so store processed delivery IDs and skip any repeat.
What should I do if my endpoint was down and I missed webhook events?+
The retry window spans a couple of minutes at most, so extended downtime means missed deliveries. Recover by querying the REST API for the affected resources, for example GET /v1/extractions to list recent extractions, rather than relying on redelivery.