Intake Events
Triple emits events during and at the end of an intake session, via two channels:
window.postMessagefrom the intake iframe to the parent page. Use these for in-app UX (progress indicators, success redirects).- Webhooks to your backend. Use these for durable business logic (creating the dispute record, triggering downstream workflows).
Both channels emit the same logical events, but you'll typically want webhooks for anything that must not be lost if the browser closes.
Event names and payload fields below are under active development and may change before general availability.
postMessage events
All messages from the intake iframe have this shape:
{
type: string, // e.g. "triple.intake.completed"
intake_session_id: string,
...payload
}
Always verify event.origin === 'https://intake.triple.app' before trusting a message.
triple.intake.opened
Fired once when the cardholder loads the flow.
{
"type": "triple.intake.opened",
"intake_session_id": "is_a1b2c3",
"mode": "form"
}
triple.intake.step_changed
Fired each time the cardholder moves to a new step (page in the form, message in the chatbot). Useful for analytics.
{
"type": "triple.intake.step_changed",
"intake_session_id": "is_a1b2c3",
"step_id": "cardholder_statement",
"step_index": 2,
"step_total": 5
}
triple.intake.completed
Fired when the cardholder finishes the flow and an evaluation has been created. This is the event most integrations care about.
{
"type": "triple.intake.completed",
"intake_session_id": "is_a1b2c3",
"evaluation_id": "eval_7d9e1f"
}
triple.intake.abandoned
Fired if the cardholder closes the iframe or stays idle past the session's inactivity threshold. You may offer to resume via a fresh session.
{
"type": "triple.intake.abandoned",
"intake_session_id": "is_a1b2c3",
"reason": "timeout"
}
triple.intake.error
Fired if something goes wrong inside the flow — an upload failure, an unrecoverable validation mismatch, etc.
{
"type": "triple.intake.error",
"intake_session_id": "is_a1b2c3",
"code": "evidence_upload_failed",
"message": "The cardholder's upload could not be stored."
}
Webhook events
The same events (minus the noisy UX ones) are delivered to your webhook endpoint. See Webhooks for configuration and signature verification.
| Event | When |
|---|---|
intake.session.completed | Cardholder finished; evaluation is queued/available |
intake.session.abandoned | Session timed out or was closed without completion |
Example payload for intake.session.completed:
{
"event": "intake.session.completed",
"data": {
"intake_session_id": "is_a1b2c3",
"evaluation_id": "eval_7d9e1f",
"cardholder": {
"external_id": "cust_9f3a2"
},
"occurred_at": "2026-04-23T16:24:11Z"
}
}
Deciding which channel to use
- Need to close a modal / redirect the cardholder? Use
postMessage. - Need to write to a database / notify an ops team? Use webhooks.
- Want both? Do both. They are independent — delivery of one doesn't affect the other.