Vai al contenuto
Sfoglia il riferimento
Torna al riferimento API
Guida

Ricevere i webhook

I webhook ti mandano gli eventi in tempo reale, senza doverli chiedere di continuo. Iscrivi un URL, scegli gli eventi che ti interessano e verifica ogni consegna con la sua firma HMAC.

Iscriversi

Crea una sottoscrizione tramite l'API Webhooks con l'URL del tuo endpoint e gli eventTypes che vuoi ricevere. In cambio ricevi un segreto di firma: conservalo, serve a verificare ogni consegna.

bash
curl -H "Authorization: Bearer vokse_sk_…" \     -H "Content-Type: application/json" \     -H "Idempotency-Key: $(uuidgen)" \     -X POST https://api.vokse.ai/households/current/webhooks/subscriptions \     -d '{"url":"https://example.com/hooks/vokse","eventTypes":["transaction.created","budget.overrun"]}'

Tipi di evento

L'elenco completo e sempre aggiornato dei tipi di evento lo trovi su /meta/webhook-events. Il catalogo di oggi:

  • transaction.created: è stato registrato un movimento.
  • recurrence.materialised: un movimento ricorrente è stato generato in automatico.
  • bank.sync.completed: un collegamento bancario ha finito di sincronizzare.
  • budget.overrun: una categoria ha sforato il budget del mese.
  • spending.anomaly: è stata rilevata una spesa fuori dal solito.
  • goal.reached: un obiettivo di risparmio è stato raggiunto.
  • insight.generated: è pronta una nuova analisi dell'IA.

Verificare la firma

Ogni consegna porta un header X-Vokse-Signature nella forma t=<timestamp>,v1=<signature>. La firma è un HMAC-SHA256 calcolato con il tuo segreto di firma sul timestamp, un punto e il corpo grezzo della richiesta. Ricostruisci quella stringa dai byte esatti che hai ricevuto, ricalcola l'HMAC, confrontalo con v1 a tempo costante e scarta i timestamp troppo vecchi.

js
import crypto from 'node:crypto';// X-Vokse-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>function verify(rawBody, signatureHeader, signingSecret) {  const parts = new Map(    signatureHeader.split(',').map((kv) => kv.split('=')),  );  const t = parts.get('t');  const v1 = parts.get('v1');  const expected = crypto    .createHmac('sha256', signingSecret)    .update(`${t}.${rawBody}`) // timestamp, a dot, the exact bytes received    .digest('hex');  if (!t || !v1 || v1.length !== expected.length) return false;  // freshness: reject stale timestamps to block replays  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));}

Nuovi tentativi e consegna

Rispondi 2xx entro pochi secondi per confermare. Le risposte 5xx e i timeout vengono ritentati con backoff esponenziale, fino a cinque tentativi; un 4xx è considerato definitivo e non viene mai ritentato. Dopo troppi fallimenti di fila la sottoscrizione va in pausa da sola e il proprietario della famiglia riceve una notifica.