
# Webhook-uri

Webhook-urile permit <span data-t="appName">DM Champ</span> să notifice automat celelalte instrumente de afaceri ori de câte ori se întâmplă ceva important — crearea unui contact nou, programarea unei întâlniri, primirea unui mesaj. În loc să verificați manual actualizările, sistemele conectate primesc o notificare instantanee în momentul în care are loc un eveniment.

::: walkthrough webhooks
:::

---

## Ce sunt webhook-urile?

Gândiți-vă la un webhook ca la un mesaj text automat între două aplicații. Când se întâmplă ceva în <span data-t="appName">DM Champ</span> (cum ar fi înregistrarea unui contact nou), platforma trimite instantaneu o notificare către un alt sistem ales de dumneavoastră. Furnizați o adresă web (numită „URL webhook”) unde ar trebui trimise aceste notificări — aceasta este furnizată de obicei de CRM-ul, platforma de automatizare sau dezvoltatorul dumneavoastră.

> **Webhook-urile trimit date DOAR în afara <span data-t="appName">DM Champ</span>.** Un webhook este o cale cu sens unic *de la* <span data-t="appName">DM Champ</span> *către* celelalte instrumente ale tale. **Nu există niciun URL de webhook care să trimită clienți potențiali, contacte sau mesaje ÎN platformă.** Pentru a introduce un client potențial nou — dintr-un formular de pe site, din CRM-ul tău sau din GoHighLevel — sistemul tău efectuează în schimb un **apel API**. Consultă [Acces API](api-access.md) (operațiunea *Create a Contact*) și [Funnel-uri](funnels.md). Singurul lucru de care ai nevoie pentru direcția de intrare este **cheia API**, care se află în propria sa secțiune — consultă [Acces API](api-access.md#generating-your-api-key). Pagina **Webhook-uri** descrisă aici este exclusiv pentru direcția de ieșire.

::: note
**Notă:** Configurarea webhook-urilor implică o anumită configurare tehnică. Dacă nu vă simțiți confortabil cu acest lucru, partajați această pagină cu dezvoltatorul dvs. sau utilizați o platformă de automatizare precum Zapier, Make sau Pabbly, care oferă URL-uri de webhook fără a fi nevoie de programare.
:::


Utilizările comune includ:

- Sincronizarea contactelor noi cu CRM-ul dumneavoastră.
- Declanșarea unui flux de lucru în Zapier, Make sau Pabbly atunci când este aplicată o etichetă.
- Notificarea echipei în Slack atunci când un om este alertat.
- Actualizarea sistemului de calendar atunci când este programată o întâlnire.
- Înregistrarea rezumatelor conversațiilor în baza de date.

---

## Configurarea webhook-urilor

1. În bara laterală din stânga, faceți clic pe **Settings** (pictograma roată).
2. În bara laterală Settings, sub grupul **Integrations**, faceți clic pe **Webhooks**.

::: master-only
<figure><img src="../.gitbook/assets/v2-settings-overview.png" alt="Pagina de setări, care arată navigarea grupată din bara laterală stângă"><figcaption><p>Webhooks și API Key sunt două secțiuni separate sub Integrations în v2 — cheia API nu mai este inclusă pe această pagină.</p></figcaption></figure>
:::

Într-un cont în care nu sunt configurate încă webhook-uri, pagina arată astfel:

::: master-only
<figure><img src="../.gitbook/assets/v2-settings-webhooks.png" alt="Pagina Webhooks fără niciun webhook încă, arătând cardul de stare goală și butonul New webhook"><figcaption><p>Nu este nimic de văzut încă — faceți clic pe <strong>New webhook</strong> (dreapta sus sau butonul din cardul de stare goală) pentru a-l adăuga pe primul. Odată ce aveți cel puțin unul salvat, fiecare rând afișează propriul buton <strong>Test</strong> și un comutator pornit/oprit, iar clic pe rând deschide panoul <strong>Signing secret</strong> — nimic din toate acestea nu este disponibil până când un webhook nu este salvat efectiv.</p></figcaption></figure>
:::

3. Faceți clic pe **New webhook** (Webhook nou), în dreapta sus. Un formular se va deschide direct în pagină:

::: master-only
<figure><img src="../.gitbook/assets/v2-webhook-new-form.png" alt="Formularul pentru webhook nou: câmpurile Endpoint URL și Name, jetoane pentru evenimente din care poți alege, comutatorul Retry failed deliveries, comutatorul Also fire for all client accounts disponibil doar pentru agenții și nota despre secretul de semnare"><figcaption><p>Formularul pentru webhook nou. Introdu URL-ul endpoint-ului, alege cel puțin un jeton de eveniment și dă clic pe <strong>Create webhook</strong>. Secretul de semnare devine disponibil după salvarea webhook-ului. Comutatorul <strong>Also fire for all client accounts</strong> apare doar în conturile de agenție — vezi <a href="#one-webhook-for-all-your-client-accounts-agencies">Un singur webhook pentru toate conturile clienților tăi</a>.</p></figcaption></figure>
:::

4. Completați:
   - **URL Endpoint** — adresa web către care <span data-t="appName">DM Champ</span> va trimite notificările despre evenimente. O obțineți de la sistemul extern (CRM, platformă de automatizare sau server personalizat).
   - **Nume** — o etichetă pe care o veți recunoaște ulterior (de exemplu, „Alerte Slack” sau „Sincronizare CRM”). Doar pentru referința dumneavoastră.

> **URL-ul dvs. de webhook trebuie să fie o adresă `https://` accesibilă public.** Adresele `http://` simple, `localhost` sau adresele de rețea privată și adresele interne ale platformei sunt respinse la salvare. Pentru a testa de pe propriul computer, utilizați un tunel public (webhook.site sau ngrok) în loc de localhost.

5. Sub **Evenimente**, faceți clic pe evenimentele pe care doriți să le primească acest webhook — toate cele 22 sunt listate în [Cele 22 de evenimente Webhook](#the-22-webhook-events).
6. *(Opțional)* Activați **Reîncercare livrări eșuate** dacă doriți ca <span data-t="appName">DM Champ</span> să continue să încerce în caz de eșec temporar — consultați [Reîncercarea livrărilor eșuate](#retrying-failed-deliveries).
7. Faceți clic pe **Creează webhook**. Acesta apare în lista de sub formular și puteți face clic pe **Test** în rândul său oricând pentru a trimite un payload de probă către endpoint-ul dvs.

> **Permisiune necesară.** Adăugarea, editarea sau testarea webhook-urilor necesită permisiunea „edit” pentru Integrations (membrii echipei cu acces doar pentru vizualizare vor vedea o notificare de tip read-only în locul formularului).

> **Semnarea unui webhook** necesită ca acesta să fie deja salvat — deschideți rândul unui webhook existent pentru a-l edita, iar panoul **Signing secret** va apărea în partea de jos a formularului de editare. O schiță nouă, nesalvată, nu are încă opțiune de semnare — consultați [Signed Payloads](#signed-payloads-verifying-a-webhook-really-came-from-us) mai jos.

---

## Un singur webhook pentru toate conturile clienților tăi (Agenții)

Dacă administrezi o agenție, nu trebuie să recreezi același webhook pentru fiecare cont de client. În contul de agenție, formularul pentru webhook are un comutator suplimentar: **Also fire for all client accounts**. Activează-l și acest webhook va primi și evenimentele care au loc în fiecare cont de client din cadrul agenției tale — un singur endpoint pentru întreaga agenție.

Cum funcționează:

- **Blocul `user` îți indică apartenența evenimentului la un anumit client.** Fiecare notificare conține deja un bloc `user` care identifică contul în care a avut loc evenimentul, astfel încât automatizarea ta să poată direcționa datele per client.
- **Setările proprii ale webhook-ului tău se aplică peste tot.** Evenimentele selectate, secretul de semnare și setarea de reîncercare sunt utilizate și pentru livrările către conturile clienților.
- **Fără livrări duble.** Dacă un cont de client are propriul său webhook care indică către același URL, acesta va fi utilizat în schimb pentru evenimentele acelui cont — același eveniment nu va ajunge niciodată de două ori la același endpoint.
- **Clienții nu îl văd.** Webhook-ul nu apare în pagina de Webhooks a contului clientului, iar clienții nu îl pot dezactiva — este sub controlul tău.
- **Fiabilitatea este monitorizată per cont de client.** Dacă endpoint-ul tău continuă să eșueze, acesta este dezactivat automat doar pentru contul ale cărui livrări au eșuat (vezi [Fiabilitatea Webhook-urilor](#webhook-reliability)), nu pentru întreaga agenție deodată.

Comutatorul apare doar în conturile de agenție. Configurarea acestuia prin API este, de asemenea, acceptată — vezi câmpul `apply_to_sub_accounts` din [Webhooks API](../api/webhooks.md#one-subscription-for-all-client-accounts-agencies).

---

## Evenimente de declanșare disponibile

Puteți activa sau dezactiva fiecare dintre cele 22 de evenimente webhook în mod independent. Când un eveniment este declanșat, <span data-t="appName">DM Champ</span> trimite o notificare către URL-ul webhook-ului dvs. cu datele relevante. Fiecare eveniment, semnificația acestuia și codul `event` pe care îl introduce în payload sunt listate împreună în [Cele 22 de evenimente Webhook](#the-22-webhook-events) mai jos pe această pagină.

> **Bine de știut:** **Task Created**, **Task Updated** și **Task Completed** sunt complet selectabile și se salvează corect. **Daily Summary Created** este, de asemenea, o adăugare recentă. Consultați [Webhook pentru Task Completed](#task-completed-webhook) mai jos pentru structura acelui payload.

---

## Declanșatoare de webhook bazate pe etichete

`subscribed_to_tags` nu limitează evenimentele unui webhook la o etichetă. Acesta doar restrânge etichetele care produc o notificare de rezumat al conversației. Pentru a primi o solicitare atunci când este aplicată o anumită etichetă, setați un URL de webhook pe acea etichetă în fila **Etichete** a agentului (sau campaniei).

Formularul de webhook în sine nu are un selector de etichete, nici la crearea unui webhook nou, nici la editarea unuia, deci `subscribed_to_tags` poate fi citit sau modificat doar prin [API-ul Webhooks](../api/webhooks.md) sau solicitând asistență.

> **Bine de știut:** editarea unui webhook existent care are o listă `subscribed_to_tags` (redenumirea acestuia, modificarea evenimentelor, activarea reîncercărilor) nu mai șterge acea listă — deoarece formularul nu are un selector de etichete de trimis înapoi, salvarea din această pagină lasă acum lista existentă neatinsă. (Aceasta a fost o eroare reală înainte de **21 iulie 2026**: salvarea din formularul de webhook obișnuia să șteargă lista deoarece trimitea întotdeauna o listă de etichete goală. Dacă un webhook și-a pierdut lista `subscribed_to_tags` înainte de acea dată, va trebui reconfigurat prin API.)

### Generarea unui rezumat pentru contactele etichetate

Acolo unde un webhook are o listă `subscribed_to_tags`, puteți activa **Generează rezumat**. Când este activat, <span data-t="appName">DM Champ</span> generează automat un rezumat al conversației pentru contact atunci când una dintre acele etichete este aplicată și îl include în datele webhook-ului — context complet fără o solicitare separată.

---

## Testarea webhook-ului dumneavoastră

1. Deschideți **Setări → Integrări → Webhook-uri**.
2. Pe rândul webhook-ului dvs., faceți clic pe **Test**.
3. Verificați sistemul extern pentru a confirma că a primit datele de test.
4. Examinați formatul datelor pentru a vă asigura că sistemul dvs. îl poate analiza corect.

Pentru un test complet cap-la-cap, trimiteți un mesaj care ar declanșa unul dintre evenimentele configurate (o difuzare sau un mesaj primit pe un canal conectat) și verificați dacă webhook-ul se declanșează cu datele reale.

::: tip
**Sfat:** Utilizați un instrument precum [webhook.site](https://webhook.site) sau [RequestBin](https://requestbin.com) în timpul dezvoltării pentru a inspecta datele brute ale webhook-ului înainte de a vă conecta sistemul de producție.
:::


### Ce este considerată o livrare reușită

Indiferent dacă dai clic pe **Test** sau dacă evenimentul este declanșat în mod real, trimitem același lucru:

- O solicitare **POST** (niciodată GET), cu corpul sub formă de JSON și `Content-Type: application/json`.
- Antetele listate sub [Payload-uri semnate](#signed-payloads-verifying-a-webhook-really-came-from-us). Antetele de semnătură sunt incluse doar după ce ați setat o cheie secretă de semnare.

Considerăm livrarea reușită atunci când:

- Endpoint-ul tău răspunde cu **orice cod de stare 2xx** (200, 201, 204 — toate sunt acceptate).
- Răspunde **în decurs de 30 de secunde**.

Câteva aspecte care îi surprind pe utilizatori:

- **Corpul răspunsului este ignorat.** Nu trebuie să returnați niciun JSON anume. Un răspuns 200 gol este suficient.
- **Redirecționările sunt considerate eșecuri.** Noi nu le urmăm, așa că un cod 301 sau 302 (inclusiv o redirecționare cu slash la final sau de la http la https) este înregistrat ca o livrare eșuată. Salvați URL-ul final, nu unul care redirecționează.
- **Șirurile de interogare (query strings) sunt pe deplin acceptate.** `https://your-app.com/hook?token=abc123` este trimis exact așa cum l-ați salvat, deci plasarea unui token în șirul de interogare funcționează la fel de bine ca plasarea lui în cale.
- **URL-ul dumneavoastră trebuie să fie `https://` și accesibil public.** Adresele care aparțin propriei infrastructuri <span data-t="appName">DM Champ</span> sunt respinse, dar propriile dumneavoastră endpoint-uri pe Google Cloud Functions, Cloud Run, App Engine, Firebase Hosting sau oriunde altundeva sunt în regulă.
- **Un firewall sau un strat de protecție împotriva boților din fața endpoint-ului dumneavoastră ne poate bloca.** Cel mai frecvent caz este Cloudflare: dacă zona dumneavoastră are activat „Bot Fight Mode” sau o provocare gestionată, cererea noastră primește o pagină de provocare „Just a moment...” cu un cod 403 în loc să ajungă la serverul dumneavoastră — iar o cerere server-la-server nu poate trece niciodată de o provocare de browser, așa că atât butonul **Test**, cât și evenimentele reale eșuează în același mod. Butonul Test vă va spune când se întâmplă acest lucru („Cloudflare is showing a bot challenge to our request”). Remediați problema în Cloudflare cu o regulă de Securitate / WAF care omite provocările pentru calea webhook-ului dumneavoastră (sau pentru agentul utilizator `Webhook-Delivery/1.0`), apoi faceți clic din nou pe **Test**.
- **Dacă firewall-ul dumneavoastră are nevoie de o listă de permisiuni IP în schimb** (de exemplu, planul gratuit Cloudflare, unde „Bot Fight Mode” simplu nu poate fi omis printr-o regulă WAF, dar o regulă de acces IP setată pe „Allow” rulează înaintea acestuia), vă putem ajuta: fiecare livrare, fie că provine de la butonul **Test** sau de la un eveniment live, este trimisă de la o singură adresă IPv4 fixă (fără intervale, fără IPv6, fără rotație). Contactați asistența și vă vom oferi adresa pentru a o adăuga în lista de permisiuni. Păstrați [verificarea semnăturii](#signed-payloads-verifying-a-webhook-really-came-from-us) ca verificare reală de încredere, deoarece aceasta validează fiecare sarcină utilă indiferent de locul din care provine.
- **Rezultatul testului vă spune exact ce a răspuns endpoint-ul dumneavoastră.** Un test eșuat arată acum motivul real (codul de stare HTTP pe care l-a returnat endpoint-ul dumneavoastră, un timeout sau faptul că nu am putut accesa deloc adresa) în loc de o eroare generică, iar un test pe un webhook salvat este trimis semnat atunci când semnarea este activată, exact ca un eveniment live.

### Utilizarea n8n, Make sau Zapier ("Test URL" vs "Production URL")

Platformele de automatizare îți oferă de obicei două adrese webhook diferite, iar acest lucru îi induce pe mulți în eroare:

- Un **URL de test** (în n8n conține `/webhook-test/`). Acesta primește date doar în timp ce monitorizați activ panoul și tocmai ați făcut clic pe **Ascultă evenimentul de test** (sau **Testare flux de lucru**). Acesta captează un singur eveniment și apoi încetează să mai asculte — deci, dacă faceți clic pe **Test** în <span data-t="appName">DM Champ</span> de mai multe ori la rând, se va capta doar primul, și doar dacă fereastra de ascultare este activă în acel moment exact. Pentru a testa: faceți clic mai întâi pe **Ascultă evenimentul de test** în n8n, apoi reveniți la <span data-t="appName">DM Champ</span> și faceți clic pe **Test** o singură dată.
- Un **URL de producție** (în n8n conține `/webhook/`, fără `-test`). Acesta este cel care trebuie lipit în <span data-t="appName">DM Champ</span> pentru evenimente live. Funcționează doar după ce fluxul de lucru este setat pe **Activ**. Dacă fluxul de lucru nu este activ, n8n respinge cererea cu o eroare "404 / webhook not registered", chiar dacă <span data-t="appName">DM Champ</span> a trimis datele corect.

Pe scurt: testează cu URL-ul de test în timp ce asculți, dar pentru ca webhook-ul să continue să funcționeze pentru contacte reale, salvează **URL-ul de producție** în <span data-t="appName">DM Champ</span> și asigură-te că fluxul de lucru este **Active**.

---

## Formatul datelor webhook

Când un webhook este declanșat, <span data-t="appName">DM Champ</span> trimite date structurate (JSON) către URL-ul webhook-ului dumneavoastră. Dacă utilizați o platformă de automatizare precum Zapier sau Make, aceasta analizează automat aceste date pentru dumneavoastră. Dacă construiți o integrare personalizată:

```json
{
  "event": "contactCreated",
  "contact": { "id": "<contact-id>", "first_name": "Jane", "...": "..." },
  "campaign": { "id": "<campaign-id>", "name": "AI Receptionist", "status": "Live" },
  "agent": { "id": "<agent-id>", "name": "Front Desk" },
  "user": { "id": "<account-id>", "email": "owner@example.com" }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Șirul exact al evenimentului care a declanșat notificarea (de exemplu, `contactCreated`, `booked`). Aceasta **nu** este eticheta de afișare prezentată în lista de evenimente; fiecare etichetă și codul său corespondent se află în [Cele 22 de evenimente Webhook](#the-22-webhook-events). |
| `contact` | Contactul despre care este evenimentul sau `null` pentru evenimentele care nu sunt legate de un contact (cum ar fi `creditsRecharged`). |
| `campaign` | Campania din care face parte contactul sau `null` dacă nu există una. |
| `agent` | Agentul care gestionează conversația sau `null` dacă nu există unul. |
| `user` | Informații de identitate de bază pentru contul care deține datele. |

> **`campaign` sau `agent` — de obicei unul, nu ambele.** Dacă contul dvs. utilizează agenți, contactele sunt alocate unui agent, nu unei campanii, deci `campaign` apare ca `null`, iar `agent` vă indică cine a gestionat conversația. Conturile mai vechi, bazate pe campanii, văd situația invers. Citiți câmpul care este completat; nu presupuneți că `campaign` este întotdeauna prezent.

> **Blocul `agent` a fost introdus pe 15 august 2026.** Acesta se află alături de `campaign` în ceea ce privește evenimentele legate de o conversație — un chat încheiat, modul „nu deranjați”, o reluare, o dezarhivare, o pauză AI, un mesaj nou, un rezumat al conversației și webhook-ul pe care îl puteți seta pe o etichetă — și conține `id` și `name` ale agentului care gestionează conversația, sau `null` atunci când nu este implicat niciun agent. Este pur aditiv: fiecare câmp pe care îl primiți deja rămâne neschimbat, astfel încât un receptor pe care l-ați creat înainte de acea dată va continua să funcționeze fără a fi nevoie de actualizări.

Unele evenimente adaugă propriul lor bloc suplimentar de nivel superior. De exemplu, **Appointment Booked** adaugă un bloc `appointment` (vezi [Webhook-ul Appointment Booked](#appointment-booked-webhook)), **New Message** adaugă un bloc complet `message` cu textul (vezi [Webhook-ul New Message](#new-message-webhook)), iar **Deliveries** și **Reads** adaugă un bloc scurt `message` doar cu ID-ul și starea mesajului (vezi [Webhook-ul Deliveries and Reads](#deliveries-and-reads-webhook)).

> **Deliveries și Reads vă spun despre ce mesaj este vorba, dar nu și ce conținea acesta.** Acestea conțin un bloc `message` care include `id` și `status` ale mesajului — iar acel `id` este același `messageId` pe care îl returnează [endpoint-ul de trimitere a mesajelor](../api/messages.md#send-a-message), astfel încât să puteți potrivi o confirmare de livrare sau de citire cu mesajul exact pe care l-ați trimis — dar nu conțin corpul mesajului. **Replies** nu conține deloc un bloc `message`. Dacă aveți nevoie de cuvintele trimise sau primite, abonați-vă și la **New Message**.

> **Două lucruri de știut înainte de a scrie receptorul.** Nu există niciun câmp `timestamp` și niciun wrapper `data`. Fiecare bloc se află la nivelul superior al obiectului JSON, așa cum se arată mai sus.

### Cele 22 de evenimente Webhook

Cele 22 de evenimente webhook, cu eticheta de afișare pe care o bifați în aplicație și codul `event` trimis în payload. Codul `event` este un șir scurt care **nu** se potrivește cu eticheta de afișare, deci potriviți receptorul dvs. pe baza codului, nu a etichetei:

| Etichetă de afișare (în aplicație) | Cod `event` în payload | Ce înseamnă |
|---|---|---|
| Contact Created | `contactCreated` | Un contact nou este adăugat în contul dvs. (manual, prin import sau prin API). |
| Contact Paused | `contact_paused` | O conversație cu un contact este întreruptă (botul nu mai răspunde). |
| Contact Resumed | `contact_resumed` | O conversație întreruptă cu un contact este reluată. |
| Contact Do Not Disturb | `contact_do_not_disturb_changed` | Setarea „Nu deranja” a unui contact este activată. |
| Contact Unarchived | `contact_unarchived` | Un contact arhivat trimite un mesaj nou, readucându-l în inbox-ul dvs. activ. |
| New Message | `new_message` | Orice mesaj este adăugat la o conversație pe orice canal — atât mesajele pe care contactul vi le trimite, cât și mesajele pe care AI-ul sau echipa dvs. le trimite acestuia. Acesta este singurul eveniment care conține textul propriu-zis al mesajului (vezi [Webhook-ul New Message](#new-message-webhook)). |
| Replies | `replied` | Un contact răspunde la un mesaj. |
| Reads | `read` | Un contact citește un mesaj (pe canalele care acceptă confirmări de citire). Conține ID-ul mesajului care a fost citit — vezi [Webhook-ul Deliveries and Reads](#deliveries-and-reads-webhook). |
| Deliveries | `delivered` sau `undelivered` | Un mesaj este livrat cu succes unui contact (`undelivered` când livrarea eșuează). Conține ID-ul mesajului — vezi [Webhook-ul Deliveries and Reads](#deliveries-and-reads-webhook). |
| Human Alerted | `humanAlerted` | Botul AI determină că nu poate gestiona o conversație și o marchează pentru atenție umană. |
| Chat Concluded | `chat_concluded` | Botul AI decide că o conversație a ajuns la final (programare efectuată, lead descalificat etc.). |
| Appointment Booked | `booked` | Un contact programează o întâlnire prin sistemul de programări. |
| Credits Spent | `creditsSpent` | Creditele sunt deduse din contul dvs. |
| Credits Recharged | `creditsRecharged` | Creditele sunt adăugate în contul dvs. prin reîncărcare automată sau achiziție manuală. |
| Low Credit Balance | `lowCreditBalance` la o livrare **Test**, `Low Credit Balance` la una reală | Un avertisment timpuriu că soldul de credite a scăzut sub pragul de alertă (100 de credite, dacă nu ați setat altul). Destinat agențiilor ale căror sub-conturi consumă dintr-un fond comun. Conține `balance`, `threshold` și `account_email` în loc de un bloc de contact, este trimis cel mult o dată la 24 de ore cât timp soldul rămâne scăzut și se reactivează imediat ce soldul depășește din nou pragul. |
| Task Created | `taskCreated` | O sarcină este creată. |
| Task Updated | `taskUpdated` | O sarcină se modifică fără a trece într-o etapă de finalizare. |
| Task Completed | `taskCompleted` | O sarcină trece într-o etapă configurată ca etapă de finalizare. |
| Daily Summary Created | `dailySummaryCreated` | Raportul dvs. zilnic este generat. |
| Channel Connected | `channelConnected` | **Încă nu este trimis — selectabil, dar nu este emis momentan. Nu construiți pe baza acestuia.** Destinat momentului în care un canal de mesagerie termină conectarea. |
| Broadcast Started | `broadcastStarted` | O difuzare începe să fie trimisă (starea se schimbă în „Sending”). Se declanșează o dată per pornire, inclusiv când o difuzare întreruptă este reluată. Conține un bloc `broadcast` în loc de un bloc de contact: id, nume, canal, stare, stare anterioară, lista vizată (`list_id`, `list_name`, `is_smart_list`), `scheduled_at`, `total_contacts`. |
| Broadcast Completed | `broadcastCompleted` | O difuzare se termină (starea se schimbă în „Sent” sau „Failed”). Același bloc `broadcast` plus `completed_at` și, când este disponibil, `completion_summary` (`total_sent`, `permanently_failed`, `unique_replied`, `failure_rate`, `had_errors`). Folosiți-le pe ambele pentru a conecta o listă Smart Broadcast la instrumente externe. |

Încă două coduri nu apar niciodată în acea listă deoarece nu vă abonați la ele: `contact_tags_updated`, trimis de un URL de webhook setat pe o etichetă individuală, și `summary_generated`, trimis când un rezumat al chat-ului este scris pentru o etichetă din lista `subscribed_to_tags` a unui webhook.

> **Canal conectat nu este trimis încă.** Apare în lista de evenimente, dar nimic nu îl emite în prezent. Nu construiți funcționalități bazate pe acesta.

Notificările bazate pe etichete și sarcini folosesc propriile forme separate. Consultați [Contact Tags Updated](#contact-tags-updated-webhook) și [Task Completed](#task-completed-webhook).

---

## Webhook pentru Contact Creat

Trimis când se declanșează evenimentul **Contact creat** (un contact nou este adăugat manual, prin import sau prin API).

### Numele evenimentului

`contactCreated`

### Formatul sarcinii utile (payload)

```json
{
  "event": "contactCreated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Întotdeauna `contactCreated` pentru acest eveniment. |
| `contact.id` | ID-ul unic al noului contact. |
| `contact.email` / `contact.phone_number` | Adresa de e-mail și numărul de telefon ale contactului, dacă sunt cunoscute (oricare poate fi gol, în funcție de canal). |
| `contact.first_name` / `contact.last_name` | Numele contactului, dacă este cunoscut. |
| `contact.human_alerted` / `contact.human_alert_reason` | Dacă contactul este marcat pentru atenție umană și motivul. |
| `contact.is_bot_active` | Dacă botul AI este activ în prezent pentru acest contact. |
| `contact.ad_referral` | Atribuirea reclamei Meta Click-to-WhatsApp sau `null` — consultați [Atribuirea reclamelor Click-to-WhatsApp](click-to-whatsapp-attribution.md). |
| `campaign` | Campania sub care a fost creat contactul sau `null`. |
| `agent` | Agentul atribuit contactului sau `null`. |
| `user` | Informații de bază de identitate pentru contul care deține contactul. |

> **Eșantionul de "Test" și un eveniment real arată ușor diferit.** Butonul de test trimite date de substituent (John Doe, o campanie eșantion). Un eveniment real de Contact creat conține detaliile reale ale contactului, iar unele câmpuri pot fi goale în funcție de canal.

---

## Webhook Mesaj nou

Acest webhook se declanșează de fiecare dată când un mesaj este adăugat la o conversație, pe orice canal. Acesta acoperă ambele direcții: mesajele pe care contactul ți le trimite și mesajele pe care AI-ul, echipa ta sau o campanie le trimite acestuia. Este singurul webhook care include textul mesajului, deci acesta este cel pe care trebuie să îl folosești atunci când dorești să oglindești conversațiile într-un sistem extern.

### Numele evenimentului

`new_message`

### Formatul sarcinii utile (payload)

```json
{
  "event": "new_message",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "body": "Hi, are you open on Saturday?",
    "direction": "inbound",
    "status": "received",
    "created_at": "2026-07-30T17:27:06.000Z",
    "channel": "whatsapp_web"
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Întotdeauna `new_message` pentru acest eveniment. Rețineți că acesta este șirul exact trimis — nu este eticheta de afișare „New Message”. |
| `contact` | Contactul căruia îi aparține conversația mesajului. Aceeași formă ca în [Contact Created](#contact-created-webhook). |
| `agent` | Agentul care gestionează conversația (`id` și `name`) sau `null` dacă nu este implicat niciun agent. |
| `user` | Informații de identitate de bază pentru contul care deține conversația. |
| `message.id` | ID-ul unic al mesajului. |
| `message.body` | Textul mesajului. Gol pentru un mesaj care conține doar un atașament (imagine, notă vocală, document). |
| `message.direction` | `inbound` pentru un mesaj de la contact, `outbound` pentru unul trimis de AI-ul dvs. sau de echipa dvs. din inbox și `outbound-api` pentru unul trimis de o campanie, o difuzare, un șablon sau prin API. |
| `message.status` | Unde se află mesajul în ciclul său de viață: `received` pentru primire și `queued` / `sent` / `delivered` / `read` / `failed` / `undelivered` pentru trimitere. Aceasta este starea în momentul în care mesajul a fost creat, deci un mesaj trimis ajunge de obicei aici ca `queued` sau `sent` și ajunge la `delivered` ulterior — folosiți evenimentele **Deliveries** și **Reads** dacă aveți nevoie de acele tranziții ulterioare. Ele conțin același `message.id` ca acest bloc, astfel încât să puteți potrivi tranziția cu acest mesaj (vezi [Webhook-ul Deliveries and Reads](#deliveries-and-reads-webhook)). |
| `message.created_at` | Când a fost creat mesajul, în UTC (ISO 8601). |
| `message.channel` | Canalul prin care a trecut mesajul, de exemplu `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `telegram`, `email` sau `custom`. |

> **Încă nu există un bloc `campaign` în acest payload.** Mesajul nou trimite `contact`, `agent`, `user` și `message`. Blocul `agent` a fost adăugat pe **15 august 2026** și vă indică ce agent gestionează conversația; dacă aveți nevoie și de contextul campaniei, căutați contactul prin API folosind `contact.id`.

> **Înregistrările interne ale AI-ului nu declanșează acest webhook.** Pe lângă mesajele reale, platforma își păstrează propriile rânduri de evidență într-o conversație (apelurile de instrumente ale AI-ului și înregistrările interne ale turnurilor). Acelea nu sunt trimise niciodată — primești doar mesajele care au fost trimise sau primite în mod autentic.

---

## Webhook-ul Deliveries and Reads

Aceste două evenimente raportează ce s-a întâmplat cu un mesaj după ce a părăsit <span data-t="appName">DM Champ</span>: **Deliveries** se declanșează când un mesaj ajunge la contact (sau nu reușește), iar **Reads** se declanșează când contactul îl deschide, pe canalele care acceptă confirmări de citire.

Ambele conțin un bloc `message` cu ID-ul mesajului la care se referă evenimentul, astfel încât să puteți potrivi actualizarea cu mesajul exact pe care l-ați trimis.

### Numele evenimentelor

`delivered` și `undelivered` pentru **Deliveries**, `read` pentru **Reads**.

### Formatul sarcinii utile (payload)

```json
{
  "event": "delivered",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "status": "delivered"
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | `delivered` sau `undelivered` pentru **Deliveries**, `read` pentru **Reads**. |
| `contact` | Contactul căruia i-a fost trimis mesajul. |
| `campaign` | Campania din care face parte contactul sau `null`. |
| `agent` | Agentul care gestionează conversația sau `null`. |
| `user` | Informații de identitate de bază pentru contul care deține datele. |
| `message.id` | ID-ul mesajului la care se referă această actualizare. Este aceeași valoare pe care [endpoint-ul de trimitere a mesajelor](../api/messages.md#send-a-message) o returnează ca `messageId` și același `message.id` pe care îl conține o notificare [New Message](#new-message-webhook). |
| `message.status` | Noua stare, întotdeauna același șir ca `event` (`delivered`, `undelivered` sau `read`). |

> **Cum să potriviți o actualizare cu mesajul trimis.** Stocați `messageId` pe care îl primiți când trimiteți un mesaj prin API. Când sosește o notificare **Deliveries** sau **Reads**, căutați acel ID stocat în `message.id` din payload — aceasta este confirmarea de livrare sau de citire pentru acel mesaj exact.

> **Nu există text de mesaj aici.** Blocul `message` conține doar ID-ul și starea. Abonați-vă la [New Message](#new-message-webhook) dacă aveți nevoie și de corpul mesajului.

> **Blocul `message` este prezent doar atunci când știm despre ce mesaj este vorba.** În cazul rar al unei actualizări pe care nu o putem asocia cu un mesaj stocat, blocul este omis complet în loc să fie trimis gol — deci verificați dacă `message` există înainte de a citi `message.id`.

> **O notificare per schimbare de stare.** Un singur mesaj trimis produce în mod normal o notificare `delivered` și apoi, pe canalele cu confirmări de citire, una `read`. O trimitere eșuată produce `undelivered` în schimb.

---

## Appointment Booked Webhook

Se declanșează atunci când un contact programează o întâlnire. Se declanșează în același mod, indiferent dacă AI-ul a programat-o în timpul unei conversații, dacă ați programat-o manual sau dacă a venit prin API.

### Numele evenimentului

`booked`

### Formatul sarcinii utile (payload)

```json
{
  "event": "booked",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith"
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com"
  },
  "appointment": {
    "appointment_id": "<appointment-id>",
    "start_time": "2026-07-20T15:00:00.000Z",
    "end_time": "2026-07-20T15:30:00.000Z",
    "status": "confirmed",
    "room_name": "Room 1",
    "description": "Discovery call",
    "summary": "30 min intro",
    "google_calendar_event_id": null,
    "event": {
      "id": "<service-id>",
      "event_name": "Intro Call",
      "slot_duration": 30,
      "location": "Zoom",
      "meeting_link": "https://...",
      "event_type": "online"
    }
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Întotdeauna `booked` pentru acest eveniment. |
| `contact` | Persoana care a efectuat programarea. `email` și `phone_number` pot fi goale în funcție de canal. |
| `appointment.appointment_id` | ID-ul unic al programării. |
| `appointment.start_time` / `end_time` | Începutul și sfârșitul intervalului programat, în UTC (ISO 8601). |
| `appointment.status` | Starea curentă a programării. |
| `appointment.room_name` | Camera în care a fost plasată programarea, dacă este utilizată. |
| `appointment.description` / `summary` | Detalii textuale capturate odată cu programarea. |
| `appointment.google_calendar_event_id` | ID-ul Google Calendar pentru evenimentul sincronizat. Este adesea `null` în webhook-ul Appointment Booked, deoarece evenimentul din calendar este creat în același moment în care este trimisă notificarea — re-preluați programarea prin `appointment_id`-ul său puțin mai târziu dacă aveți nevoie și așteptați-vă la un `null` permanent pe conturile fără un Google Calendar conectat. |
| `appointment.event` | Serviciul care a fost programat: nume, lungimea intervalului, locație, link de întâlnire, tip. |

> **`google_calendar_event_id` este adesea `null` în acest webhook, și acest lucru este normal.** Evenimentul Google Calendar este creat în același moment în care este trimisă această notificare, deci ID-ul de obicei nu este încă gata. Regăsiți programarea după `appointment_id` puțin mai târziu dacă aveți nevoie de ea. Rămâne `null` permanent dacă contul nu are un Google Calendar conectat, deci nu așteptați la nesfârșit.

> **Butonul "Test" nu include blocul `appointment`.** Folosiți-l pentru a confirma că punctul final răspunde, apoi faceți o programare reală pentru a vedea sarcina utilă completă.

> **Două cazuri în care acest webhook nu se declanșează:** programările importate dintr-un calendar extern și rezervările care provin prin integrarea Formitable.

---

## Webhook pentru actualizarea etichetelor de contact

Se declanșează atunci când o etichetă este **aplicată** unui contact, iar acea etichetă are un URL de webhook configurat pentru agentul sau campania de care aparține contactul.

### Numele evenimentului

`contact_tags_updated`

### Când se declanșează

- O etichetă este aplicată unui contact care are un agent atribuit, o campanie atribuită sau ambele.
- Cel puțin una dintre etichetele aplicate are un URL de webhook setat în fila Etichete a acelui agent sau acelei campanii.

Dacă un contact le are pe ambele și etichetele campaniei conțin URL-uri de webhook, acelea au prioritate; în caz contrar, se folosesc cele ale agentului.

Dacă mai multe etichete cu URL-uri de webhook diferite sunt aplicate în aceeași actualizare, se trimite o cerere per URL, fiecare conținând doar etichetele care corespund acelui URL.

**Eliminarea unei etichete nu trimite niciodată o cerere.** Majoritatea utilizatorilor direcționează aceste URL-uri către o acțiune — colectarea unui depozit, rezervarea unui interval, alertarea unui reprezentant — astfel încât eliminarea unei etichete de pe un contact ar fi putut declanșa din nou acea acțiune. Acest lucru nu mai este posibil. O eliminare apare totuși în `removed_tags` atunci când are loc în aceeași actualizare cu o aplicare care merge către același URL, astfel încât o automatizare care citește ambele matrice păstrează imaginea completă; ceea ce nu va vedea niciodată este o cerere cauzată doar de o eliminare. (Modificat la **12 august 2026**. Înainte de această dată, eliminările trimiteau și ele o cerere.)

### Formatul sarcinii utile (payload)

```json
{
  "event": "contact_tags_updated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "is_bot_active": true,
    "ad_referral": {
      "ctwa_clid": "ARAbc123...",
      "source_id": "120210000000000",
      "source_type": "ad",
      "source_url": "https://fb.me/xxxx",
      "headline": "Get 20% off today",
      "body": "Message us now to claim your discount",
      "channel": "whatsapp"
    }
  },
  "added_tags": ["qualified-lead"],
  "removed_tags": ["new-lead"],
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Întotdeauna `contact_tags_updated` pentru acest webhook. |
| `contact.id` | ID-ul unic al contactului ale cărui etichete s-au modificat. |
| `contact.email` / `contact.phone_number` | E-mailul/telefonul contactului, dacă este cunoscut. |
| `contact.first_name` / `contact.last_name` | Numele contactului. |
| `contact.human_alerted` | Dacă contactul este marcat în prezent pentru atenția unui operator uman. |
| `contact.is_bot_active` | Dacă botul AI este activ în prezent în conversația acestui contact. |
| `contact.ad_referral` | Prezent doar atunci când contactul v-a contactat pentru prima dată printr-o reclamă sau postare Meta Click-to-WhatsApp (CTWA). `null` în caz contrar. |
| `added_tags` | Matrice de nume de etichete aplicate în această actualizare. Niciodată goală — o aplicare este cea care declanșează cererea. |
| `removed_tags` | Matrice de nume de etichete eliminate în aceeași actualizare, dacă există. O eliminare de una singură nu trimite nimic. |
| `agent` | Agentul care gestionează conversația contactului (`id` și `name`), sau `null` dacă nu este implicat niciun agent. Adăugat pe **15 august 2026**. |
| `user` | Informații de bază de identitate pentru contul care deține contactul. |

### Testarea unui webhook de etichetă

Lângă câmpul URL-ului webhook-ului din fila Etichete există un buton **Test**. Acesta trimite imediat un payload de probă către acel URL, astfel încât să puteți confirma că automatizarea dvs. îl primește înainte de a aștepta o conversație reală.

Testul trimite aceeași formă `contact_tags_updated` prezentată mai sus, folosind un contact substituent, cu eticheta pe care o testați în `added_tags` și un `removed_tags` gol. Ceea ce vede automatizarea dvs. în test este ceea ce va vedea în producție.

Două lucruri de știut:

- **Salvați mai întâi eticheta.** Testul caută eticheta după numele salvat, deci o etichetă nouă sau o redenumire nesalvată nu poate fi testată încă. Butonul rămâne gri până când numele de pe ecran corespunde cu cel salvat.
- **Un test eșuat nu afectează webhook-ul dvs.** Testele nu contribuie niciodată la oprirea automată după eșecuri repetate descrisă în [Fiabilitatea Webhook-urilor](#webhook-reliability).

Dacă testul eșuează, mesajul vă spune ce a răspuns endpoint-ul dvs. (de exemplu, un `404` sau `500`), ceea ce este de obicei suficient pentru a identifica un URL greșit sau un flux de lucru care nu este activat.

---

## Webhook pentru sarcină finalizată

> **Doar pentru referință.** Webhook-urile de sarcini (ca date) sunt documentate aici pentru dezvoltatori; evenimentele **Task Created**, **Task Updated** și **Task Completed** sunt selectabile în lista standard de evenimente din formularul de webhook ca oricare alt eveniment — consultați [Evenimente de declanșare disponibile](#available-trigger-events) și [Cele 22 de evenimente Webhook](#the-22-webhook-events).

Acest payload este trimis atunci când o sarcină trece într-o etapă marcată ca etapă de finalizare. O sarcină care se mută între etape care nu sunt de finalizare trimite în schimb formatul `taskUpdated`.

### Numele evenimentului

`taskCompleted`

### Când se declanșează

- O sarcină este actualizată.
- Valoarea `stage` a acesteia s-a modificat față de valoarea anterioară.
- Noua etapă este configurată ca etapă de finalizare în setările etapelor de sarcini ale contului.

### Formatul sarcinii utile (payload)

```json
{
  "event": "taskCompleted",
  "contact": {
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<task-id>",
    "title": "Follow up with Jane",
    "description": "Confirm pricing and send proposal",
    "type": "follow_up",
    "priority": "high",
    "stage": "<stage-id>",
    "due_date": "2026-01-20T15:00:00Z",
    "source": "ai",
    "source_detail": "<source-detail>",
    "campaign_id": "<campaign-id>",
    "linked_human_alert": "<human-alert-id>",
    "tags": ["qualified-lead"],
    "notes": "Customer requested a callback"
  }
}
```

| Câmp | Descriere |
|---|---|
| `event` | Întotdeauna `taskCompleted` pentru acest webhook. Același format de payload este trimis ca `taskUpdated` atunci când o sarcină se modifică fără a intra într-o etapă de finalizare. |
| `contact` | Contactul legat de sarcină, dacă există. `null` când nu este legat. |
| `contact.human_alert_reason` | Motivul pentru care contactul a fost marcat pentru atenție umană, dacă este cazul. |
| `user` | Informații de identitate de bază pentru contul care deține sarcina. |
| `message.id` | ID-ul unic al sarcinii. |
| `message.title` / `description` | Titlul și descrierea sarcinii. |
| `message.type` | Tipul sarcinii (de exemplu, `follow_up`, `call`, `custom`). |
| `message.priority` | Prioritatea sarcinii (`low`, `medium`, `high`). |
| `message.stage` | ID-ul etapei în care se află acum sarcina. |
| `message.due_date` | Data scadentă a sarcinii, dacă este setată. |
| `message.source` | Ce a creat sarcina (`ai`, `manual`, `api`). |
| `message.source_detail` | Detalii suplimentare despre sursă. |
| `message.campaign_id` | ID-ul campaniei legate sau `null`. |
| `message.linked_human_alert` | ID-ul alertei umane legate, dacă există. |
| `message.tags` | Etichete aplicate sarcinii. |
| `message.notes` | Note libere despre sarcină. |

---

## Dezactivarea (sau ștergerea) unui webhook

Fiecare webhook are un comutator pornit/oprit, chiar pe rândul său. Oprirea unuia (**off**) îl împiedică să primească evenimente, dar păstrează tot ce ați configurat — URL-ul, evenimentele, orice secret de semnare. Reporniți-l și va continua de unde a rămas; nimic din ce s-a întâmplat în timp ce era oprit nu va fi livrat ulterior.

Folosiți această opțiune atunci când doriți ca livrările să se oprească pentru o perioadă: punctul final este în curs de reconstrucție, depanați o integrare zgomotoasă sau întrerupeți o automatizare.

**Ștergerea** unui webhook (pictograma coș de gunoi de pe rândul său) îl elimină definitiv, inclusiv secretul său de semnare. Dacă doriți doar ca livrările să se oprească, opriți-l în schimb — ștergerea este pentru când ați terminat complet cu acel endpoint.

> **Acest lucru nu este același lucru cu dezactivarea automată a unui webhook.** Dacă dezactivăm webhook-ul dumneavoastră după eșecuri repetate (consultați [Fiabilitatea Webhook](#webhook-reliability)), comutatorul de mai sus nu îl va reactiva. Odată ce punctul final este remediat, editați webhook-ul și salvați-l cu o adresă URL modificată (orice modificare a URL-ului îl reactivează) sau apelați [punctul final de reactivare](../api/webhooks.md) prin API — sau contactați asistența și îl vom reactiva noi pentru dumneavoastră.

---

## Payload-uri semnate (Verificarea faptului că un webhook provine într-adevăr de la noi)

Oricine află URL-ul webhook-ului dvs. ar putea trimite o cerere falsă către acesta. Dacă acționați automat pe baza webhook-urilor — actualizarea facturării, crearea de înregistrări CRM — activarea **semnării** vă permite să verificați dacă fiecare cerere provine cu adevărat de la noi.

Semnarea este **opțională și dezactivată implicit**, și o activați pentru fiecare webhook, din vizualizarea de editare a acelui webhook (deschideți rândul unui webhook salvat).

### Activarea semnării

1. Deschideți webhook-ul (Setări → Integrări → Webhook-uri → faceți clic pe rândul webhook-ului dvs.).
2. În secțiunea **Secret de semnare**, faceți clic pe **Generare**.
3. Copiați secretul (începe cu `whsec_`) și stocați-l în sistemul dvs. de primire. Tratați-l ca pe o parolă.

Puteți reveni oricând pentru a dezvălui, copia, roti sau dezactiva secretul din același panou.

### Ce trimitem

Odată ce semnarea este activată, fiecare livrare pentru acel webhook conține aceste două anteturi HTTP suplimentare:

| Antet | Semnificație |
|---|---|
| `X-Webhook-Signature` | Semnătura, sub forma `v1=<hex>`. |
| `X-Webhook-Timestamp` | Când am trimis-o, sub formă de marcaj temporal Unix în secunde. |

Aceste trei sunt prezente la **fiecare** livrare, semnată sau nu:

| Antet | Semnificație |
|---|---|
| `X-Webhook-Delivery` | Un ID unic pentru acest eveniment. Rămâne același pe parcursul reîncercărilor, deci acesta este elementul după care puteți elimina duplicatele. |
| `X-Webhook-Attempt` | A câta încercare este aceasta (`1` este prima încercare). |
| `X-Webhook-Event` | Numele evenimentului, astfel încât să puteți direcționa fluxul fără a citi corpul mesajului. |

### Cum se verifică

Semnătura este un HMAC-SHA256 al șirului `<timestamp>.<raw request body>`, folosind secretul tău de semnare drept cheie.

**Verificați în raport cu corpul cererii brute — octeții exacți pe care i-ați primit.** Dacă framework-ul dvs. analizează JSON-ul și îl reserializează înainte de verificare, octeții se pot modifica și semnătura nu se va potrivi.

Exemplu Node.js:

```js
const crypto = require("crypto");

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"]; // "v1=<hex>"

  // Reject anything older than 5 minutes so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(Buffer.from(signature.replace("v1=", "")), Buffer.from(expected));
}
```

Exemplu Python:

```python
import hashlib, hmac, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    timestamp = headers["X-Webhook-Timestamp"]
    signature = headers["X-Webhook-Signature"].replace("v1=", "")

    # Reject anything older than 5 minutes so a captured request can't be replayed later.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()

    return hmac.compare_digest(signature, expected)
```

> **Compară semnăturile cu o funcție sigură la sincronizare (timing-safe)** (`timingSafeEqual` / `compare_digest`), nu `==`. Nu costă nimic și evită o clasă subtilă de atacuri.

### Rotarea secretului

Dă clic pe **Rotește** pentru a înlocui secretul. Comutarea este imediată: următoarea livrare este semnată doar cu noul secret. Dacă endpoint-ul tău este activ, acceptă **atât** secretul vechi, cât și pe cel nou timp de câteva minute, în timp ce îl implementezi pe cel nou.

Dezactivarea semnării oprește pur și simplu trimiterea antetelor de semnătură.

---

## Reîncercarea livrărilor eșuate

În mod implicit, o livrare care eșuează nu este reîncercată — dacă sistemul dvs. este indisponibil în acel moment, evenimentul respectiv este pierdut.

Activează **Reîncearcă livrările eșuate** pentru un webhook (în formularul de creare/editare) și vom continua să încercăm:

| Încercare | Când |
|---|---|
| 1 | Imediat |
| 2 | 1 minut mai târziu |
| 3 | 5 minute mai târziu |
| 4 | 30 minute mai târziu |
| 5 | 2 ore mai târziu |

Acest interval însumează aproximativ **2 ore și 40 de minute**, astfel încât un webhook poate supraviețui unei ferestre de mentenanță sau unei întreruperi scurte din partea dvs.

**Ce se reîncearcă:** probleme temporare — serverul dvs. returnează o eroare 5xx, un timeout sau o eroare de conexiune.

**Ce nu facem:** dacă endpoint-ul tău respinge cererea (orice eroare 4xx), nu reîncercăm — trimiterea aceleiași cereri din nou ar produce doar aceeași respingere.

**Ce evenimente se reîncearcă:** webhook-urile de etichete (`contact_tags_updated`), cele trei evenimente de sarcină și rezumatul zilnic. Restul sunt trimise o singură dată, deci pentru acelea comutatorul nu are nicio acțiune. Fiecare eveniment conține în continuare `X-Webhook-Delivery`, deci o singură regulă de eliminare a duplicatelor le acoperă pe toate.

> **Activează reîncercările doar dacă endpoint-ul tău este idempotent.** Reîncercările înseamnă că același eveniment poate ajunge de mai multe ori. Folosește antetul `X-Webhook-Delivery` pentru a recunoaște o repetiție: acesta rămâne același la fiecare încercare pentru un eveniment, astfel încât poți ignora în siguranță un ID pe care l-ai procesat deja.

Reîncercările interacționează cu oprirea automată după eșecuri repetate (consultați [Fiabilitatea webhook-urilor](#webhook-reliability)) exact așa cum v-ați dori: contorul de eșecuri numără o **livrare completă**, doar după ce fiecare reîncercare a fost epuizată — nu fiecare încercare individuală.

---

## Fiabilitatea Webhook-urilor

- <span data-t="appName">DM Champ</span> trimite webhook-uri printr-o conexiune securizată (HTTPS). Asigurați-vă că adresa web pe care o furnizați utilizează HTTPS.
- Dacă sistemul dumneavoastră returnează o eroare, livrarea este considerată eșuată.
- Monitorizați timpul de funcționare al sistemului de primire pentru a evita pierderea evenimentelor.
- Pentru fluxuri de lucru critice, activați [Reîncercarea livrărilor eșuate](#retrying-failed-deliveries) și luați în considerare și un mecanism de rezervă.

> **Webhook-urile sunt dezactivate automat după eșecuri repetate.** Dacă URL-ul webhook-ului dumneavoastră eșuează în mod repetat (aproximativ 5 erori consecutive sau 3 consecutive pentru erori de tip configurare), <span data-t="appName">DM Champ</span> nu mai trimite automat evenimente către acel URL. Pentru a-l reactiva odată ce punctul final este funcțional: editați webhook-ul și salvați-l cu o adresă URL modificată (orice modificare a URL-ului îl reactivează) sau utilizați [punctul final de reactivare](../api/webhooks.md) prin API — salvarea cu același URL nu este suficientă. Asistența îl poate reactiva, de asemenea, pentru dumneavoastră.

---

## Depanare

| Problemă | Soluție |
|---|---|
| Webhook-ul nu se declanșează | Mai întâi, verificați dacă webhook-ul nu este **oprit** pe rândul său. Apoi, confirmați că evenimentele corecte sunt selectate și că URL-ul dvs. este accesibil de pe internet. |
| Evenimentul de test funcționează, dar evenimentele reale nu | Asigurați-vă că tipul specific de eveniment este activat. Dacă ați așteptat o solicitare la aplicarea unei etichete, rețineți că `subscribed_to_tags` nu limitează evenimentele unui webhook la o etichetă — ci doar restrânge etichetele care generează o notificare de rezumat al conversației. Pentru a primi o solicitare când este aplicată o etichetă specifică, setați un URL de webhook pe acea etichetă în fila **Etichete** a agentului (sau campaniei) — consultați [Webhook pentru actualizarea etichetelor de contact](#contact-tags-updated-webhook). |
| Nu ajunge nimic în n8n / Make / Zapier | Probabil utilizați **URL-ul de test** al platformei, care ascultă doar un singur eveniment imediat după ce faceți clic pe „Ascultă evenimentul de test”. Pentru evenimente live, salvați **URL-ul de producție** și comutați fluxul de lucru pe **Activ**. |
| Primiți evenimente duplicate | Verificați dacă există mai multe webhook-uri care indică spre același URL. Dacă opțiunea **Reîncearcă livrările eșuate** este activată, o repetare este de așteptat ori de câte ori punctul final a acceptat un eveniment, dar nu a reușit să răspundă la timp — eliminați duplicatele pe `X-Webhook-Delivery`. |
| Verificarea semnăturii eșuează mereu | Aproape întotdeauna deoarece corpul a fost re-serializat înainte de verificare. Verificați în raport cu corpul **brut** al cererii, semnați `<timestamp>.<body>` și confirmați că utilizați secretul curent dacă l-ați rotit recent. |
| Reîncercările nu au loc | Reîncercările sunt dezactivate, cu excepția cazului în care sunt activate pentru acel webhook specific. Nu reîncercăm răspunsurile 4xx. |
| Blocul `campaign` este întotdeauna `null` | Este de așteptat dacă contul dvs. utilizează agenți: contactele sunt alocate unui agent, nu unei campanii. Citiți blocul `agent` în schimb — consultați [Formatul datelor webhook](#webhook-data-format). |
| Datele sunt goale sau malformate | Verificați dacă sistemul dvs. de primire acceptă JSON. Verificați jurnalele serverului pentru erori de parsare. |
| URL-ul webhook-ului returnează erori | Testați URL-ul cu un instrument precum Postman sau [webhook.site](https://webhook.site). |
| Webhook-ul a încetat să se mai declanșeze complet după o întrerupere | Eșecurile repetate dezactivează automat un webhook. Salvarea din nou nu îl reactivează — reparați punctul final, apoi contactați asistența. |
| Salvarea sau Testarea oferă o eroare de permisiune | Aveți nevoie de permisiunea „edit” pentru Integrări. Cereți proprietarului contului să v-o acorde. |
| Lista `subscribed_to_tags` a unui webhook a revenit goală | `subscribed_to_tags` nu limitează evenimentele unui webhook la o etichetă — ci doar restrânge etichetele care generează o notificare de rezumat al conversației. Editarea din formularul de webhook nu mai șterge acea listă (remediat la 21 iulie 2026). Dacă un webhook și-a pierdut lista înainte de acea dată, setați `subscribed_to_tags` din nou prin [API-ul Webhooks](../api/webhooks.md) — consultați [Declanșatoare webhook bazate pe etichete](#tag-based-webhook-triggers). |

---

## Pașii următori

- [Integrare GoHighLevel](ghl-integration.md) — utilizați webhook-uri pentru a integra <span data-t="appName">DM Champ</span> cu GHL.
- [Acces API](api-access.md) — combinați webhook-urile cu API-ul pentru automatizări puternice.
- [Utilizarea etichetelor pentru a marca contactele](../get-started/creating-tags.md) — configurați etichete care declanșează webhook-urile dumneavoastră.
