---
title: "Prezentare generală a webhookurilor"
description: "Cum livrează ThunderPhone evenimente în timp real, cum verificați semnăturile și cum se compară modelele de livrare vechi și bazate pe endpointuri."
---

ThunderPhone trimite cereri HTTP `POST` către serverul dumneavoastră atunci când se
întâmplă lucruri în timpul unui apel — începe un apel de intrare, se încheie un apel, se finalizează
o rulare de evaluare, se declanșează o alertă și așa mai departe. Există **două modele
de livrare**:

<CardGroup cols={2}>
  <Card title="Endpointuri webhook (recomandat)" icon="bolt" href="/ro/webhooks/endpoints">
    URL-uri multiple, secrete per endpoint, filtre de evenimente per endpoint
    și reîncercări automate.
    Gestionați prin `GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints`.
  </Card>
  <Card title="Webhook legacy cu un singur URL" icon="link" href="/api-reference/organizations#legacy-single-url-webhook">
    Un URL per organizație. Include evenimentele din ciclul de viață al apelului, inclusiv
    schimburile de configurare **blocante**. Gestionat prin `GET/PUT /v1/webhook`.
  </Card>
</CardGroup>

Toate tipurile de evenimente enumerate în [catalogul de evenimente](/ro/webhooks/events) sunt
livrate prin endpointuri webhook. Cele șase evenimente din ciclul de viață al apelului
(`telephony.incoming`, `telephony.complete`, `telephony.tool`,
`web.incoming`, `web.complete`, `web.tool`) sunt trimise **și** către
webhookul legacy cu un singur URL — dacă aveți atât un URL legacy, cât și un
endpoint corespunzător, primiți evenimentul pe **ambele** căi. Comportamentul blocant
([schimbul de configurare `telephony.incoming` / `web.incoming`](/ro/webhooks/call-incoming) și
[dispecerizarea instrumentelor](/ro/tools/overview) în modul webhook)
există exclusiv pe calea legacy; fiecare livrare către endpoint este o
notificare fără așteptarea răspunsului.

## Formatul încărcăturii utile

Livrările către endpointuri sunt un obiect JSON cu `data`, `event_id` și
`type`:

