Webhooks na het gesprek
Abonneer je op call.completed-events — transcripties, opnames, uitkomsten.
Post-call Webhooks
Brand uw server elke keer als een Finn gesprek eindigt. Ontvang transcriptie, opname URL, gestructureerde uitkomst, sentiment, en kosten. De belangrijkste webhook voor het synchroniseren van call data in uw CRM, analytics, of ops pipeline.
Als het vuurt
- Event:
call.completed - Bestanden: binnen 5 seconden na het einde van de oproep (om het even welke reden gekozen, gemist, voicemail, bezet, mislukt)
-
- Order:** best-forfort. Gebruik
created_at+ idempotent handlers, vertrouw niet op strikte volgorde.
- Order:** best-forfort. Gebruik
- Retries: 5 pogingen over ~10 minuten op
5xx/ timeout. Laatste poging aangemeld in het dashboard webhook log.
Een abonnement registreren
Via dashboard
Instellingen → Integraties → Webhooks → Nieuwe webhook.
Kies call.completed uit de evenementenlijst. Plak je eindpunt URL. Opslaan Finn toont het ondertekening geheim eenmaal. Kopieer het nu (je kunt het niet meer zien).
Via API
curl https://api.hirefinn.ai/v1/webhooks \
-H "Authorization: Bearer $FINN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/finn/post-call",
"events": ["call.completed"],
"description": "CRM + analytics sync"
}'
De respons omvat secret .
Betaling
{
"id": "evt_2H4abc",
"type": "call.completed",
"created_at": "2026-05-22T14:32:14.892Z",
"org_id": "org_8fac17c5",
"data": {
"call_id": "cal_xyz789",
"deployment_id": "dep_abc123",
"finn_id": "fn_def456",
"phone_number_id": "ph_1234",
"from": "+919876543210",
"to": "+918765432100",
"call_type": "outbound",
"channel": "pstn",
"started_at": "2026-05-22T14:30:01.245Z",
"answered_at": "2026-05-22T14:30:04.812Z",
"ended_at": "2026-05-22T14:32:14.123Z",
"duration_seconds": 130,
"ring_seconds": 4,
"outcome": {
"label": "qualified",
"confidence": 0.87,
"extracted_fields": {
"preferred_slot": "2026-05-24T15:00:00+05:30",
"budget": "25000",
"is_decision_maker": true
}
},
"sentiment": "positive",
"csat_score": null,
"call_status": "completed",
"hangup_party": "agent",
"recording_url": "https://recordings.hirefinn.ai/.../cal_xyz789.mp3",
"recording_duration_seconds": 130,
"transcript_url": "https://transcripts.hirefinn.ai/.../cal_xyz789.json",
"credits_charged": 3,
"currency": "INR",
"monetary_value": 10.05,
"audience_id": "aud_xyz789",
"audience_row": {
"name": "Priya M",
"phone": "+919876543210",
"loan_amount": "500000"
},
"metadata": {
"campaign_tag": "may-cohort-3"
}
}
}
Veldreferentie
Veld Type Notities
De string is wereldwijd uniek. Gebruik als uw dedupe sleutel
Bron campagne. Null voor eenmalige testoproepen
Voorvertaling. WhatsApp calls gebruiken wa_id hier
#channel
ISO-8601 Toen Finn gestart met het bellen / ontvangen van de oproep
| answered_at | ISO-8601 / null | Null if the call never picked up |
| duration_seconds | int | Billable duration, from answered_at to ended_at |
Uw aangepaste uitkomst taxonomie van de prompt
| outcome.confidence | float 0–1 | Model confidence in the label |
| outcome.extracted_fields | object | Per-call structured data (free-form by prompt design) |
#sentiment
| call_status | enum | completed | no_answer | busy | failed | voicemail |
#hangup_party
Float Wallet debit voor deze oproep
De volledige CSV-rij (voor uitgaande). Null voor inkomend
Controle van de handtekening
Finn tekent elke webhaak met HMAC-SHA256. Controleer voordat je de lading vertrouwt.
Kop: X-Finn-Signature: t=1716391823,v1=abc123...
De t= is het tijdstempel. De v1= is HMAC-SHA256(secret, t + "." + raw_body).
Knooppunt
import crypto from "crypto";
function verifyFinnSignature(
rawBody: string,
header: string,
secret: string,
toleranceSeconds = 300,
): boolean {
const parts = Object.fromEntries(
header.split(",").map((p) => p.split("=") as [string, string]),
);
const ts = parseInt(parts.t, 10);
const sig = parts.v1;
if (!ts || !sig) return false;
if (Math.abs(Date.now() / 1000 - ts) > toleranceSeconds) return false; // replay guard
const expected = crypto
.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
Python
import hmac, hashlib, time
def verify_finn_signature(raw_body: bytes, header: str, secret: str, tolerance=300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
ts = int(parts.get("t", 0))
sig = parts.get("v1", "")
if not ts or not sig: return False
if abs(time.time() - ts) > tolerance: return False
expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
** Controleer altijd op de ruwe aanvraag-lichaam**, niet de ontleed JSON re-serialization verandert witruimte en breekt de HMAC.
Omgaan met de lading (Node voorbeeld)
import express from "express";
const app = express();
// raw body required for signature verification
app.post("/finn/post-call",
express.raw({ type: "application/json" }),
async (req, res) => {
const sig = req.headers["x-finn-signature"] as string;
const ok = verifyFinnSignature(req.body.toString(), sig, process.env.FINN_WEBHOOK_SECRET!);
if (!ok) return res.status(401).send("bad signature");
const event = JSON.parse(req.body.toString());
// Dedupe — idempotent processing
if (await db.eventExists(event.id)) {
return res.status(200).send("dup");
}
await db.markEventSeen(event.id);
// Route by event type
if (event.type === "call.completed") {
await handleCallCompleted(event.data);
}
res.status(200).send("ok");
},
);
async function handleCallCompleted(call: any) {
// 1. Update CRM record
await crm.updateLead(call.audience_row?.phone, {
last_call_outcome: call.outcome.label,
last_call_sentiment: call.sentiment,
last_call_recording: call.recording_url,
});
// 2. If qualified, fire a Slack alert
if (call.outcome.label === "qualified") {
await slack.notify("#sales-hot-leads", `Hot lead: ${call.audience_row.name}`);
}
// 3. Push to data warehouse
await warehouse.insert("finn_calls", call);
}
Betrouwbaarheid + geschiktheid
- Dedupe door
event.id - Terugkeer 2xx binnen 5 seconden
- Doe het zware werk async
- Replay vanaf dashboard Faalde leveringen verschijnen in Settings → Integraties → Webhooks → Logs met een "Replay" knop
Gemeenschappelijke gotcha's
Symptoom Fix
|---|---|
Je ontleedt JSON voordat je het controleert. Controleer eerst het ruwe lichaam
Voeg een unieke beperking of seen-set toe
Je eindpunt nam > 5s. Verplaats verwerking naar een wachtrij
De oproep was inkomende (geen publiek). Controleer call_type eerst
Opname van URL-URL-NL-adressen verlopen standaard na 30 dagen. Spiegel naar uw eigen opslag voor lange termijn archief
Gerelateerde gebeurtenissen
De post-call webhook is een van de vele. Zie de volledige catalogus:
Gebeurtenis Wanneer |---|---| Draagtuig opgepikt Deze pagina Warm overbrengen naar de mens De campagne is uitgeput Onder geconfigureerde drempel
Gerelateerd
Was this page helpful?
Still stuck or have feedback?
Email [email protected] or use the chat bubble in the bottom-right corner — it's a Finn that knows the Academy cold.