Eșecuri de livrare a webhook-urilor și auto-dezactivare
Când endpoint-ul tău nu mai primește evenimente webhook, întrebarea e mereu: a încetat e-bon să mai trimită sau a continuat să trimită dar endpoint-ul tău a început să eșueze? Această rețetă urmează întreg ciclul de eșec și auto-dezactivare ca să poți face diferența și să recuperezi.
enabled: false pe abonament. Până nu îl reactivezi prin PATCH /api/v1/org/webhooks/{id}, nu se mai trimite niciun eveniment nou — nici măcar webhook.test. Reîncercările deja în curs continuă până își epuizează încercările.Cum funcționează livrarea și reîncercările
- Timeout pe încercare — fiecare încercare de livrare are 10 secunde să întoarcă un răspuns 2xx. După aceea, cererea e abandonată și numărată ca eșec.
- Backoff de retry — încercările eșuate sunt reluate pe un program fix: 1 min → 5 min → 30 min → 2 h → 12 h.
- Număr maxim de încercări — 5 încercări în total. După a 5-a eșuată, livrarea trece la
failedși nu mai e reîncercată niciodată. - Prag de auto-dezactivare — după 20 de livrări consecutive eșuate pe același webhook, abonamentul e setat automat pe
enabled: false. - Captură de răspuns — până la 500 de caractere din corpul răspunsului endpoint-ului tău sunt stocate pe fiecare înregistrare de livrare ca să poți depana ce a întors serverul tău.
- Procesare periodică a reîncercărilor — reîncercările în așteptare sunt preluate la fiecare 30 de secunde, deci o reîncercare programată se declanșează în ~30 s de la
nextRetryAt.
Cauze probabile
- Endpoint-ul răspunde non-2xx — orice altceva în afară de
200–299se numără ca eșec. Redirect-urile301/302nu sunt urmate. - Endpoint-ul depășește 10 s —
AbortController-ul pe încercare taie cererea chiar dacă handler-ul tău răspunde în cele din urmă. - Erori de hostname / TLS / DNS —
fetchrespinge înainte să sosească răspunsul; mesajul ajunge îndelivery.error. - Abonament auto-dezactivat —
failureCounta ajuns la20și procesorul a oprit trimiterea evenimentelor noi către acest abonament.
Cum verifici
Răsfoiește istoricul de livrări pentru webhook-ul afectat:
curl https://api.e-bon.ro/api/v1/org/webhooks/{webhookId}/deliveries \
-H "Authorization: Bearer <jwt>"
O livrare eșuată arată așa:
{
"id": "del_abc123",
"status": "failed",
"attempt": 5,
"httpStatus": 502,
"responseBody": "Bad Gateway",
"error": "http 502",
"attemptedAt": "2026-04-23T20:09:55.000Z"
}
Verifică webhook-ul părinte ca să vezi dacă a fost auto-dezactivat:
curl https://api.e-bon.ro/api/v1/org/webhooks/{webhookId} \
-H "Authorization: Bearer <jwt>"
Caută "enabled": false și un failureCount mare (≥ 20).
Remediere
Repară endpoint-ul de bază
Asigură-te că endpoint-ul tău întoarce un 2xx în 10 secunde pentru orice payload pe care e-bon îl trimite. Confirmă întâi, apoi pune munca grea pe o coadă — corpul a fost capturat în responseBody (până la 500 de caractere), deci poți reproduce local.
Trimite o livrare de test
Odată ce endpoint-ul e sănătos, trimite un eveniment de test cu webhook-ul în starea curentă:
curl -X POST https://api.e-bon.ro/api/v1/org/webhooks/{webhookId}/test \
-H "Authorization: Bearer <jwt>"
Vei primi un eveniment webhook.test. Confirmă că ajunge și că endpoint-ul tău întoarce 2xx. (Dacă webhook-ul e deja auto-dezactivat, endpoint-ul de test va respinge cu 409 CONFLICT până îl reactivezi — vezi pasul următor.)
Reactivează abonamentul
Dacă webhook-ul a fost auto-dezactivat, pune-l înapoi pe activ. Asta resetează și failureCount-ul pe partea de server la următoarea livrare reușită:
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 }'
Reia fereastra ratată doar dacă chiar ai nevoie
e-bon nu reia automat evenimentele care au fost trimise cât timp endpoint-ul tău era jos — au rămas pending, au fost reîncercate până la marca de 12 ore, apoi au trecut la failed. Dacă ai nevoie să recuperezi datele, interoghează resursa relevantă (de ex. GET /api/v1/receipts?since=…) și reconciliază cu starea ta.
Tot blocat?
Deschide un caz de suport la support@e-bon.ro sau e-bon.ro/contact cu webhookId-ul, un deliveryId recent eșuat, responseBody-ul capturat și hostname-ul endpoint-ului tău, ca suportul să poată corela log-urile de trimitere.
Timeout-uri de comenzi și sweep-ul de 180s
Ce înseamnă de fapt `command.timeout` față de `command.failed`, cum funcționează sweep-ul de 30 de secunde și cum `Idempotency-Key` îți permite să reîncerci în siguranță.
Remediază respingerile ANAF de raport (P7B / MF / JE)
Diagnostichează și rezolvă o respingere ANAF pe un raport fiscal — motivele frecvente, cum verifici statusul prin endpoint-ul de rapoarte și calea de remediere pe categorie.