Retries & Delivery Logs
How BeeL. retries failed deliveries and how to inspect the delivery history.
BeeL. automatically retries webhook deliveries that fail due to network errors or non-2xx HTTP responses. You can also inspect the delivery history and trigger manual retries from the dashboard or the API.
Retry Policy
| Parameter | Value |
|---|---|
| Max attempts | 5 (1 original + 4 automatic retries) |
| Retry strategy | Exponential backoff |
| Initial delay | 5 seconds |
| Max delay | 6 hours |
| Timeout per attempt | 10 seconds |
Backoff Schedule
| Attempt | Approximate delay after previous attempt |
|---|---|
| 1st (original) | — |
| 2nd | ~5 seconds |
| 3rd | ~10 seconds |
| 4th | ~20 seconds |
| 5th | ~40 seconds |
If all 5 attempts fail, no further automatic retries occur. You can still trigger a manual retry from the dashboard or API at any time.
What Triggers a Retry
| Scenario | Retried? |
|---|---|
Your server returns 5xx | ✅ Yes |
| Connection refused / DNS failure / timeout | ✅ Yes |
Your server returns 4xx | ❌ No — treated as a client error |
Your server returns 2xx | ❌ No — delivery successful |
If your endpoint returns 4xx, BeeL. assumes the payload is invalid and will not retry. Return 5xx if you need BeeL. to retry (e.g. your database is temporarily unavailable).
Delivery Logs
BeeL. keeps a log of the last 50 delivery attempts per subscription. Each log entry records:
- Delivery timestamp and duration
- HTTP status code and response body
- All request headers sent (including
BeeL-Signature,BeeL-Event-Id,BeeL-Delivery-Id,BeeL-Event) - The full JSON payload that was sent
- The attempt number
- Error description (for failed deliveries)
View delivery logs
curl "https://app.beel.es/api/v1/webhooks/{webhook_id}/deliveries" \
-H "Authorization: Bearer beel_sk_live_xxx"{
"success": true,
"data": [
{
"id": "8ee6b023-c4e5-482e-93ca-dc66da2f9cb5",
"subscription_id": "3f7a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"event_type": "verifactu.status.updated",
"attempt_number": 1,
"http_status": 200,
"success": true,
"duration_ms": 142,
"response_body": "OK",
"error_message": null,
"request_headers": {
"BeeL-Signature": "t=1741362026,v1=3c4f7a2e...",
"BeeL-Event": "verifactu.status.updated",
"BeeL-Event-Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"BeeL-Delivery-Id": "8ee6b023-c4e5-482e-93ca-dc66da2f9cb5",
"Idempotency-Key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"payload": "{\"id\":\"a1b2c3d4...\",\"type\":\"verifactu.status.updated\",...}",
"delivered_at": "2026-03-07T16:20:26Z"
}
]
}Log fields
| Field | Description |
|---|---|
id | Unique ID for this delivery attempt. Matches the BeeL-Delivery-Id header. |
attempt_number | 1 for the original delivery, 2 for the first retry, etc. |
http_status | HTTP status returned by your endpoint. null if connection failed. |
success | true if your endpoint returned 2xx |
duration_ms | Round-trip time in milliseconds |
error_message | Error detail for failed attempts (timeout, DNS error, etc.) |
request_headers | Headers sent with this attempt — useful for re-verifying the signature |
payload | The exact JSON body that was sent to your endpoint |
Manual Retry
Trigger a retry for any delivery — successful or not:
curl -X POST \
"https://app.beel.es/api/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/retry" \
-H "Authorization: Bearer beel_sk_live_xxx"This uses the original payload and generates a new signature with a fresh timestamp. A new delivery log entry is created with the result.
Endpoint Requirements
To ensure reliable delivery, your endpoint should:
- Respond within 10 seconds — BeeL. does not wait longer
- Return
2xximmediately and process the event asynchronously if needed - Return
5xxif you are temporarily unable to process (triggers a retry) - Not return
4xxunless the payload itself is the problem
// ✅ Good: acknowledge immediately, process async
app.post('/webhooks/beel', async (req, res) => {
res.status(200).send('OK'); // respond first
await queue.push(req.body); // process later
});
// ❌ Bad: synchronous processing blocks the response
app.post('/webhooks/beel', async (req, res) => {
await processEventSynchronously(req.body); // may exceed 10s timeout
res.status(200).send('OK');
});