Webhook Payload Structure & Event Types
Learn how webhook data is structured, including identifiers, event types and detailed outputs.
Overview
All Begini webhooks use the same top-level envelope. The contents of event.details vary by event type.
Request format
| Property | Value |
|---|---|
| Method | POST |
| Content-Type | application/json |
X-Signature header |
HMAC SHA-512 signature of the raw payload |
Common envelope
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "event_name",
"details": {}
}
}
| Field | Description |
|---|---|
uid |
Your unique identifier for this user, as passed when creating the session. Use this to match the webhook back to your internal record. |
integration_id |
Identifies which deployment generated the event. Useful when running multiple deployments or environments. |
event.type |
The event type string — determines how to process the payload. |
event.details |
Event-specific data. Structure varies by event type — see below. |
event.reasons |
Optional array. Present on application.incomplete and application.cancelled events only. |
Data formats
-
Timestamps — all time fields are in epoch (Unix) format, e.g.
1644397242 - Scores — integer format
-
Percentages — decimal string format, e.g.
"0.333333333333333"
Event types
psychometric_score.complete
Generated when a psychometric score result is available. This is the primary event for decisioning.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event" : {
"type": "psychometric_score.complete",
"details" : {
"application_started_at" : 1644397242,
"application_completed_at" : 1644397300,
"scored_at" : 1644397637,
"platform": "WEB",
"calculated" : {
"score" : ##,
"risk_band" : "RISK_RATING",
"score_confidence" : "CONFIDENCE_RATING",
"traits": [
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
},
{
"key": "trait_type",
"value": #,
"risk_band": "RISK_RATING"
}
]
},
"flags" : [ ]
}
}
}
application.complete
Generated when the user finishes the application journey. Precedes the score event.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "application.complete",
"details": {
"application_started_at": 1644397242,
"application_completed_at": 1644397300
}
}
}
android_score.complete
Generated when a score is available from an Android device data integration.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "android_score.complete",
"details": {
"application_started_at": 1644397242,
"application_completed_at": 1644397300,
"scored_at": 1644397637,
"platform": "ANDROID",
"calculated": {
"score": 68,
"risk_band": "MEDIUM"
},
"permissions_granted": [],
"permissions_denied": []
}
}
}
ios_score.complete
Generated when a score is available from an iOS device data integration.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "ios_score.complete",
"details": {
"application_started_at": 1644397242,
"application_completed_at": 1644397300,
"scored_at": 1644397637,
"platform": "IOS",
"calculated": {
"score": 65,
"risk_band": "MEDIUM"
},
"permissions_granted": [],
"permissions_denied": []
}
}
}
application.expired
Generated when the session time limit is reached before the user completes the assessment.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "application.expired",
"details": {
"application_started_at": 1652882892,
"application_expired_at": 1652883492,
"percentage_completed": "0.333333333333333"
}
}
}
application.incomplete
Generated when the user submits the journey but required sections were not completed (e.g. missing permissions, unanswered sections).
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "application.incomplete",
"details": {
"application_started_at": 1652882892,
"last_response_submitted_at": 1652883492,
"percentage_completed": "0.333333333333333"
},
"reasons": ["Missing data"]
}
}
application.cancelled
Generated when the user exits or rejects the privacy policy before completing.
{
"uid": "1234QWER-TYUI4567-ASDFD890",
"integration_id": "12345678901234567890",
"event": {
"type": "application.cancelled",
"details": {
"application_started_at": 1652882892,
"application_cancelled_at": 1652883492
},
"reasons": ["Denied the terms and conditions"]
}
}
Response handling
Your endpoint must return HTTP 200 for Begini to consider delivery successful. Return 200 only when processing is complete. Any non-200 response will trigger a retry.
| Status | Meaning |
|---|---|
200 |
Webhook received and processed successfully |
| Non-200 | Delivery failed — Begini will retry |
Handling duplicates
Events may be delivered more than once due to retries. Your system should be idempotent. At minimum log uid, integration_id, event.type and the relevant timestamp so you can detect and safely ignore duplicate deliveries.
Forward compatibility
New fields may be added to payloads over time. Your implementation should tolerate unknown fields without failing.
Next steps
- Securing Webhooks (HMAC) — verify every incoming webhook request
- Testing Webhooks — validate your endpoint using the test API
- Webhook Troubleshooting — diagnose delivery and processing issues
Was this article helpful?
Give feedback