Ringhum.

Sviluppatori

Webhook

Ricevi notifiche HTTPS firmate quando le chiamate terminano, vengono presi messaggi, cambiano appuntamenti, ordini e prenotazioni, oppure termina una campagna, e verifica che ognuna provenga davvero da Ringhum.

6 min di lettura Aggiornato il 24 settembre 2026

In questa pagina

Un webhook invia una richiesta HTTPS al tuo server nel momento in cui accade qualcosa nel tuo spazio di lavoro. Usa i webhook invece di interrogare periodicamente la API: quando una chiamata termina, ricevi subito il riepilogo, l'esito, i dettagli raccolti e la trascrizione. Ogni recapito è firmato con un segreto che solo tu e Ringhum conoscete, così il tuo server può rifiutare qualsiasi cosa non provenga da Ringhum.

Aggiungi un endpoint

Solo il Proprietario e gli Amministratori dello spazio di lavoro possono aggiungere, testare e rimuovere endpoint.

  1. Apri Sviluppatori nella barra laterale.
  2. Nella scheda Webhook, clicca su Aggiungi endpoint.
  3. Inserisci l'URL dell'endpoint. Deve iniziare con https://.
  4. In Eventi, seleziona gli eventi che vuoi. call.ended è già selezionato per te.
  5. Clicca su Aggiungi endpoint.
  6. Copia il segreto di firma dal riquadro verde (inizia con whsec_) e conservalo sul tuo server. Clicca su Fatto.

Importante: il segreto di firma viene mostrato una sola volta. Se lo perdi, rimuovi l'endpoint e aggiungilo di nuovo per ottenere un nuovo segreto.

Puoi aggiungere tutti gli endpoint di cui hai bisogno. I webhook coprono ogni assistente nello spazio di lavoro. Puoi anche gestire gli endpoint tramite la API, con POST /webhooks e una chiave che abbia l'ambito write.

Eventi

Evento Quando viene inviato
call.started Una chiamata ha ricevuto risposta da un assistente
call.ended Una chiamata è terminata ed è stata riassunta (include trascrizione e riepilogo)
call.transferred Una chiamata è stata trasferita a una persona
message.taken L'assistente ha preso un messaggio
appointment.booked L'assistente ha prenotato un appuntamento
appointment.rescheduled Un appuntamento è stato spostato a un nuovo orario
appointment.cancelled Un appuntamento è stato annullato
order.created È stato effettuato un ordine (da un assistente, manualmente o tramite la API)
order.updated Un ordine è passato a un nuovo stato
order.cancelled Un ordine è stato annullato
reservation.created È stata effettuata una prenotazione di camera (da un assistente, manualmente o tramite la API)
reservation.updated Una prenotazione è passata a un nuovo stato (confermata, check-in effettuato, check-out effettuato, non presentato)
reservation.cancelled Una prenotazione è stata annullata
campaign.completed Una campagna in uscita ha terminato di chiamare il suo elenco
test.ping Hai cliccato su Invia test

Come si presenta un recapito

Ogni recapito è una POST con un corpo JSON e questi header:

POST https://example.com/hooks/ringhum
Content-Type: application/json
User-Agent: Ringhum-Webhooks/1.0
X-Ringhum-Event: call.ended
X-Ringhum-Timestamp: 1789250000
X-Ringhum-Signature: v1=5f1a…

{
  "id": "evt_8f2k…",
  "type": "call.ended",
  "created_at": "2026-09-24T14:03:11+00:00",
  "data": {
    "call_id": 4812,
    "direction": "inbound",
    "from": "+14155550132",
    "to": "+14155550100",
    "assistant_id": 3,
    "status": "completed",
    "outcome": "message_taken",
    "sentiment": "neutral",
    "duration_seconds": 94,
    "summary": "Caller asked for a quote for a kitchen repair…",
    "extracted": { "name": "Dana Lee", "reason": "Quote" },
    "transcript": [
      { "role": "assistant", "content": "Hello, you've reached…" },
      { "role": "user", "content": "Hi, I'd like a quote…" }
    ]
  }
}

