Webhook delivery failures and auto-disable
When your endpoint stops receiving webhook events, the question is always: did e-bon stop sending, or did it keep sending but your endpoint started failing? This recipe walks the full failure-and-disable lifecycle so you can tell the difference and recover.
enabled: false on the subscription. Until you re-enable it via PATCH /api/v1/org/webhooks/{id}, no new events are dispatched at all — not even webhook.test. Existing in-flight retries continue until they exhaust their attempts.How delivery and retry work
- Per-attempt timeout — each delivery attempt has 10 seconds to return a 2xx response. After that, the request is aborted and counted as a failure.
- Retry backoff — failed attempts are retried on a fixed schedule: 1 min → 5 min → 30 min → 2 h → 12 h.
- Max attempts — 5 attempts total. After the 5th failure the delivery moves to
failedand is never retried again. - Auto-disable threshold — after 20 consecutive failed deliveries on the same webhook, the subscription is automatically set to
enabled: false. - Response capture — up to 500 characters of your endpoint's response body are stored on each delivery record so you can debug what your server returned.
- Retry sweep — pending retries are picked up every 30 seconds, so a scheduled retry will fire within ~30 s of its
nextRetryAt.
Likely causes
- Endpoint returns non-2xx — anything other than
200–299counts as a failure.301/302redirects are not followed. - Endpoint exceeds 10 s — the per-attempt
AbortControllercuts the request even if your handler eventually responds. - Hostname / TLS / DNS errors — the
fetchrejects before the response arrives; the error message lands indelivery.error. - Subscription auto-disabled —
failureCounthit20and the sweeper stopped dispatching new events to this subscription.
How to verify
Browse delivery history for the affected webhook:
curl https://api.e-bon.ro/api/v1/org/webhooks/{webhookId}/deliveries \
-H "Authorization: Bearer <jwt>"
A failed delivery looks like this:
{
"id": "del_abc123",
"status": "failed",
"attempt": 5,
"httpStatus": 502,
"responseBody": "Bad Gateway",
"error": "http 502",
"attemptedAt": "2026-04-23T20:09:55.000Z"
}
Check the parent webhook to see whether it was auto-disabled:
curl https://api.e-bon.ro/api/v1/org/webhooks/{webhookId} \
-H "Authorization: Bearer <jwt>"
Look for "enabled": false and a high failureCount (≥ 20).
Fix
Fix the underlying endpoint
Make sure your endpoint returns a 2xx within 10 seconds for any payload e-bon will throw at it. Acknowledge first, then queue the heavy work — the body has been captured in responseBody (up to 500 chars), so you can reproduce locally.
Send a test delivery
Once the endpoint is healthy, fire a test event with the webhook still in its current state:
curl -X POST https://api.e-bon.ro/api/v1/org/webhooks/{webhookId}/test \
-H "Authorization: Bearer <jwt>"
You will receive a webhook.test event. Confirm it lands and your endpoint returns 2xx. (If the webhook is already auto-disabled, the test endpoint will reject with 409 CONFLICT until you re-enable it — see next step.)
Re-enable the subscription
If the webhook was auto-disabled, flip it back on. This also resets failureCount server-side on the next successful delivery:
curl -X PATCH https://api.e-bon.ro/api/v1/org/webhooks/{webhookId} \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{ "enabled": true }'
Replay the missed window only if you need to
e-bon does not automatically replay events that were dispatched while your endpoint was down — they stayed pending and were retried up to the 12-hour mark, then went failed. If you need to backfill, query the relevant resource (e.g. GET /api/v1/receipts?since=…) and reconcile against your own state.
Still stuck?
Open a support case at support@e-bon.ro or e-bon.ro/contact with the webhookId, a recent failed deliveryId, the captured responseBody, and your endpoint's hostname so support can correlate dispatch logs.
Command timeouts and the 180s sweep
What `command.timeout` actually means versus `command.failed`, how the 30-second sweep works, and how `Idempotency-Key` lets you safely retry.
Fix ANAF report rejections (P7B / MF / JE)
Diagnose and resolve an ANAF rejection on a fiscal report — common reasons, how to check status via the reports endpoint, and the fix path for each category.