Webhook
Un webhook avvisa il tuo server quando succede qualcosa, come la fine di un video. Ti evita di dover interrogare GET /v1/job/{id}. I webhook sono gestiti con la stessa chiave API del resto del API, sotto https://reigniter.ai/api/webhooks.
| Evento | Inviato quando |
|---|---|
video.completed |
Un render completato. Il payload ha download_url, un collegamento che funziona per 7 giorni. |
video.failed |
Un rendering fallito. Un render che annulli non invia questo. |
training.invited |
A uno studente veniva assegnato un modulo e inviava la propria pagina di formazione. |
training.completed |
Un apprendente con nome ha completato un modulo. Il payload contiene il punteggio (segnato dal server), passed, e la loro pagina dei risultati. |
training.passed / training.failed |
Inviato con training.completed, contro il voto di superamento del modulo. Rimanere senza tempo è un fallimento. |
training.overdue |
Uno studente non ha finito entro la scadenza. Una volta per invito. |
training.certificate_expiring |
Un certificato scade entro 30 giorni. Una volta per certificato. |
post.published |
Un post è stato pubblicato su YouTube, TikTok, LinkedIn, Facebook o Instagram. Il payload contiene la piattaforma, l’account e url, il link al post quando la piattaforma lo fornisce. |
post.failed |
Un post non poteva essere pubblicato. reason è la risposta della piattaforma in parole semplici. |
credits.low |
Il saldo scese a 10 crediti o meno. Una volta per ogni consegna. |
credits.purchased |
Sono stati aggiunti crediti al conto. |
subscription.created |
È stato avviato un abbonamento al piano. |
subscription.canceled |
Un abbonamento al piano è stato cancellato. |
user.signup |
L’account è stato creato. |
user.onboarded |
L’account ha terminato l’onboarding. |
GET /api/webhooks/events restituisce questa lista.
Crea un webhook
Sezione intitolata “Crea un webhook”-
Crea un endpoint sul tuo server che accetti le richieste
POSTcon un JSON e risponda2xxrapidamente. Deve essere raggiungibile tramite internet pubblico. Gli indirizzi di rete privati e locali vengono rifiutati. -
Iscriviti a un evento. Un webhook ascolta un evento; creane uno per ogni evento di cui hai bisogno.
Finestra del terminale curl https://reigniter.ai/api/webhooks/hooks \-H "Authorization: Bearer $REIGNITER_API_KEY" \-H "Content-Type: application/json" \-d '{"event": "video.completed","webhook_url": "https://hooks.example.com/reignitor","description": "Post finished videos to our CMS"}'const res = await fetch('https://reigniter.ai/api/webhooks/hooks', {method: 'POST',headers: {Authorization: `Bearer ${process.env.REIGNITER_API_KEY}`,'Content-Type': 'application/json',},body: JSON.stringify({event: 'video.completed',webhook_url: 'https://hooks.example.com/reignitor',description: 'Post finished videos to our CMS',}),});const { hook, secret } = await res.json();res = requests.post("https://reigniter.ai/api/webhooks/hooks",headers={"Authorization": f"Bearer {os.environ['REIGNITER_API_KEY']}"},json={"event": "video.completed","webhook_url": "https://hooks.example.com/reignitor","description": "Post finished videos to our CMS",},)data = res.json()hook, secret = data["hook"], data["secret"] -
Conserva il
secretdella risposta201. Ti serve per controllare le firme. -
Invia un test.
POST /api/webhooks/hooks/{id}/testinvia un eventopingfirmato al tuo URL e ti dice cosa ha risposto il tuo endpoint:{ "delivered": true, "status": 200 }
Sottoscrivere di nuovo lo stesso evento e URL non crea un duplicato. Restituisce il webhook esistente con reused: true e lo riattiva.
Com’è una consegna
Sezione intitolata “Com’è una consegna”Ogni consegna è una POST con un corpo JSON:
{ "event": "video.completed", "payload": { "job_id": "7d2e4b10-5c3a-4f8e-a1b2-9c0d8e7f6a54", "user_id": "3f1c2a9e-8b7d-4c1e-9f0a-2d6b5e4c3a21", "output_url": "https://cdn.example.com/exports/7d2e4b10.mp4", "canvas_id": null, "scene_count": 4, "scenes_failed": 0, "credits_charged": 12 }, "emitted_at": "2026-09-25T10:15:00.000Z", "delivery_id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"}video.failed trasporta job_id, user_id, canvas_id e un reason.
Abbina payload.job_id al job_id che hai ottenuto da POST /v1/render.
E queste intestazioni:
| Intestazione | Valore |
|---|---|
X-Reigniter-Event |
Il nome dell’evento. |
X-Reigniter-Delivery |
Un ID unico per questa consegna. Rimane invariata quando una consegna viene riprovata. |
X-Reigniter-Timestamp |
Unix, in pochi secondi, quando la consegna fu firmata. |
X-Reigniter-Signature |
sha256= e l’esagono HMAC-SHA256 di {timestamp}.{raw body}, collegati al tuo segreto. |
Verifica la firma
Sezione intitolata “Verifica la firma”Controlla ogni consegna prima di fidarti:
- Leggi il corpo grezzo della richiesta, prima di JSON parsing.
- Costruisci la corda
{X-Reigniter-Timestamp}.{raw body}. - Calcola HMAC-SHA256 con il tuo segreto, come esadecimale, e aggiungi
sha256=davanti. - Confrontalo con
X-Reigniter-Signatureusando un confronto a tempo costante. - Rifiuta la consegna se il timestamp ha più di 5 minuti.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyReigniterWebhook(rawBody, headers, secret) { const timestamp = headers['x-banshea-timestamp']; const received = headers['x-banshea-signature'] ?? ''; if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = 'sha256=' + createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`) .digest('hex');
const a = Buffer.from(expected); const b = Buffer.from(received); return a.length === b.length && timingSafeEqual(a, b);}import hashlib, hmac, time
def verify_reignitor_webhook(raw_body: bytes, headers, secret: str) -> bool: timestamp = headers.get("X-Reigniter-Timestamp") received = headers.get("X-Reigniter-Signature", "") if not timestamp or abs(time.time() - int(timestamp)) > 300: return False
signed = f"{timestamp}.".encode() + raw_body expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, received)Consegna e tentativi
Sezione intitolata “Consegna e tentativi”- Ogni consegna aspetta fino a 10 secondi prima che il tuo endpoint risponda.
- Un
5xx, un429, un timeout o un errore di rete viene riprovato, fino a 3 tentativi in totale, a circa un secondo di distanza. - Qualsiasi altro
4xxnon viene riprovato. - I retenti mantengono lo stesso
X-Reigniter-Delivery. Usalo per ignorare una consegna che hai già fatto. - Dopo 20 consegne fallite di fila, il webhook viene spento.
GET /api/webhooks/hooksmostraactive: falsee l’ultimo errore inlast_status. Ripara il tuo endpoint, poi riaccendilo conPATCH /api/webhooks/hooks/{id}e{ "active": true }.
Rispondi 2xx appena hai memorizzato la consegna e lavora lentamente dopo.
Gestire i webhook
Sezione intitolata “Gestire i webhook”| Metodo | Percorso | Cosa fa |
|---|---|---|
GET |
/api/webhooks/events |
Elenca i nomi degli eventi e lo schema delle firme |
GET |
/api/webhooks/hooks |
Elenca i tuoi webhook |
POST |
/api/webhooks/hooks |
Crea un webhook |
PATCH |
/api/webhooks/hooks/{id} |
Pausa, riprendi o cambia URL o descrizione |
DELETE |
/api/webhooks/hooks/{id} |
Elimina un webhook |
POST |
/api/webhooks/hooks/{id}/test |
Invia un ping firmato |
Un account può avere fino a 25 webhook. Le forme complete di richiesta e risposta sono nel riferimento all’endpoint.