Webhook in uscita
Mentre il canale webhook in entrata riceve eventi esterni da elaborare, i webhook in uscita fanno l'inverso: notificano i tuoi sistemi quando si verifica un evento rilevante in betool.
Perché
Probabilmente disponi già di:
- Un sistema di allerta (PagerDuty, Opsgenie, Slack).
- Uno strumento ITSM (Jira, ServiceNow) per gestire i ticket.
- Una dashboard personalizzata che aggrega il tuo stato operativo.
Anziché chiedere a questi sistemi di interrogare l'API di betool tramite polling, iscrivili ai webhook in uscita: vengono notificati istantaneamente quando accade qualcosa.
Configurazione
- Amministrazione → Webhook in uscita → Nuova sottoscrizione.
- Scegli:
- URL di destinazione — l'endpoint che riceverà le POST.
- Eventi da monitorare — vedi l'elenco qui sotto.
- Segreto HMAC — generato automaticamente; usalo lato ricevente per verificare le firme.
- (Facoltativo) Filtri — limita alle esecuzioni di una pipeline specifica, a un livello di gravità, ecc.
Eventi disponibili
| Evento | Quando si attiva |
|---|---|
execution.failed | Un'esecuzione di pipeline è fallita |
execution.requires_human | Un nodo confirmation è in attesa di convalida |
execution.cost_threshold | Un'esecuzione ha superato una soglia di costo |
billing.low_balance | Il saldo dei crediti è sceso sotto la soglia configurata |
billing.out_of_credits | Il saldo è pari a zero (i rifiuti pre-chiamata sono attivi) |
audit.cross_tenant_read | Un agent esterno ha letto contenuti di questa organizzazione |
webhook.delivery_failed | Un precedente webhook in uscita è fallito 3 volte |
Formato della POST
POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-Betool-Event: execution.failed
X-Betool-Signature: sha256=...
X-Betool-Delivery: dlv_01HXYZ...
{
"event": "execution.failed",
"delivered_at": "2026-05-24T10:42:13Z",
"org_id": "org_...",
"data": {
"execution_id": "exec_...",
"pipeline_id": "pip_...",
"pipeline_name": "support email triage",
"failed_node": "agent: classifier",
"error_kind": "llm_timeout",
"error_message": "Provider responded after 30s timeout"
}
}
Firma HMAC
L'header X-Betool-Signature contiene sha256=<hmac> dove hmac = HMAC-SHA256(secret, body). Verificalo alla ricezione per assicurarti che la richiesta provenga effettivamente da betool:
import hmac, hashlib
def verify(body: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(),
body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
Retry e idempotenza
- Se il tuo endpoint risponde 2xx, l'evento viene contrassegnato come consegnato.
- Se la risposta non è 2xx oppure scade il timeout, betool riprova con backoff esponenziale (1 min, 5 min, 30 min, 2 h, 12 h, 24 h — massimo 6 tentativi).
- Dopo 6 fallimenti, l'evento viene contrassegnato come dead-letter e viene emesso un
webhook.delivery_failed(verso le tue altre sottoscrizioni attive).
Ogni POST trasporta un identificatore univoco X-Betool-Delivery. Se il tuo endpoint riceve la stessa consegna due volte (caso limite di rete), trattala come idempotente.
Sicurezza
- HTTPS obbligatorio — le sottoscrizioni in HTTP semplice vengono rifiutate.
- Segreto rigenerabile — puoi rigenerare il segreto in qualsiasi momento; le POST in corso che usano il vecchio segreto continueranno a essere accettate fino alla scadenza (5 min).
- IP di origine — betool pubblica i propri IP in uscita su status.betool.fr affinché tu possa inserirli nella allow-list del tuo firewall.