Webhooks
Get notified the instant something happens — a call comes in, a voicemail is left, or a transcription finishes. Register a URL once, pick the events you care about, and Phone.inc will POST a JSON payload to your endpoint in real time.
The webhook model
A webhook subscription tells Phone.inc where to send event notifications and which events to include.
Properties
- Name
id- Type
- string
- Description
Unique public identifier for the webhook.
- Name
name- Type
- string
- Description
A human-readable label for the webhook (e.g.
Slack notifications,CRM sync).
- Name
url- Type
- string
- Description
The HTTPS endpoint where events are delivered via POST.
- Name
events- Type
- array
- Description
List of event types this webhook subscribes to. See Events for all available types.
- Name
active- Type
- boolean
- Description
Whether the webhook is currently receiving events. Set to
falseto pause delivery without deleting the subscription.
- Name
created_at- Type
- timestamp
- Description
ISO 8601 timestamp of when the webhook was created.
- Name
updated_at- Type
- timestamp
- Description
ISO 8601 timestamp of the last update.
Events
Each event maps to a specific moment in a call's lifecycle or a voicemail being recorded.
- Name
call.initiated- Description
A new inbound or outbound call has started. The call exists but hasn't been answered yet.
- Name
call.outside_business_hours- Description
An inbound call arrived outside the business number's configured business hours. Existing
call.outside_opening_hourssubscriptions are migrated to this name, and payloads now usecall.outside_business_hours.
- Name
call.queued- Description
The caller joined the employee wait queue. The payload is the existing call envelope;
stateisqueuedandanswered_atis still null. Fires once per call.
- Name
call.answered- Description
The call was answered by an employee.
answered_atis now set on the call, andemployeesincludes the employee who answered.
- Name
call.ended- Description
The call has ended, regardless of outcome. Fires for every call that reaches the
endedstate — answered, missed, or rejected.
- Name
call.lost- Description
The call ended without being answered and without a spoken voicemail message. This includes recordings containing only silence or sound effects. Discarding a sound-only recording emits this event unless it was already emitted for the call.
- Name
call.transcription_done- Description
The call recording has been transcribed. The
transcriptionandtranscription_segmentsfields are now populated on the call. The summary is generated afterwards, so do not rely onsummarybeing populated in this event. Subscribe tocall.summary_doneto receive it.
- Name
call.summary_done- Description
The AI summary of the call has been saved. The payload includes
summary,transcription, andtranscription_segments. Dispatched aftercall.transcription_done, but webhook deliveries may arrive out of order. Not sent when the call has too little conversation to summarize, contains no meaningful content, or its transcription was deleted during summary generation.
- Name
call.data_deleted- Description
Call content or a recording was deleted.
data.deletedliststranscription,recording, or both. Deleting transcription data also deletes the summary, stored caller context, and whisper brief, even if no transcript exists.data.reasonisretention_policyfor scheduled deletion,keep_disabledwhen temporary audio is removed after transcription, ormanualwhen an employee deletes call data.
- Name
voicemail.new- Description
A new voicemail was recorded and confirmed to contain spoken words. Fires after transcription, not immediately after the recording upload. The payload includes both the call and voicemail data, including the transcription.
- Name
voicemail.transcription_done- Description
The voicemail recording has been transcribed. The payload's
voicemailobject now has itstranscriptionfield populated.
- Name
voicemail.data_deleted- Description
A voicemail transcription or recording was manually deleted.
data.deletedliststranscription,recording, or both, anddata.reasonismanual.
- Name
contact.created- Description
A new contact was added to your address book. The payload's
data.contactobject includes the full contact model.
- Name
contact.updated- Description
An existing contact was edited. The payload's
data.contactobject includes the new values.
- Name
contact.deleted- Description
A contact was removed. The payload's
data.contactobject reflects the contact at the time of deletion.
- Name
employee.status.changed- Description
An employee's live presence changed (for example from
availabletoon_call, or when they enable/disable do-not-disturb). The payload'sdata.employeeobject matches the employee model, includingstatus,do_not_disturb,do_not_disturb_activated_at, anddo_not_disturb_expires_at. It also has acall_id: the call the employee is ringing for whenstatusisringing, the call they are on whenstatusison_call, andnullotherwise. If an employee rings for several calls at once,call_idis the most recent one. The event also fires whencall_idchanges whilestatusstays the same.
- Name
number.registration_approved- Description
A business number's regulatory registration was approved by the carrier. The payload's
business_numberincludesid,number, andregistration_status.
- Name
number.registration_rejected- Description
A business number's regulatory registration was rejected. The payload's
business_numberincludesid,number, andregistration_status. A siblingreasonstring explains the rejection.
Payload structure
Call, voicemail, contact, and employee webhook deliveries are JSON POSTs with the following envelope:
Webhook payload
{
"event": "call.answered",
"timestamp": "2026-05-15T14:22:33Z",
"data": {
"id": "01JVWX...",
"call_control_id": "v3:...",
"from": "+14155551234",
"to": "+14155559876",
"direction": "inbound",
"state": "answered",
"started_at": "2026-05-15T14:22:00Z",
"answered_at": "2026-05-15T14:22:33Z",
"duration": null,
"summary": null,
"transcription": null,
"transcription_segments": null,
"business_number_id": "01JVWX...",
"business_number_name": "Sales",
"business_number_number": "+14155559876",
"business_number_number_formatted": "(415) 555-9876",
"employees": [{ "id": "01JVWX...", "name": "Jane Smith", "first_name": "Jane", "last_name": "Smith" }],
"initiated_by": null
}
}
For call.* events, the data object contains the full call model. On call.data_deleted, deleted fields are already null, data.deleted identifies what was removed, and data.reason identifies why. For voicemail.new, voicemail.transcription_done, and voicemail.data_deleted events, the payload also includes a voicemail object nested inside data with the voicemail id, from, business_number_name, business_number_number, transcription, and created_at. The transcription is populated on voicemail.new and voicemail.transcription_done, and null after voicemail.data_deleted. For contact.created, contact.updated, and contact.deleted events, data contains a contact object with the full contact model. For employee.status.changed events, data contains an employee object with the full employee model (including status) plus call_id. For number.registration_approved and number.registration_rejected events, the top level contains a business_number object with id, number, and registration_status; rejected events also include a reason string.
Registration events use this payload structure:
Registration payload
{
"event": "number.registration_rejected",
"business_number": {
"id": "01JVWX...",
"number": "+14155559876",
"registration_status": "rejected"
},
"reason": "Address does not match identity country"
}
Your endpoint should return a 2xx status code to acknowledge receipt. Non-2xx responses trigger up to 5 retries with exponential backoff.
Webhook payloads are sent with Content-Type: application/json and a User-Agent: PhoneInc-Webhooks/1.0 header.
List webhooks
Returns all webhook subscriptions for your company.
Request
curl https://app.phone.inc/api/v1/webhooks \
-H "X-Api-Key: $PHONE_INC_API_KEY"
Response
[
{
"id": "01JVWX...",
"name": "Slack notifications",
"url": "https://example.com/webhooks",
"events": ["call.initiated", "call.answered", "voicemail.new"],
"active": true,
"created_at": "2026-05-15T10:00:00Z",
"updated_at": "2026-05-15T10:00:00Z"
}
]
Create a webhook
Registers a new webhook subscription.
Required attributes
- Name
name- Type
- string
- Description
A human-readable label for the webhook.
- Name
url- Type
- string
- Description
The HTTPS endpoint to receive events.
- Name
events- Type
- array
- Description
One or more event types to subscribe to. See Events.
Request
curl -X POST https://app.phone.inc/api/v1/webhooks \
-H "X-Api-Key: $PHONE_INC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Slack notifications",
"url": "https://example.com/webhooks",
"events": ["call.initiated", "call.answered"]
}'
Response
{
"id": "01JVWX...",
"name": "Slack notifications",
"url": "https://example.com/webhooks",
"events": ["call.initiated", "call.answered"],
"active": true,
"created_at": "2026-05-15T10:00:00Z",
"updated_at": "2026-05-15T10:00:00Z"
}
Update a webhook
Updates an existing webhook. You can change the URL, events, or toggle it on/off.
Optional attributes
- Name
name- Type
- string
- Description
New label for the webhook.
- Name
url- Type
- string
- Description
New endpoint URL.
- Name
events- Type
- array
- Description
Replace the subscribed events list.
- Name
active- Type
- boolean
- Description
Set to
falseto pause delivery,trueto resume.
Request
curl -X PATCH https://app.phone.inc/api/v1/webhooks/01JVWX... \
-H "X-Api-Key: $PHONE_INC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"active": false}'
Response
{
"id": "01JVWX...",
"name": "Slack notifications",
"url": "https://example.com/webhooks",
"events": ["call.initiated", "call.answered"],
"active": false,
"created_at": "2026-05-15T10:00:00Z",
"updated_at": "2026-05-15T14:30:00Z"
}
Delete a webhook
Permanently removes a webhook subscription. Events will stop being delivered immediately.
Request
curl -X DELETE https://app.phone.inc/api/v1/webhooks/01JVWX... \
-H "X-Api-Key: $PHONE_INC_API_KEY"
Returns 204 No Content on success.