Retries & Error Handling
How Pipes.bot handles webhook delivery failures.
Pipes.bot uses automatic retries with exponential backoff. If all retries fail, the payload is persisted to the WebhookDelivery table for manual retry.
Retry schedule
When your endpoint returns a non-2xx status code or is unreachable, Pipes.bot retries up to 3 times:
| Attempt | Delay | Total elapsed |
|---|---|---|
| 1 | Immediate | 0s |
| 2 | 2 seconds | 2s |
| 3 | 8 seconds | 10s |
What counts as a failure
- HTTP status codes outside
200-299 - Connection timeouts (10 second limit)
- DNS resolution failures
- Network errors (connection refused, reset, etc.)
After all retries fail
If all 3 attempts fail, the payload is persisted to the WebhookDelivery table (with the full payload, last error, and attempt count) with status pending for manual retry. It is not auto-delivered over WebSocket and not automatically re-dequeued — treat exhaustion as a delivery you must reconcile yourself.
Requirements for your endpoint
To ensure reliable delivery:
- Respond quickly. Pipes.bot enforces a 10-second timeout per request. Do heavy processing asynchronously after responding.
- Return
2xxon success. Any status outside200-299triggers a retry. - Be idempotent. Retries may deliver the same message more than once. Use the
messages[].idfield to deduplicate. - Use HTTPS. While HTTP is accepted, HTTPS is strongly recommended for production.
- Keep your endpoint available. Prolonged downtime will exhaust retries; exhausted deliveries are persisted to
WebhookDeliveryfor manual retry, not auto-delivered elsewhere.
URL restrictions
Webhook URLs must point to a public server. The following are blocked for security (SSRF protection):
localhost,127.0.0.0/8,::1- Private ranges:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - Link-local:
169.254.0.0/16,fe80::/10 - CGNAT:
100.64.0.0/10 - Non-HTTP schemes (
ftp://,file://, etc.)
Template status events
template_status_update events (BYON template review outcomes) use a different, lighter policy than message webhooks: 3 attempts at 0s / 2s / 8s with a 10s timeout, then the event is dropped with only a log entry — no WebhookDelivery row, no queue, no WebSocket fallback. See Template Management.