```json
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

`event_id` este unic pentru fiecare eveniment emis. Este identic între reîncercări
**și** între toate endpointurile care primesc evenimentul — eliminați duplicatele pe baza acestuia.

Webhookul legacy cu un singur URL trimite aceleași valori `type` și `data`, însă
**fără** `event_id`:

```json
{
  "type": "telephony.incoming",
  "data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}
```

În tranzit, fiecare corp este serializat canonic — cheile sunt sortate
alfabetic, fără spații albe, în UTF-8. Exemplele formatate pentru afișare din
această documentație sunt doar pentru lizibilitate.

Consultați [Catalogul de evenimente](/ro/webhooks/events) pentru lista completă a tipurilor de evenimente
și a câmpurilor încărcăturii utile.

## Verificarea semnăturii

Fiecare cerere include două semnături, ambele HMAC-SHA256 cu cheia
`secret` a endpointului (sau `secret` webhook la nivel de organizație pentru
livrările vechi):

- `X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>` semnează
  marcajul temporal, metoda, calea și interogarea, precum și corpul brut. Verificați-o
  pe aceasta și respingeți cererile al căror `t` diferă cu mai mult de **5 minute**
  față de ceasul dumneavoastră, astfel încât o cerere capturată să nu poată fi redifuzată ulterior.
  Reîncercările sunt semnate din nou când sunt trimise.
- `X-ThunderPhone-Signature` semnează numai corpul brut. Este trimisă în continuare,
  nemodificată, astfel încât verificatorii existenți să funcționeze în continuare.

### Pași

1. Citiți antetul, metoda, calea brută și interogarea, precum și corpul
   brut **înainte** de orice analiză.
2. Calculați HMAC-SHA256 hexazecimal al
   `<t>\n<METHOD>\n<path and query>\n<body>` folosind secretul dumneavoastră.
3. Respingeți solicitarea dacă `t` diferă cu mai mult de 300 de secunde sau dacă
   rezultatul nu corespunde cu `v1` într-o comparare în timp constant.

Corpurile sunt serializarea JSON canonică (chei sortate, separatoare compacte) și semnăm exact octeții pe care îi transmitem. [Ghidul de verificare](/ro/guides/verify-webhook-signatures) conține șirul semnat exact, un exemplu detaliat, cod fără SDK și antetul vechi.

<CodeGroup>
```python Python (Flask)
from flask import Flask, abort, request
from thunderphone import verify_signature

app = Flask(__name__)

@app.post("/thunderphone-webhook")
def handle():
    query = request.query_string.decode()
    if not verify_signature(
        request.headers.get("X-ThunderPhone-Signature-V2"),
        secret=WEBHOOK_SECRET,
        method=request.method,
        path=request.path + (f"?{query}" if query else ""),
        body=request.get_data(),  # raw bytes
    ):
        abort(401)
    event = request.get_json()
    # dispatch on event["type"] …
    return "", 204
```

```javascript Node.js (Express)
import express from "express";
import { verifySignature } from "@thunderphone/sdk";

const app = express();
app.post(
  "/thunderphone-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ok = verifySignature({
      header: req.header("X-ThunderPhone-Signature-V2"),
      secret: process.env.WEBHOOK_SECRET,
      method: req.method,
      path: req.originalUrl,
      body: req.body,
    });
    if (!ok) return res.sendStatus(401);
    const event = JSON.parse(req.body.toString("utf8"));
    // dispatch on event.type …
    res.sendStatus(204);
  },
);
```
</CodeGroup>

## Semantica livrării

Aceste semantici se aplică livrărilor către **endpoint**. Webhookul moștenit cu un singur URL
este o singură încercare sincronă, fără reîncercări, cu excepția
schimbului de configurație pentru apeluri telefonice [`telephony.incoming`](/ro/webhooks/call-incoming),
care este reîncercat o dată.

<AccordionGroup>
  <Accordion title="Reîncercări">
    Fiecare eveniment este încercat imediat o dată. Orice răspuns `2xx`
    confirmă livrarea. Pentru orice alt rezultat (altul decât 2xx,
    eroare de conexiune, expirare a timpului), reîncercăm la **1 min., 5 min., 30 min., 2 h, 6 h,
    12 h și 24 h după prima încercare** — 8 încercări pe durata a
    24 de ore. Dacă toate încercările eșuează, livrarea se oprește, iar endpointul
    este marcat cu `status="failing"` în
    [endpointurile webhook](/ro/webhooks/endpoints); trimitem un e-mail proprietarilor
    și administratorilor organizației dumneavoastră și afișăm acest lucru în tabloul de bord. Returnați `2xx` de îndată ce
    încărcătura utilă este acceptată în mod durabil; procesați-o asincron.
    Trimiterile de test din API-ul de testare a endpointului primesc o reîncercare la aproximativ un minut după
    prima încercare și nu modifică niciodată starea endpointului.
  </Accordion>

  <Accordion title="Ordonare">
    Ordonarea livrărilor se face după principiul efortului maxim. În
    practică, livrăm în ordinea în care sunt emise evenimentele, însă
    reîncercările pot schimba ordinea în caz de eșec.
    Eliminați întotdeauna duplicatele și reconciliați după `call_id` / id-ul obiectului.
  </Accordion>

  <Accordion title="Duplicate">
    Livrarea este **cel puțin o dată**: o reîncercare după un răspuns pe care nu l-am
    primit poate duplica un eveniment. Fiecare reîncercare conține același
    `event_id`, așadar stocați id-urile procesate și ignorați repetările. `event_id` este
    partajat și între endpointuri — două endpointuri abonate la același
    eveniment primesc același `event_id`.
  </Accordion>

  <Accordion title="Expirări ale timpului">
    Livrările către endpoint au o limită de timp de **30 s** pentru fiecare încercare. Pe
    calea moștenită, cererile blocante care controlează comportamentul apelurilor în timp real — schimbul de
    configurație [`telephony.incoming` / `web.incoming`](/ro/webhooks/call-incoming)
    — sunt limitate la **10 s** pentru prima încercare a unui apel telefonic
    și la **13 s** pentru întregul schimb, inclusiv unica sa
    reîncercare, precum și la **10 s** pentru o sesiune de widget. Un răspuns lent întârzie
    preluarea apelului, astfel încât urmăriți să răspundeți în câteva secunde. [Transmiterea instrumentelor](/ro/tools/overview) în modul webhook permite 20 s
    în mod implicit, iar declarațiile de instrumente pot seta un `timeout` de nivel superior.
  </Accordion>

  <Accordion title="IP-uri sursă">
    Webhookurile trimise provin din intervalul de IP-uri cloud al ThunderPhone.
    Dacă paravanul dumneavoastră de protecție necesită o listă de permisiuni, contactați asistența, iar noi
    vă vom comunica intervalele actuale.
  </Accordion>
</AccordionGroup>

## Alegerea între webhookurile moștenite și cele bazate pe endpointuri

| Funcționalitate | Versiune moștenită (`/v1/webhook`) | Endpointuri (`/v1/developer/webhook-endpoints`) |
|---------|------------------------|----------------------------------------------|
| Număr de URL-uri | 1 per organizație | Mai multe per organizație |
| Acoperire evenimente | Doar `telephony.*` / `web.*` | Toate cele 10 tipuri de evenimente |
| Filtru de evenimente | — | Per endpoint |
| Reîncercări | Niciuna, cu excepția uneia pentru schimbul de configurare a apelului telefonic | 8 încercări în 24 h |
| Plic | `type` + `data` | `type` + `data` + `event_id` |
| Rotația secretului | Înlocuiește secretul unic | Secret per endpoint |
| Dezactivare fără ștergere | `PUT /v1/webhook` cu `{"url": ""}` | `status=disabled` |
| Vizibilitatea stării | — | `active` / `disabled` / `failing` |
| Schimb de configurare blocant | Da ([`telephony.incoming` / `web.incoming`](/ro/webhooks/call-incoming)) | Niciodată — doar notificări |
| Recomandat pentru | Configurarea dinamică a apelurilor | Consumarea evenimentelor în producție |

Integrările noi trebuie să consume evenimente prin webhookuri bazate pe
endpointuri. Păstrați (sau adăugați) un URL moștenit numai dacă configurați apelurile
dinamic în momentul preluării sau utilizați dispecerizarea instrumentelor în modul webhook — aceste
schimburi cerere/răspuns funcționează numai pe ruta moștenită.

---

## Asociate

<CardGroup cols={2}>
  <Card title="Catalog de evenimente" icon="list" href="/ro/webhooks/events">
    Toate tipurile de evenimente și încărcăturile lor utile.
  </Card>
  <Card title="Endpointuri webhook" icon="bolt" href="/ro/webhooks/endpoints">
    Gestionați mai multe endpointuri, filtre de evenimente și secrete.
  </Card>
  <Card title="telephony.incoming / web.incoming" icon="phone" href="/ro/webhooks/call-incoming">
    Cererea blocantă la care serverul dumneavoastră trebuie să răspundă pentru a configura apelurile.
  </Card>
  <Card title="telephony.complete / web.complete" icon="phone" href="/ro/webhooks/call-complete">
    Încărcătură utilă post-apel cu transcriere, înregistrare și metrici.
  </Card>
</CardGroup>
