https://api.echonova.aiDevelopers
Delivery, retries and failures
What counts as a successful delivery, the retry schedule, the delivery status values, when a webhook is disabled, and how to handle duplicates.
This page describes what happens after an event fires: how long a delivery waits for your endpoint, when it retries, and when it gives up. Use it to size your handler's timeout and to design de-duplication.
One delivery
When an event fires, every enabled webhook subscribed to it receives one delivery. Each attempt does the following:
| Step | Detail |
|---|---|
| Sign | A fresh Unix timestamp is taken and the body is signed. See Verify a webhook signature. |
| Send | One POST to your Endpoint URL with Content-Type: application/json and the three X-Webhook-* headers. |
| Wait | Up to 10 seconds for your response. The request is aborted after that. |
| Judge | Any status from 200 to 299 is a success. Any other status, a timeout, a connection error or a TLS error is a failure. |
Only the status code of your response matters; the body is not interpreted.
Retry schedule
A delivery gets 3 attempts in total. The wait before each retry doubles, starting at 5 seconds.
| Attempt | Wait before it | Earliest start | Latest start |
|---|---|---|---|
| 1 | none | 0 s | 0 s |
| 2 | 5 s | 5 s | 15 s |
| 3 | 10 s | 15 s | 35 s |
"Earliest" assumes each failed attempt returns at once, for example with a
500. "Latest" assumes each attempt runs into the 10-second timeout. In the
worst case the last attempt ends about 45 seconds after the first began.
Allow a little on top of these figures.
Retries send the same body. Only the timestamp and the signature change. A
delivery is final once an attempt gets a 2xx, or after the third failed
attempt.
Where to see deliveries
Delivery outcomes are not shown in the portal. The Webhooks tab lists each webhook's name, events, id, endpoint and status. Log every delivery on your side, including the headers, so you can investigate from your own records.
Automatic disable
The count is of consecutive failed deliveries per webhook, not of attempts. A delivery counts as failed after all 3 attempts.
| Event | Effect on the counter |
|---|---|
A delivery ends failed |
Counter goes up by 1. |
A delivery ends delivered |
Counter resets to 0. |
| The counter reaches 5 | The webhook is disabled. The portal shows Disabled. |
| You enable the webhook | Counter resets to 0. |
A disabled webhook is skipped when events fire; the events are not sent later when you enable it. Saving the Edit Webhook dialog with Enable on also resets the counter.
Handling duplicates
Two things can make your endpoint see the same event twice: a retry after
your server processed the event but did not answer within 10 seconds, and
spending.exhausted, which fires on every metered call that leaves a key at
or above its limit. The body carries no delivery id, so de-duplicate on the
content:
| Event | De-duplication key |
|---|---|
job.completed, job.failed |
jobId plus the X-Webhook-Event header. A job finishes once, so a second delivery with the same pair is a retry. |
spending.warning |
apiKeyId plus the event name. It is sent once per billing cycle. |
spending.exhausted |
apiKeyId plus the event name. Treat it as a level, not an edge: mark the key exhausted and ignore repeats until the next cycle. |
Store the key before you do the work, in a store shared by all instances of your handler, and make the work itself safe to run twice. A hash of the raw body also identifies a retry, because retries reuse the body byte for byte.
Answer 2xx first, then process. If processing can take more than a few
seconds, queue it and return at once. That keeps you under the 10-second
limit and avoids the retry that causes most duplicates.
Recommended
- Verify the signature, record the de-duplication key, return
200, then download the audio or update your records from a worker.
Less effective
- Download the audio, transcode it and write three tables, then return
200twelve seconds later, so the delivery is retried and processed twice.
FAQ
How many times will you call my endpoint for one event?
Up to 3 times, about 5 and then 10 seconds apart, until one attempt gets a
2xx. Each attempt waits up to 10 seconds for your response.
Does a slow 200 count as delivered?
No. A response that arrives after 10 seconds is a failed attempt, even if
it is a 200, and the delivery is retried.
Are missed events replayed when I re-enable a webhook?
No. Events that fired while the webhook was disabled are not sent later. Poll the job endpoints for anything that ended during that time.
Why did my webhook turn itself off?
Five deliveries in a row failed after all their attempts. Fix the endpoint, then enable the webhook again; the counter starts from zero.
Can I see past deliveries?
Not in the portal. Keep your own log of every delivery, with its headers, on the receiving side.