POST de fiecare dată când se întâmplă ceva cu un anunț al tău: e publicat, respins, editat în portal. Nu mai trebuie să întrebi periodic.
Webhook-urile urmează specificația deschisă Standard Webhooks, deci orice bibliotecă compatibilă îți verifică semnătura.
Configurarea
Din contul tău, la Setări → API, secțiunea Webhook-uri:1
Adaugă adresa
O adresă
https:// publică, de exemplu https://crm.exemplu.ro/hooks/housera. Alegi evenimentele pe care vrei să le primești.2
Păstrează secretul
La creare primești secretul webhook-ului, de forma
whsec_…. Se arată o singură dată. Îl folosești ca să verifici semnătura fiecărei livrări.3
Trimite un test
Butonul „Trimite un test” livrează un eveniment
webhook.test, semnat ca oricare altul, doar către acel webhook.Evenimentele
Schimbările de stare produc evenimente indiferent de unde au pornit: prin API, din portal sau de la moderare. Evenimentele unui anunț ajung la contul care deține anunțul, doar dacă acel cont are cel puțin o cheie API.
Forma unui eveniment
Corpul fiecărei livrări e un obiect JSON:string
Id-ul unic al evenimentului. E același cu antetul
webhook-id. Îl folosești ca să nu procesezi de două ori același eveniment.string
Tipul evenimentului, din tabelul de mai sus.
string
Momentul evenimentului, ISO 8601.
object
Pentru evenimentele de anunț:
code, external_ref (sau null), status (starea anunțului în momentul evenimentului), url, plus câmpurile specifice tipului.listing.rejected
listing.rejected
listing.withdrawn
listing.withdrawn
by e owner și apare "deleted": true.listing.edited_in_portal
listing.edited_in_portal
GET /account/listings/{code} și decide ce păstrezi. Vezi Pentru CRM-uri.media.failed
media.failed
webhook.test
webhook.test
Livrarea
Fiecare livrare e unPOST cu corpul JSON și antetele:
- Răspunde cu un status
2xxîn cel mult 10 secunde. Orice alt status, o redirecționare sau o depășire de timp e o livrare eșuată. - Răspunde repede, procesează apoi. Pune evenimentul într-o coadă proprie și confirmă imediat; nu face toată sincronizarea în timp ce Housera așteaptă.
- Redirecționările nu sunt urmate. Configurează adresa finală.
Reîncercările
O livrare eșuată se reîncearcă automat de încă 6 ori, după 30 de secunde, 2 minute, 10 minute, 30 de minute, 2 ore și 6 ore. În total, Housera încearcă aproximativ 9 ore. Evenimentelewebhook.test nu se reîncearcă.
Pentru că o livrare poate ajunge de mai multe ori (de exemplu, ai procesat-o, dar răspunsul tău s-a pierdut) și pentru că ordinea nu e garantată:
- ține minte id-urile procesate (
webhook-id) și ignoră un eveniment deja văzut; - nu te baza pe ordinea sosirii: pentru starea curentă a unui anunț, sursa de adevăr rămâne
GET /account/listings/{code}.
Verificarea semnăturii
Orice server poate trimite unPOST la adresa ta. Semnătura dovedește că livrarea vine de la Housera și nu a fost modificată.
Semnătura e un HMAC-SHA256 în base64, calculat peste șirul {webhook-id}.{webhook-timestamp}.{corp}, unde {corp} sunt octeții exacți ai corpului primit. Cheia HMAC e partea de după whsec_ din secret, decodată din base64.
Pașii:
- Citește corpul brut, înainte de orice parsare JSON. Un corp re-serializat nu mai dă aceeași semnătură.
- Verifică
webhook-timestamp: respinge livrările mai vechi sau mai noi de 5 minute față de ora ta. Așa, o livrare interceptată nu poate fi retrimisă mai târziu. - Calculează semnătura așteptată și compar-o în timp constant cu fiecare semnătură din
webhook-signature(antetul poate conține mai multe, separate prin spațiu, fiecare cu prefixulv1,).
Recuperarea evenimentelor
Un webhook pe care serverul tău nu l-a primit (a fost căzut mai mult de 9 ore, sau webhook-ul era oprit) nu e pierdut. Fiecare eveniment se păstrează 35 de zile și îl citești cuGET /events (dreptul listings:read):
- Evenimentele vin în ordine, de la cel mai vechi la cel mai nou, în aceeași formă ca la webhook.
aftere id-ul ultimului eveniment pe care l-ai procesat. Fărăafter, pornești de la cel mai vechi eveniment păstrat.limitmerge de la 1 la 500 (implicit 100).- Cât timp
meta.nextnu enull, mai sunt evenimente: ceri pagina următoare cuafteregal cumeta.next. - Când
meta.nextenull, ai ajuns la capăt. Păstrează id-ul ultimului eveniment dindatași pornește de la el data viitoare.
GET /events?after=<ultimul id> ca să prinzi orice a scăpat. Id-urile îți spun ce ai procesat deja.