Webhook Integration Guide
Receive real-time updates about candidate interactions via HTTP POST callbacks.
Overview
TalentPrism webhooks allow you to receive real-time updates about candidate interactions and interview progress. Events are delivered as HTTP POST requests to your specified endpoint with a JSON payload.
For interview events, metadata.client_metadata.client_job_id
is resolved from the specific interview when possible. This matters for generic sequences where one public sequence can serve many client jobs.
Setting Up Webhooks
- Configure your endpoint URL in the sequence settings
- Save the webhook secret that is generated
- Use the test endpoint to verify your setup
Security
All webhook requests include an X-Talentprism-Signature header containing your webhook secret.
You should verify this signature to ensure the request came from TalentPrism.
Event Types
Touchpoint Events
| Event | Description |
|---|---|
| touchpoint.sent | Message has been sent |
| touchpoint.delivered | Message was delivered |
| touchpoint.responded | Candidate replied to message |
| touchpoint.failed | Message delivery failed |
| touchpoint.undelivered | Message could not be delivered |
| touchpoint.unsubscribed | Candidate opted out |
| touchpoint.rejected | Message rejected by provider |
Interview Events
| Event | Description |
|---|---|
| interview.interview_completed | Interview submitted by candidate |
| interview.interview_opened | Interview opened by candidate |
| interview.resume_uploaded | Resume uploaded |
| interview.interview_consent_selection | AI interview consent selection |
How client_metadata Is Resolved
Webhook payloads start from sequence-level metadata and may be enriched with candidate-level metadata. Interview events add one extra rule so the job id stays tied to the correct application.
- Base payload uses
sequence.client_metadata. - Candidate metadata may add extra keys for the same candidate.
- For interview events,
client_job_idis resolved from the current interview context before any legacy candidate-level fallback is used. - Internal application history stored under
candidate.client_metadata.applicationsis not emitted in the webhook payload.
Testing
To test your webhook integration, send a POST request to:
POST /sequence/sequences/{sequence_id}/test-webhook/
Example Payload
{
"event_id": "evt_12345678",
"event_type": "touchpoint.responded",
"created_at": "2025-04-22T15:30:45Z",
"data": {
"channel": "email",
"candidate": {
"id": "cand_12345",
"screenname": "John Doe",
"email": "[email protected]"
},
"touchpoint": {
"id": "tp_87654321",
"status": "responded"
},
"response": {
"responded_at": "2025-04-22T15:30:40Z",
"content": "Yes, I'm interested"
}
},
"metadata": {
"account_id": "acct_12345",
"version": "1.0"
}
}
Interview Payload Example
All people, companies, identifiers, URLs, and timestamps in this example are synthetic.
{
"event_id": "evt_12345678",
"event_type": "interview.interview_completed",
"created_at": "2026-03-14T20:31:03Z",
"data": {
"channel": "webCall",
"candidate": {
"candidate_id": 12345,
"screenname": "John Smith",
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone": null
},
"interview": {
"interview_id": "00000000-0000-4000-8000-000000000001",
"candidate_id": 12345,
"status": "completed",
"public_url": "https://talentprism.ai/candidate/interview/example-token/"
},
"response": {
"interview_opened_at": "2026-03-14T20:30:00Z",
"interview_exited_at": "2026-03-14T20:31:00Z"
}
},
"metadata": {
"account": "Example Staffing Co",
"job_title": "Welder Application Intake",
"client_metadata": {
"company_name": "Example Staffing Co",
"client_job_id": "JOB-12345",
"jobs_list_url": "https://example.com/jobs.json",
"jobs_page_url": "https://example.com/jobs",
"job_page_url_format": "https://example.com/jobs/{job_id}",
"referral_fee": "$200",
"referral_hours_requirement": "160 hours"
},
"version": "1.0"
}
}
Payload Data Fields
The data object contains event-specific information. A top-level channel field is always included:
| Value | Description |
|---|---|
| "email" | Email-based touchpoints (from Outreach Message) |
| "sms" | SMS-based touchpoints (from Outreach Message) |
| "inboundPhoneCall" | Interview events conducted via phone |
| "webCall" | Interview events conducted via web interface |
| "unknown" | Channel cannot be determined |
Webhook Payload Schema Tree
Webhook Payload
├── event_id (string)
├── event_type (string)
├── created_at (string - ISO 8601 datetime)
├── data
│ ├── channel (string: "email" | "sms" | "phone" | "web" | "unknown")
│ ├── candidate
│ │ ├── id (string)
│ │ ├── screenname (string)
│ │ ├── first_name (string)
│ │ ├── last_name (string)
│ │ ├── email (string)
│ │ └── phone (string)
│ │
│ ├── touchpoint (object - present for touchpoint.* events)
│ │ ├── id (string)
│ │ ├── candidate_id (string)
│ │ ├── outreach_message_id (string)
│ │ ├── channel (string: "email" | "sms")
│ │ └── status (string)
│ │
│ ├── interview (object - present for interview.* events)
│ │ ├── id (string)
│ │ ├── candidate_id (string)
│ │ └── status (string)
│ │
│ └── response (object - structure varies by event_type)
│ │
│ ├── IF touchpoint.responded:
│ │ ├── responded_at (ISO 8601 datetime)
│ │ ├── content (string)
│ │ └── ai_analysis (object | null)
│ │
│ ├── IF touchpoint.failed:
│ │ ├── failed_at (ISO 8601 datetime)
│ │ ├── reason (string)
│ │ └── recipient_status (string | null)
│ │
│ └── IF interview.interview_completed:
│ ├── interview_opened_at (ISO 8601 datetime | null)
│ ├── interview_exited_at (ISO 8601 datetime | null)
│ ├── language_selected (string | null)
│ ├── content (string - transcript)
│ └── ai_analysis (object)
│ ├── total_questions (integer)
│ ├── total_duration_minutes (integer | null)
│ ├── overall_score (number | null)
│ └── recommendation (string | null)
│
└── metadata
├── account (string)
├── job_title (string)
├── client_metadata (object)
│ ├── sequence-level metadata keys
│ ├── candidate-level enrichment keys
│ └── client_job_id resolved from the current interview for interview events
└── version (string)
Can't find what you're looking for?
Contact Us