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 false to 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_hours subscriptions are migrated to this name, and payloads now use call.outside_business_hours.

  • Name
    call.queued
    Description

    The caller joined the employee wait queue. The payload is the existing call envelope; state is queued and answered_at is still null. Fires once per call.

  • Name
    call.answered
    Description

    The call was answered by an employee. answered_at is now set on the call, and employees includes the employee who answered.

  • Name
    call.ended
    Description

    The call has ended, regardless of outcome. Fires for every call that reaches the ended state — 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 transcription and transcription_segments fields are now populated on the call. The summary is generated afterwards, so do not rely on summary being populated in this event. Subscribe to call.summary_done to receive it.

  • Name
    call.summary_done
    Description

    The AI summary of the call has been saved. The payload includes summary, transcription, and transcription_segments. Dispatched after call.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.deleted lists transcription, recording, or both. Deleting transcription data also deletes the summary, stored caller context, and whisper brief, even if no transcript exists. data.reason is retention_policy for scheduled deletion, keep_disabled when temporary audio is removed after transcription, or manual when 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 voicemail object now has its transcription field populated.

  • Name
    voicemail.data_deleted
    Description

    A voicemail transcription or recording was manually deleted. data.deleted lists transcription, recording, or both, and data.reason is manual.

  • Name
    contact.created
    Description

    A new contact was added to your address book. The payload's data.contact object includes the full contact model.

  • Name
    contact.updated
    Description

    An existing contact was edited. The payload's data.contact object includes the new values.

  • Name
    contact.deleted
    Description

    A contact was removed. The payload's data.contact object reflects the contact at the time of deletion.

  • Name
    employee.status.changed
    Description

    An employee's live presence changed (for example from available to on_call, or when they enable/disable do-not-disturb). The payload's data.employee object matches the employee model, including status, do_not_disturb, do_not_disturb_activated_at, and do_not_disturb_expires_at. It also has a call_id: the call the employee is ringing for when status is ringing, the call they are on when status is on_call, and null otherwise. If an employee rings for several calls at once, call_id is the most recent one. The event also fires when call_id changes while status stays the same.

  • Name
    number.registration_approved
    Description

    A business number's regulatory registration was approved by the carrier. The payload's business_number includes id, number, and registration_status.

  • Name
    number.registration_rejected
    Description

    A business number's regulatory registration was rejected. The payload's business_number includes id, number, and registration_status. A sibling reason string 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.


GET/v1/webhooks

List webhooks

Returns all webhook subscriptions for your company.

Request

GET
/v1/webhooks
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"
  }
]

POST/v1/webhooks

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

POST
/v1/webhooks
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"
}

PATCH/v1/webhooks/:id

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 false to pause delivery, true to resume.

Request

PATCH
/v1/webhooks/:id
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/v1/webhooks/:id

Delete a webhook

Permanently removes a webhook subscription. Events will stop being delivered immediately.

Request

DELETE
/v1/webhooks/:id
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.