Webhook Configuration
Overview
HeyMilo Webhooks allow you to receive real-time HTTP notifications when key events occur during the candidate interview lifecycle. Instead of polling the API for updates, webhooks push data to your specified endpoint as soon as an event happens — enabling seamless automation, ATS syncing, and custom workflow triggers.
With webhooks, you can:
Get notified instantly when a candidate starts or completes an interview
Receive full interview reports as soon as they are generated
Automate downstream actions like ATS updates, email notifications, or scoring pipelines
Build event-driven integrations without continuous API polling
How Webhooks Work
Register a webhook via the API, specifying a destination URL, the event type you want to subscribe to, and the posting (job) it applies to.
HeyMilo fires an HTTP request to your URL whenever the subscribed event occurs.
Your endpoint receives the payload containing all relevant event data (candidate info, interview details, scores, etc.).
┌──────────┐ Event occurs ┌────────────────┐
│ HeyMilo │ ──── HTTP POST/GET ────────► │ Your Endpoint │
└──────────┘ (JSON payload) └────────────────┘Authentication
Webhook API endpoints require authentication using the X-API-KEY header, the same key used for all Public API requests.
Webhook Event Types
HeyMilo supports the following webhook event types:
interview_started
Triggered when a candidate begins an interview session
interview_completed
Triggered when a candidate finishes all steps of an interview
report_available
Triggered when the AI-generated interview report is ready to view
Event Lifecycle
A typical candidate journey triggers events in this order:
Note: The
report_availableevent fires after AI analysis is complete, which may occur several seconds to minutes after the interview is marked as completed.
Webhook API Endpoints
All webhook endpoints use the base URL:
1. Create Webhook
POST /create
Register a new webhook to receive event notifications for a specific job posting.
Request Body
Request Schema
posting_id
string
Yes
ID of the job posting this webhook applies to
url
string (URL)
Yes
The destination URL that will receive the webhook payload
event_type
string
Yes
One of: interview_started, interview_completed, report_available
http_method
string
No
HTTP method used to deliver the webhook: get or post (default: post)
Example Request
Response
Response Schema
webhook_id
string
Unique identifier for the created webhook
posting_id
string
The job posting this webhook is associated with
url
string
Destination URL for webhook delivery
event_type
string
The subscribed event type
http_method
string
HTTP method used for delivery (get or post)
is_active
boolean
Whether the webhook is currently active
created_at
float
Unix timestamp when the webhook was created
updated_at
float
Unix timestamp when the webhook was last modified
2. Get Webhook
GET /fetch/{webhook_id}
Retrieve a specific webhook configuration by its ID.
Path Parameters
webhook_id
string
Yes
The unique ID of the webhook
Example Request
Response
3. Get All Webhooks
GET /all
Retrieve all webhooks for your workspace, with optional filters.
Query Parameters
posting_id
string
No
Filter webhooks by job posting ID
event_type
string
No
Filter by event type: interview_started, interview_completed, report_available
Example Request
Response
4. Deactivate Webhook
POST /deactivate/{webhook_id}
Deactivate an existing webhook. Deactivated webhooks will no longer receive event notifications.
Path Parameters
webhook_id
string
Yes
The unique ID of the webhook
Example Request
Webhook Payload Schemas
When an event fires, HeyMilo sends an HTTP request to your registered URL with a JSON payload. The payload structure varies by event type. Each event type has a distinct schema — see the full payloads and field-by-field breakdowns below.
Payload: interview_started
interview_startedSent when a candidate begins an interview session.
interview_started Payload Schema
interview_started Payload Schemainterview_id
string
Unique identifier for the interview
posting_id
string
The job posting ID
timestamp
float
Unix timestamp when the interview started
metadata
object
Candidate metadata object (see below)
Candidate Metadata Object:
candidate_name
string
Candidate's full name
candidate_email
string
Candidate's email address
candidate_id
string
Unique identifier for the candidate
metadata
object/null
Additional ingestion metadata (can be null). See inner metadata below.
Inner Metadata Object (nullable):
source
string
How the candidate was ingested (e.g., user_ingestion)
job_id
string
The job/posting ID associated with the ingestion
Note: The inner
metadataobject can benullif no additional ingestion context is available.
Payload: interview_completed
interview_completedSent when a candidate finishes all required steps of an interview.
interview_completed Payload Schema
interview_completed Payload Schemainterview_id
string
Unique identifier for the interview
agent_conversation_id
string
Conversation ID for the agent interaction (empty string if not applicable)
parent_conversation_id
string
Parent conversation ID linking related interview sessions
engagement_id
string
Engagement tracking ID (empty string if not applicable)
posting_id
string
The job posting ID
timestamp
float
Unix timestamp when the event was emitted
workflow_completed
boolean
Whether the full agentic workflow has been completed
completion_timestamp
float
Unix timestamp when the interview was actually completed
Payload: report_available
report_availableSent when the AI-generated interview report is ready. This is the most comprehensive payload, containing the full analysis data: scores, highlights, scorecard, communication evaluation, transcript, interview data model, company info, and posting info.
report_available Top-Level Schema
report_available Top-Level Schemainterview_id
string
Unique identifier for the interview
posting_id
string
The job posting ID
metadata
object
Candidate metadata (same structure as interview_started)
report_url
string
Direct URL to download the generated PDF report
timestamp
float
Unix timestamp when the report became available
interview_type
string
Type of interview (e.g., web_interview)
agentic_data
object
AI-generated analysis data (summary, scorecard, transcript, etc.)
interview_data_model
object
Full interview record with candidate details, company & posting info
agentic_data Object
agentic_data Objectweb_interview_info
object/null
AI analysis of web/voice interview (present if interview type is web)
agentic_data.web_interview_info Object
agentic_data.web_interview_info Objectsummary
object
High-level interview summary with highlights and match score
scorecard
object
Detailed question-by-question scoring
communication
object
Communication and speech quality evaluation
transcript
object
Full interview transcript
audio_recording_link
string
URL to the audio recording of the interview
video_recording_link
string
URL to the video recording (if video enabled)
summary Object
summary Objectinterview_id
string
Interview identifier
highlights
array
List of candidate strengths (strings)
lowlights
array
List of candidate weaknesses or gaps (strings)
match_score
integer
Overall match score (0-100)
scorecard Object
scorecard Objectinterview_id
string
Interview identifier
match_details
array
List of match assessment details (strings)
questions
array
List of scored question objects
tags
array
Skill tags identified during the interview
scorecard.questions[] Object
scorecard.questions[] Objectquestion_id
string
Unique identifier for the question
question
string
The interview question text
evaluation_summary
string
AI-generated summary of the candidate's answer
evaluation_criteria
string
The criteria used for evaluation
preview_timestamp
integer
Timestamp offset (seconds) for the answer preview
evaluation_score
integer
Score for this question (1-10)
rank
integer
Ranking position of this question
chat_transcript
array
Relevant transcript excerpts for this question
score_of_1
string
Description of what constitutes the lowest score
score_of_5
string
Description of what constitutes the highest score
score_weight
integer
Weight multiplier for this question's score
not_scored
boolean
Whether this question was excluded from scoring
chat_transcript[] Object
chat_transcript[] Objectspeaker
string
Who spoke (Candidate, bot, user)
text
string
The spoken text
timestamp
integer
Timestamp offset in seconds from interview start
timestamp_str
string
Human-readable timestamp (e.g., "04:34")
communication Object
communication Objectinterview_id
string
Interview identifier
speech_score
float
Overall speech/communication score (-1 if not scored)
evaluations
array
List of communication evaluation objects (can be empty)
template_id
string/null
Template ID used for evaluation (if applicable)
transcript Object
transcript Objectinterview_id
string
Interview identifier
transcript
array
List of transcript entry objects
interview_data_model Object
interview_data_model Objectinterview_id
string
Unique identifier for the interview
details
object
Core interview details (candidate info, workflow, metadata)
company_info
object
Full company/workspace configuration
posting_info
object
Full job posting configuration
web_interview_info
object/null
Web interview analysis (duplicated from agentic_data)
resume_interview_info
object/null
Resume screening analysis (null if no resume step)
sms_interview_info
object/null
SMS screening analysis (null if no SMS step)
form_interview_info
object/null
Form screening analysis (null if no form step)
interview_data_model.details Object
interview_data_model.details Objectinterview_id
string
Interview identifier
candidate_id
string
Unique identifier for the candidate
interviewed_on
float
Unix timestamp when the interview was conducted
score
float
Overall score
name
string
Candidate's full name
email
string
Candidate's email address
actions
object/null
Available actions for this interview
status
string/null
Interview status
workflow_status
object
Detailed workflow step statuses
metadata
object
Per-stage metadata (resume, web_interview, sms, form)
candidate_feedback
object/null
Candidate's feedback on the interview
candidate_next_steps
object/null
Next steps for the candidate
candidate_interview_url
string
The candidate-facing interview URL
workflow_status Object
workflow_status Objectinterview_id
string
Interview identifier
step_by_step
array
List of workflow step status objects
all_complete
boolean
Whether all required steps are complete
last_engagement
float
Unix timestamp of the last candidate interaction
metadata
object/null
Additional workflow metadata
workflow_status.step_by_step[] Object
workflow_status.step_by_step[] Objectcomplete
boolean
Whether this step is complete
required
boolean
Whether this step is required
order
integer
Position in the workflow sequence (1-based)
id
string
Step identifier (e.g., web_interview, resume_upload)
started
boolean
Whether the candidate has started this step
details
object/null
Human-readable status details (details, title, description)
raw_status
string
Internal status code (e.g., INTERVIEW_PROCESSED_RAW_FILES)
last_updated_timestamp
float
Unix timestamp of the last update to this step
knocked_out
boolean
Whether the candidate was disqualified at this step
completion_percentage
float
Step completion progress (0 to 1)
completion_metadata
object/null
Additional completion metadata
is_analyzing_call
boolean
Whether AI analysis is still in progress
total_duration
float/null
Total duration of the step in seconds
state_flags
object
Boolean state flags for the step
state_flags Object
state_flags Objectis_completed
boolean
Whether the step is fully completed
is_incomplete
boolean
Whether the step is incomplete
is_analyzing_call
boolean
Whether AI analysis is in progress
is_in_progress
boolean
Whether the step is currently in progress
details.metadata Object
details.metadata Objectresume
object/null
Resume metadata (null if no resume step)
web_interview
object/null
Web interview metadata (score, highlights, recording links)
sms
object/null
SMS screening metadata (null if no SMS step)
form
object/null
Form screening metadata (null if no form step)
details.metadata.web_interview Object
details.metadata.web_interview Objectfinal_score
float
Final interview score
skill_highlights
array
List of skill tags (strings)
audio_recording_link
string
URL to audio recording
video_recording_link
string
URL to video recording
company_info Object
company_info Objectcompany_id
string
Unique company identifier
workspace_id
string
Workspace identifier
created_at
float
Unix timestamp when the company was created
updated_at
float/null
Unix timestamp of last update
created_by
string
Creator identifier
name
string
Company name
image_url
string
Company logo URL
intro_message
string/null
Custom intro message
company_background
string/null
Company background info
voice_id
string/null
Default voice ID for interviews
knowledge_base
object/null
Company knowledge base configuration
interview_domain
string/null
Custom interview domain
interview_domain_id
string/null
Custom interview domain ID
sender_email_id
string/null
Sender email configuration ID
address
string/null
Company address
address_data
object/null
Structured address data
timezone
string/null
Company timezone
base_web_interview_config
object
Default web interview config (backdrop, avatar, branding)
message_settings
object/null
Messaging configuration
sms_agent_config
object/null
SMS agent configuration
pdf_generation_config
object/null
PDF report generation settings
cheat_detection
object/null
Cheat detection configuration
allow_white_labeling
boolean/null
Whether white labeling is enabled
disable_all_candidate_communications
boolean/null
Whether all candidate communications are disabled
interview_completion_confidence_threshold
float
Confidence threshold for interview completion (0-1)
retention_policy_days
integer/null
Data retention policy in days
video_cheat_detection_enabled
boolean/null
Whether video cheat detection is enabled
form_agent_enabled
boolean/null
Whether form agent is enabled
calendar_management_enabled
boolean/null
Whether calendar management is enabled
email_templates_enabled
boolean/null
Whether email templates are enabled
phone_calls_enabled
boolean/null
Whether phone calls are enabled
profile_picture_processing
boolean/null
Whether profile picture processing is enabled
chat_agent_enabled
boolean/null
Whether chat agent is enabled
copilot_enabled
boolean/null
Whether copilot is enabled
design_templates_enabled
boolean/null
Whether design templates are enabled
interview_templates_enabled
boolean/null
Whether interview templates are enabled
sourcing_configs_enabled
boolean/null
Whether sourcing configs are enabled
pbac_enabled
boolean/null
Whether permissions-based access control is enabled
email_report_to_candidate_enabled
boolean/null
Whether email reports to candidates are enabled
posting_info Object
posting_info Objectposting_id
string
Unique posting identifier
title
string
Job title
name
string
URL-friendly posting name
internal_name
string/null
Internal posting name
description
string
Job description (HTML)
root_level_configs
object
Top-level agent configuration
company_id
string
Company identifier
created_at
float
Unix timestamp when the posting was created
last_updated
float
Unix timestamp when the posting was last updated
archived
boolean
Whether the posting is archived
deadline
float
Posting deadline (Unix timestamp)
finalized
boolean
Whether the posting is finalized
test_posting
boolean
Whether this is a test posting
agentic_workflow
array
List of agent workflow steps with configurations
step_workflow
object
Workflow definition with steps and dependencies
phone_number_id
string/null
Associated phone number ID
sender_email_id
string
Sender email ID
email_template_group_id
string/null
Email template group ID
design_template_group_id
string/null
Design template group ID
sourcing_config_ids
array
List of sourcing config IDs
redirect_url
string/null
Post-interview redirect URL
scheduling_url
string/null
Scheduling page URL
event_slug
string/null
Calendar event slug
cal_team_id
string/null
Calendar team ID
team_slug
string/null
Team slug
mascot_url
string
Mascot image URL
mascot_id
string
Mascot identifier
days_to_complete
integer/null
Days allowed to complete the interview
ats_metadata
object/null
ATS integration metadata
allow_sms_comms
boolean
Whether SMS communications are enabled
max_retakes
integer/null
Maximum number of interview retakes
retake_cooldown_days
integer/null
Cooldown period between retakes
is_template
boolean
Whether this posting is a template
email_report_to_candidate
boolean
Whether to email reports to candidates
Setting Up Webhooks
Step 1: Prepare Your Endpoint
Your webhook endpoint must be a publicly accessible URL that can receive HTTP requests. The endpoint should:
Accept
POST(orGET) requestsReturn a
200status code to acknowledge receiptProcess the payload asynchronously if heavy processing is required
Example endpoint (Node.js / Express):
Example endpoint (Python / FastAPI):
Step 2: Register the Webhook
Use the Create Webhook API to register your endpoint for the desired event type and job posting.
Step 3: Verify Delivery
After registering, trigger a test event (e.g., start an interview for a test candidate) and confirm your endpoint receives the payload. Check the response status and payload structure to ensure your integration handles the data correctly.
Multiple Webhooks Per Posting
You can register multiple webhooks for the same posting to subscribe to different event types or send events to different endpoints.
Example: Subscribe to all events for a single posting
Best Practices
Respond Quickly
Return a 200 status code as soon as you receive the webhook. Perform any heavy processing (database writes, downstream API calls, etc.) asynchronously to avoid timeouts.
Handle Duplicate Events
Use the interview_id field to deduplicate events. In rare cases, the same event may be delivered more than once. Design your handler to be idempotent.
Validate Payloads
Always validate the structure of incoming payloads before processing. Check for required fields and handle missing or unexpected data gracefully. Many fields can be null depending on the interview configuration.
Use HTTPS Endpoints
Always use HTTPS URLs for your webhook endpoints to ensure data is encrypted in transit. HeyMilo sends sensitive candidate information in webhook payloads.
Monitor Webhook Health
Log all incoming webhook requests and monitor for failures. If your endpoint becomes unreachable, events may be missed. Consider implementing alerting for webhook processing errors.
Scope Webhooks to Postings
Register webhooks only for the job postings you need to monitor. This reduces noise and ensures your endpoint only receives relevant events.
Handle Nullable Fields
Many fields in the report_available payload can be null depending on the posting configuration (e.g., resume_interview_info, sms_interview_info, form_interview_info). Always check for null before accessing nested properties.
Common Use Cases
ATS Sync
Use interview_completed or report_available webhooks to automatically push interview results back to your Applicant Tracking System. Extract the score, workflow status, and report data to update candidate records in real time.
Recruiter Notifications
Trigger Slack, email, or SMS notifications to recruiters when candidates complete interviews. Use the interview_completed event to alert team members and include the candidate name, score, and a link to the full report.
Automated Candidate Progression
Use report_available to automatically advance or reject candidates based on their scores. For example, candidates with a match_score above a threshold can be moved to the next stage, while those below can receive an automated rejection email.
Analytics & Dashboards
Stream webhook events into your analytics platform to build custom hiring dashboards. Track metrics like time-to-complete, average scores, and candidate throughput across postings.
Workflow Automation (Zapier / Make)
Use webhook URLs as triggers in Zapier, Make, or other automation platforms. This enables no-code workflows like adding candidates to Google Sheets, sending calendar invites, or updating CRM records when interviews are completed.
Error Handling
If your endpoint returns a non-200 status code, the webhook delivery is considered failed. Ensure your endpoint is reliable and returns 200 promptly.
Common Errors
Endpoint returns 4xx
Check your endpoint URL and ensure it accepts the correct HTTP method
Endpoint returns 5xx
Investigate server-side errors in your application
Endpoint unreachable
Verify your endpoint is publicly accessible and DNS is configured
Payload parsing fails
Validate the Content-Type header and JSON body parsing logic
Support
For webhook support and questions:
Email: [email protected]
Documentation: https://docs.heymilo.cloud
Status Page: https://status.heymilo.ai
Last updated