Webhook payload- en handtekeningreferentie
Elke FluoTest-webhookintegratie stuurt bij het insturen van een quiz een HTTP POST met een JSON-body. Deze pagina documenteert het requestformaat, de standaard payloadvelden, de alternatieve payloadvorm bij veldkoppeling, en het handtekeningsysteem.
Laatst bijgewerkt
Hoe ziet een FluoTest-webhookpayload eruit?
Standaard is het een plat JSON-object met de identifiers van de inzending, contactvelden, score, niveau of uitkomst, het volledige antwoordenobject en een tijdstempel. Als er een ondertekeningssleutel is ingesteld, bevatten requests een X-FluoTest-Signature header (HMAC-SHA256 van de ruwe body).
Configuratie
Een webhookintegratie wordt geconfigureerd met een bestemmings-URL en een optionele ondertekeningssleutel. Er is geen OAuth of koppeling met een account van derden nodig.
Requestformaat
Elk webhookrequest wordt verstuurd met de volgende methode en headers:
| Header | Waarde | Opmerkingen |
|---|---|---|
| Method | POST | Altijd een POST-request. |
| Content-Type | application/json | De body is JSON-gecodeerd. |
| User-Agent | FluoTest-Webhook/1.0 | Identificeert het request als afkomstig van FluoTest. |
| X-FluoTest-Event | submission.created | Het enige eventtype dat momenteel wordt verstuurd. |
| X-FluoTest-Signature | sha256=<hex> | Alleen aanwezig als er een ondertekeningssleutel is geconfigureerd voor de webhook. |
Standaard payloadvelden
Zonder geconfigureerde veldkoppeling is de request-body een plat JSON-object:
{
"submission_id": "8f2b1c3a-...",
"test_id": "3a9d7e10-...",
"test_name": "Lead Fit Quiz",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Doe",
"company": "Acme Inc",
"contact_type": "email",
"respondent_name": "Jane Doe",
"total_score": 82,
"max_score": 100,
"score_percent": 82,
"tier": "High fit",
"scores": null,
"outcome": null,
"outcomes": null,
"disqualified": false,
"answers": {
"sections": [
{
"section_title": "Section 1",
"questions": [
{
"question_id": "q1",
"question_text": "What's your role?",
"question_type": "multiple_choice",
"answer": "Founder"
}
]
}
]
},
"submitted_at": "2026-07-10T14:32:00.000Z"
}| Veld | Type | Beschrijving |
|---|---|---|
| submission_id | string | Uniek ID van de inzending. |
| test_id | string | ID van de quiz. |
| test_name | string | Naam van de quiz. |
| string | null | E-mailadres van de respondent, indien verzameld. | |
| first_name | string | null | Voornaam van de respondent, indien verzameld. |
| last_name | string | null | Achternaam van de respondent, indien verzameld. |
| company | string | null | Bedrijfsnaam, indien verzameld. |
| contact_type | string | null | Welke contactmethode is verzameld: "email", "phone", of null. |
| respondent_name | string | null | Volledige naam, als een naamvraag is beantwoord. |
| total_score | number | De totaalscore van de respondent. |
| max_score | number | De maximaal mogelijke score. |
| score_percent | number | Score uitgedrukt als percentage. |
| tier | string | null | Label van het gematchte scoreniveau (quizzen met één score). |
| scores | object | null | Scores per categorie bij quizzen met meerdere scores; anders null. |
| outcome | string | null | Sleutel van de gematchte primaire uitkomst (alleen Pro-uitkomstsysteem). |
| outcomes | string[] | null | Sleutels van alle gematchte uitkomsten. |
| disqualified | boolean | Of de respondent is gediskwalificeerd. |
| answers | object | Geneste secties/vragen/antwoorden — zie hieronder. |
| submitted_at | string | ISO 8601-tijdstempel van de inzending. |
Een subset van velden versturen
Een webhook kan worden geconfigureerd om alleen een gekozen subset van bovenstaande velden te versturen. submission_id en test_id worden altijd meegestuurd ongeacht die keuze, zodat elke payload naar de bron te herleiden is.
Gekoppelde payloadmodus
Als er veldkoppeling is geconfigureerd voor een webhook (zie Veldkoppeling & sync-herhalingen), verandert de payloadvorm: de gekoppelde velden uit de koppelingsregels vervangen de platte structuur, samen met eventuele tags, en de volledige standaardpayload wordt ongewijzigd meegestuurd onder raw.
{
"mapped": { "email": "[email protected]", "score": 82 },
"tags": ["High fit"],
"raw": { "submission_id": "8f2b1c3a-...", "...": "..." }
}De handtekening verifiëren
Als er een ondertekeningssleutel is ingesteld, bevat elk request een X-FluoTest-Signature header: de HMAC-SHA256 hex-digest van de exacte request-body, berekend met de gedeelde sleutel en voorafgegaan door sha256=. Bereken dezelfde digest opnieuw over de ruwe request-body aan ontvangende zijde en vergelijk deze met de header om te bevestigen dat het request van FluoTest komt en onderweg niet is gewijzigd.
const crypto = require("crypto");
function isValidSignature(rawBody, header, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return header === expected;
}Aflevering, herhalingen en mislukkingen
Een webhookrequest heeft een time-out van 10 seconden. Een niet-2xx statuscode wordt beschouwd als een mislukte aflevering. Mislukte afleveringen worden automatisch opnieuw geprobeerd — zie Veldkoppeling & sync-herhalingen voor het herhalingsschema en hoe mislukkingen worden gelogd.
Veelgestelde vragen
Wat activeert een FluoTest-webhook?
Een webhook wordt eenmaal per quizinzending geactiveerd, met het eventtype submission.created. Er is momenteel geen ander eventtype.
Hoe verifieer ik de X-FluoTest-Signature header?
Bereken een HMAC-SHA256-digest van de ruwe request-body met de ondertekeningssleutel die voor de webhook is geconfigureerd, codeer deze hexadecimaal, voeg het voorvoegsel sha256= toe, en vergelijk dit met de headerwaarde via een vergelijking in constante tijd.
Wat gebeurt er als mijn endpoint onbereikbaar is of een foutmelding geeft?
De aflevering wordt als mislukt gemarkeerd en automatisch opnieuw geprobeerd met oplopende vertraging, tot 3 extra pogingen, tenzij de mislukking als permanent wordt beschouwd.
Kan ik kiezen welke velden in de payload worden verstuurd?
Ja. Een webhook kan worden geconfigureerd met een specifieke lijst velden; alleen die velden, plus submission_id en test_id, worden in elk request meegestuurd.