Delivery and retries
The retry schedule, every failure reason, the throughput limits per target, when a delivery expires, when a failing target turns off, and what happens while a target or Helios is paused.
Each event creates one delivery for each target that subscribes to it. Helios sends a delivery in
one or more attempts. Every attempt of a delivery carries the same webhook-id, so you can drop
duplicates. See delivery and ordering.
A successful attempt
An attempt succeeds when your server answers with a 2xx status within 10 seconds.
- The 10 seconds cover the DNS lookup, the connection, the TLS handshake and your full response.
- Helios does not follow redirects. A
3xxfails withredirect. - Helios does not store your response body. Each attempt records the status code, the failure reason, the duration and the URL it called.
Do slow work after you reply. Put the event in your own queue and answer at once.
Retry schedule
When an attempt fails because of your server or its network, Helios tries again later. The delay grows after each failure.
| Attempt | Sent after the previous attempt failed |
|---|---|
| 1 | At once |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 6 hours |
| 7 | 12 hours |
| 8 | 24 hours |
After the 8th failed attempt the delivery is failed. That is about 44 hours and 36 minutes after
the first attempt. For example, a server that answers 503 for two hours and then recovers gets the
event on the 5th attempt, about 2 hours and 36 minutes after the first one.
You can send a delivery again from the delivery history or with helios webhook resend. A resend
uses the same webhook-id. A resent delivery gets the full retry schedule again.
Failure reasons
Each failed attempt records exactly one reason. You see it in the delivery history and in
helios webhook deliveries.
| Reason | What happened | Next step |
|---|---|---|
dns | The host name does not exist, or it has no IPv4 address. | Retried |
connection_refused | The connection was refused, reset or closed before a response, or the host was unreachable. | Retried |
tls | The TLS handshake failed, or the certificate is not valid for the host name. | Retried |
timeout | No full response within 10 seconds. | Retried |
redirect | Your server answered 3xx. | Retried |
blocked_destination | The host name resolved to a private, loopback, link-local, multicast or reserved address. | Retried |
http_4xx | Your server answered 4xx. | Retried |
http_5xx | Your server answered 5xx. | Retried |
internal_error | Helios could not send because of a problem on its side. | Retried in 1 minute. Counts toward the 8 attempts only after the delivery's 24 hour expiry time. |
target_disabled | The target was paused or turned off before the delivery was sent. | Ends the delivery. You can resend it. |
expired | The delivery waited 24 hours without an attempt (see expiry), or its event is no longer stored. | Ends the delivery. You can resend it while the event is stored. |
An internal_error never marks your target as failing and never turns it off.
Throughput limits
Helios sends each target's deliveries separately, so a slow or failing target never delays another target. These are the default limits.
| Limit | Default |
|---|---|
| Deliveries in flight to one target | 5 |
| Deliveries sent to one organization per minute | 600 |
| Deliveries in flight to one destination host, across all Helios organizations | 20 |
| Deliveries sent to one destination host per minute, across all Helios organizations | 1,000 |
| Test events per target per hour | 10 |
| Resends per user per hour | 60 |
A target's throughput ceiling is its in-flight limit divided by your response time. With 5 in flight and a 1 second response, one target receives about 5 deliveries per second, or 300 per minute. A faster response raises the ceiling.
- Waiting is free. A delivery over a limit waits as
pendingand shows as queued in the history. Waiting does not use an attempt. - Live events first. Within one target, Helios sends first attempts of new events before retries, and retries before resends. A large resend never delays new events.
- Slow targets. After 3 attempts in a row end in
timeout, Helios sends to that target one delivery at a time until an attempt ends with anything other than a timeout. - Test events and resends count against the organization's per-minute limit and the limits
of the destination host. When the host is at its limit, they answer
429. Try again a few seconds later.
If a target needs more, email [email protected] with the target ID. Helios can raise the limits of one target or one organization without a release.
Expiry
A delivery that has had no attempt 24 hours after it was created ends as failed with the reason
expired. This happens when a target receives more events than its throughput ceiling for a long
time. The target then shows a banner with its limit.
To stop deliveries from expiring, answer faster or ask support to raise the target's limit. Time while Helios paused delivery does not count toward the 24 hours.
Failing targets turn off
A target is marked failing at its first failed attempt. Any 2xx clears the mark. Test events
and internal_error attempts never mark a target as failing.
When a target has been failing for more than 3 days, Helios turns it off with the reason failing.
Its pending deliveries end with target_disabled. The target shows a banner with two actions.
- Turn back on clears the failing mark and turns the target on.
- Resend all failed since sends again every failed delivery since a time you choose, up to 10,000 per run, spread over 30 minutes.
Time while Helios paused delivery does not count toward the 3 days.
Target status
| Status | What it receives |
|---|---|
unverified | Only test events. A new target starts here, and a target returns here when its URL changes, with the reason url_changed. It turns on when a test event to the current URL gets a 2xx. |
on | Every event it subscribes to. |
paused | Nothing, except test events an admin sends. An admin paused it. |
off | Nothing, except test events an admin sends. Helios turned it off with a reason: failing (above), owner_lost_access (see access) or version_retired (see versions). |
A change to a target applies to the next deliveries. This includes a pause, a new URL, a new payload version and a rotated secret. Requests that are already in flight finish.
Pausing a target has two effects. Make sure you want both.
- Events that occur while the target is paused are dropped for that target. You cannot resend them later.
- Deliveries that are still waiting for a retry end with
target_disabled. You can resend them after you resume the target.
Pauses by Helios
During an incident, the Helios team can pause delivery for all organizations or for one. A pause by Helios keeps every event and every pending delivery. Nothing is dropped.
When delivery resumes, retry times, the 24 hour expiry, the 3 day failing clock and the 7 day
owner deadline move forward by the length of
the pause. A pause by Helios never turns your target off and never expires a delivery. While delivery
is paused, test events and resends answer 503.
Network
- The URL must use HTTPS on port 443 and must not contain a user name or password.
- Before every attempt Helios resolves the host name and checks every address. It refuses private,
loopback, link-local, multicast and reserved ranges, so a host name that later resolves to an
internal address fails with
blocked_destination. - Helios connects over IPv4 only. A host name with only AAAA records fails with
dns. - The certificate must be valid for the host name in the URL.
- Requests come from a fixed set of IP addresses. See egress IPs to allow them in your firewall.
History and retention
Events, deliveries and attempts are kept for 30 days. Open a target in Settings > Webhooks to see its deliveries, or list them from the CLI.
helios webhook deliveries <target-id> --status failed --since 2026-10-01T00:00:00ZSee CLI webhooks for every filter.
Last updated on
Webhooks
Helios sends a signed JSON request to your URL when a run finishes, a chat turn completes, a library change is staged, and more. Learn the request format, how to check the signature, and how payloads change over time.
Event types
The full list of webhook event types, who receives each one, an example payload and the JSON Schema of each type and payload version.