Webhookuri într-un SaaS B2B: cum gestionezi reîncercările și evenimentele duplicate
Un ghid practic pentru livrarea webhookurilor către clienți: semnături, răspunsuri rapide, evenimente duplicate, reîncercări și recuperarea livrărilor eșuate.

Echipa Pentru Fondatori
Platforma fondatorilor din România

Dacă produsul tău trimite webhookuri către clienți, proiectează de la început pentru livrări repetate și pentru un receptor temporar indisponibil. Un răspuns HTTP pierdut poate face expeditorul să retrimită un eveniment pe care clientul l-a procesat deja. O conexiune reușită, la rândul ei, nu garantează că sistemul clientului a terminat operațiunea. Contractul integrării trebuie să spună ce confirmă răspunsul, cât timp încerci din nou și cum poate fi recuperat un eveniment.

Imagine editorială generată cu OpenAI; scenă ilustrativă.
Definește evenimentul înaintea endpointului
Un eveniment util are un identificator stabil, un tip, momentul producerii, versiunea formatului și referința la obiectul schimbat. Identificatorul rămâne același la fiecare reîncercare a aceleiași livrări. Nu îl înlocui cu un ID nou la fiecare apel HTTP: receptorul ar pierde metoda simplă de a recunoaște un duplicat. Documentează separat cazul în care două evenimente distincte descriu schimbări ale aceluiași obiect.
Pentru un produs care notifică schimbarea unui contract, de exemplu, clientul trebuie să poată deosebi „contract actualizat” de „contract semnat”. Nu trimite doar un obiect mare și lasă receptorul să ghicească operațiunea. Stabilește dacă payloadul este o fotografie a stării la momentul evenimentului sau doar o notificare care cere citirea stării actuale prin API. Această alegere schimbă modul în care clientul recuperează evenimentele întârziate.
Stripe explică în documentația webhookurilor că evenimentele nu sunt garantate în ordinea producerii. Pentru integrarea ta, publică aceeași limitare dacă nu poți garanta ordinea. Nu promite că un eveniment „creat” va ajunge mereu înaintea unuia „modificat”. Un client care primește mai întâi notificarea târzie ar trebui să poată citi obiectul actual prin API sau să decidă pe baza unei versiuni explicite a resursei, nu doar a orei din payload.
Confirmă preluarea, apoi procesează
Endpointul receptorului ar trebui să verifice cererea, să salveze durabil evenimentul sau să-l pună într-o coadă și să răspundă repede. GitHub cere răspuns 2xx în cel mult 10 secunde pentru propriile livrări și recomandă procesarea într-o coadă. Limita de 10 secunde este a GitHub, nu o regulă universală pentru produsul tău. Alege și publică o limită realistă pentru infrastructura ta.
Nu considera un răspuns 2xx drept dovadă că factura a fost înregistrată în contabilitatea clientului sau că utilizatorul a primit notificarea. El poate însemna numai că evenimentul a intrat în sistemul receptorului. În interfața pentru clienți, separă „livrat către endpoint” de „procesat de client”, dacă a doua stare îți este comunicată explicit. Altfel, nu o afișa.
Tratează duplicatele fără efecte repetate
La receptor, verificarea identificatorului trebuie făcută într-o operațiune care nu permite ca două cereri simultane să treacă amândouă drept noi. O înregistrare cu unicitate în baza de date este mai sigură decât o verificare în memorie urmată de o inserare separată. Dacă evenimentul este deja în coadă sau procesat, răspunde cu succes fără să repeți trimiterea e-mailului, crearea facturii ori acordarea accesului.
Stripe recomandă înregistrarea ID-urilor evenimentelor procesate și descrie chiar situația în care două obiecte Event diferite privesc același obiect și același tip de eveniment. De aceea, regula de deduplicare trebuie legată de efectul concret: ID-ul livrării pentru retransmisii, iar acolo unde este necesar, cheia operațiunii de business pentru schimbări echivalente. Testează ambele cazuri. O copie a aceleiași notificări și două notificări distincte nu sunt întotdeauna același lucru.
Semnează cererile și limitează accesul
Un URL secret nu dovedește cine a trimis cererea. Folosește semnături verificate pe conținutul brut al payloadului și o cheie separată pentru fiecare client. Ghidul OWASP pentru securitatea webhookurilor acoperă semnăturile, protecția la reluare, rotirea secretelor și validarea adreselor la care expeditorul livrează. Ultimul punct contează când clientul își poate introduce singur URL-ul: un webhook nu trebuie să devină o cale de acces către adrese interne ale infrastructurii tale.
Documentează cum se rotește cheia fără întreruperea integrării. Dacă permiți o perioadă de suprapunere între cheia veche și cea nouă, arată clar momentul expirării celei vechi. Nu scrie secretul, payloaduri sensibile ori tokenuri în jurnalul de audit. Poți păstra ID-ul evenimentului, clientul, endpointul, codul de răspuns și momentul încercării fără să expui datele din contract.
Oferă recuperare vizibilă după eșec
Stabilește ce erori merită reîncercate și după ce program. Un timeout sau un răspuns de server temporar justifică de regulă o nouă încercare; un URL inexistent sau o semnătură respinsă cere investigație. Nu repeta la nesfârșit aceeași livrare. Păstrează starea finală și o cale controlată de retrimitere după remedierea problemei. Documentația Azure Event Grid arată de ce sunt necesare limite de reîncercare și o destinație pentru evenimentele care nu mai pot fi livrate.
O pagină de integrări utilă arată ultimele încercări, codurile de răspuns, următoarea încercare programată și opțiunea de retrimitere. Dacă un client își schimbă endpointul, precizează dacă reiei automat evenimentele vechi sau doar pe cele viitoare. Include și o modalitate de reconciliere prin API, pentru intervalul în care receptorul a fost oprit. Acest scenariu poate intra în runbookul de incident pentru primele 60 de minute.
Înainte de lansare, testează trei probe pe o organizație de test: livrează același ID de două ori simultan, oprește receptorul până când expiră politica de reîncercare și trimite o cerere cu semnătură invalidă. Verifică efectele în sistemul clientului, nu doar răspunsurile HTTP. Astfel poți explica precis ce garantează webhookul tău și ce pași rămân necesari când livrarea eșuează.
Transparență AI: acest conținut poate fi redactat sau structurat cu ajutorul unor instrumente AI și este verificat editorial înainte de publicare. Imaginile generate sau modificate cu AI sunt folosite cu rol ilustrativ.
Întrebări frecvente
Poate ajunge același webhook de două ori?
Da. O livrare poate fi reluată după un răspuns pierdut sau o eroare; clientul trebuie să recunoască identificatorul evenimentului și să evite repetarea efectului.
Un răspuns HTTP 200 înseamnă că integrarea a terminat lucrul?
Nu neapărat. Într-un flux cu coadă, răspunsul confirmă preluarea durabilă a evenimentului; procesarea ulterioară trebuie urmărită separat.