L'oggetto data dipende dall'evento:

  • call.ended e message.taken: i campi della chiamata sopra.
  • call.started e call.transferred: call_id, direction, from, to, assistant_id, status e started_at.
  • appointment.*: appointment_id, title, status, starts_at, ends_at, timezone, customer (nome, telefono, email), contact_id, service, staff, call_id e notes.
  • order.*: order_id, number, status, fulfillment, customer, address, items con opzioni e prezzi, currency, subtotal, fee, total, source, call_id e, per gli annullamenti, cancel_reason.
  • reservation.*: reservation_id, number, status, room, check_in, check_out, nights, adults, children, guest, currency, nightly, total e source.
  • campaign.completed: campaign_id, name e i conteggi di avanzamento della campagna.

Nota: quando l'assistente prenota un appuntamento durante una chiamata, puoi ricevere appointment.booked due volte. Uno viene inviato mentre la prenotazione viene effettuata, con i campi dell'appuntamento. L'altro viene inviato dopo che la chiamata è stata riassunta, con i campi della chiamata. Controlla se data ha appointment_id o call_id e usa il campo id per evitare di elaborare due volte lo stesso recapito.

Verifica la firma

La firma è un HMAC-SHA256 del timestamp, un punto, e il corpo grezzo della richiesta, con chiave data dal segreto di firma del tuo endpoint. Viene inviata come v1= seguito dal digest esadecimale.

  1. Leggi il corpo grezzo esattamente come ricevuto, prima di qualsiasi analisi JSON.
  2. Costruisci la stringa {X-Ringhum-Timestamp}.{corpo grezzo}.
  3. Calcola l'HMAC-SHA256 con il tuo segreto e anteponi v1=.
  4. Confrontalo con X-Ringhum-Signature usando un confronto a tempo costante.
  5. Rifiuta la richiesta se il timestamp è più vecchio di cinque minuti, per bloccare le richieste ripetute.

Node.js:

const crypto = require('crypto');

function isValid(req, rawBody, secret) {
  const ts = req.header('X-Ringhum-Timestamp');
  const sig = req.header('X-Ringhum-Signature') || '';
  const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

PHP:

$ts = $_SERVER['HTTP_X_RINGHUM_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_RINGHUM_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(400);
    exit;
}

Risposte, timeout e nuovi tentativi

  • Rispondi con qualsiasi stato 2xx per confermare il recapito. Esegui il lavoro lento dopo aver risposto.
  • Ringhum attende fino a 10 secondi la tua risposta.
  • Se il tuo endpoint non risponde con un 2xx, il recapito viene tentato fino a 3 volte in totale: subito, di nuovo dopo circa 10 secondi, e un'ultima volta circa 60 secondi dopo. Dopodiché viene scartato.
  • I recapiti possono arrivare fuori ordine. Usa created_at e gli id in data per ordinarli.

La tabella Webhook mostra l'ultimo stato HTTP di ogni endpoint e quando è stato inviato. Un endpoint fallito resta attivo; Ringhum non lo disattiva per te.

Testare, mettere in pausa e rimuovere

  • Invia test invia subito un evento test.ping, e un messaggio mostra lo stato HTTP restituito dal tuo endpoint.
  • L'interruttore Attivo mette in pausa un endpoint. Gli eventi che avvengono mentre è disattivato non vengono inviati in seguito.
  • Rimuovi elimina l'endpoint e il suo segreto.

Domande frequenti

Qual è la differenza rispetto alle app Zapier, Make e n8n in Integrazioni? Quei collegamenti usano la pagina Integrazioni e i suoi sei tipi di evento. Il loro corpo è {"event", "workspace", "sent_at", "data"}, e quando imposti un segreto l'header della firma è X-Ringhum-Signature: sha256=…, un HMAC-SHA256 del solo corpo. I webhook per sviluppatori, descritti qui, coprono più eventi e usano la firma v1= con un timestamp. Vedi Scegliere cosa viene inviato.

Il mio endpoint restituisce 2xx ma il mio codice non vede nulla. Controlla che l'evento sia selezionato per quell'endpoint, che l'endpoint sia attivo, e che il tuo firewall consenta richieste da internet.

Perché la verifica della firma fallisce? Più spesso perché il corpo è stato analizzato e ri-codificato prima dell'hashing. Calcola l'hash dei byte grezzi esattamente come ricevuti.

Hai ancora dubbi?

Scrivi a [email protected] o mandaci un messaggio. I piani Team e Scale hanno supporto prioritario.

Contatta il supporto