Skip to content

Retries and the delivery log

At-least-once delivery over five attempts, the stable delivery id you dedupe on, the two-redirect limit, the resend endpoint, and the delivery log.

At-least-once delivery

A delivery that does not return 2xx — or that times out — is retried with exponential backoff on a dedicated queue, up to five attempts in total, so a slow endpoint of yours never holds up anyone else's. Each attempt writes its own row in the delivery log.

That makes delivery at least once, never exactly once. Your endpoint must tolerate seeing the same event twice.

Dedupe on the delivery id

X-Evoriqa-Delivery — and the identical id field in the body — is minted once when the event is emitted and is byte-identical on every retry. It is the dedupe key.

dedupe.mjs

The ts field is stable across retries too, so a duplicate is always correlatable with the original rather than looking like a fresh event.

Note:

Duplicates can also arrive without a retry: a resend (below) replays a past delivery with the same id and ts. The dedupe key handles both cases identically — though note a resent body is not guaranteed byte-identical (JSON key order may differ), which is why you dedupe on id, not on a body hash.

Redirects

Deliveries follow up to two redirects, and each hop is re-validated against the same protections that block internal and private addresses. That exists so an endpoint behind an http → https upgrade still receives events instead of silently receiving none while appearing active.

Point the endpoint at its final HTTPS URL anyway — a redirect chain is one more thing to fail.

The delivery log

Settings → Webhooks shows recent delivery attempts across your endpoints, newest first, with the event name, the outcome, and the HTTP status your server returned. The same log is available over the API:

list-deliveries.sh

It is offset-paginated (?skip/?take, take up to 200) and needs the workspace:read scope. Delivery attempts are retained for up to 90 days — and sooner if your workspace's data-retention window is shorter, since delivery payloads carry lead and conversation fields and age out on that same window.

Three optional filters narrow the log, ANDed with each other:

  • q — a case-insensitive substring match on the event name or the endpoint URL. It is trimmed, and anything past 200 characters is ignored.
  • from and to — a YYYY-MM-DD date window on when the attempt was logged. from is inclusive from the start of that day and to inclusive to the end, both in UTC, so from=2026-08-01&to=2026-08-31 covers all of August. A date that is malformed or impossible (2026-02-31) is rejected with a 422 VALIDATION_ERROR.
filter-deliveries.sh

Resending a delivery

Any logged delivery can be replayed:

resend.sh

The replay carries the same delivery id, timestamp, and stored payload as the original, so your dedupe logic sees it as the same event — drop it if you already processed it, or process it if the original never arrived. That stability is the point: a resend can never create a second lead or a duplicate ticket in a correctly deduping consumer.

The delivery log, newest first, with the status each endpoint returned
The delivery log, newest first, with the status each endpoint returned

Use it to answer the three questions that actually come up:

That last one is the most common real bug: work is done, the response is slow or errors, Evoriqa retries, and the work happens again. Respond 2xx first, then process — and dedupe regardless.

Where to go next

Last updated