Webhooks
Webhook events
Read from the API’s own reference file every hour.
Each event is an HTTPS POST to your endpoint, in the same envelope with its own data. How to answer a delivery, check its signature and read its retries is on the endpoints page.
call.started
POSTAn extension started ringing or dialing.
An extension started ringing on an incoming call, or started dialing an outgoing one. end_time and duration are null.
We look for new call events every 5 seconds, so it usually arrives within seconds. Each event is one extension's view of the call: a call that rings several extensions can send one event per extension. Numbers are digits without the leading 1.
Known issue: group_number is one fixed number of your account, the same on every call event, not always the number that was dialed. A number_filters entry for your own number can miss these events.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always call.started. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | The phone system's id for the call. It ties a call's events together. It is not always the same as call_id in GET /v1/calls. |
data. required | string | incoming, outgoing, or unknown when the phone system did not say. One of incoming, outgoing or unknown. |
data. required | string or null | The extension this event is about. |
data. required | string or null | Its name, written First Last. |
data. required | string or null | The other party's name from caller ID. |
data. required | string or null | The other party's number, digits without the leading 1. |
data. required | string or null | One number of your account, digits without the leading 1. Known issue: it is the same number on every call event, not always the number that was dialed. |
data. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
data. required | string (date-time) or null | Null until the call ends. |
data. required | integer or null | Seconds from answer to hang-up. Null until the call ends, and on a call nobody answered. |
{
"id": "evt_6703a1f25c9e8.21736450",
"event_type": "call.started",
"timestamp": "2026-09-24T14:03:14+00:00",
"company_id": 1234567890,
"data": {
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-24T14:03:12.000Z",
"end_time": null,
"duration": null
}
}Your answer
call.answered
POSTAn extension answered.
An extension answered the call. end_time and duration are null.
We look for new call events every 5 seconds, so it usually arrives within seconds. Each event is one extension's view of the call: a call that rings several extensions can send one event per extension. Numbers are digits without the leading 1.
Known issue: group_number is one fixed number of your account, the same on every call event, not always the number that was dialed. A number_filters entry for your own number can miss these events.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always call.answered. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | The phone system's id for the call. It ties a call's events together. It is not always the same as call_id in GET /v1/calls. |
data. required | string | incoming, outgoing, or unknown when the phone system did not say. One of incoming, outgoing or unknown. |
data. required | string or null | The extension this event is about. |
data. required | string or null | Its name, written First Last. |
data. required | string or null | The other party's name from caller ID. |
data. required | string or null | The other party's number, digits without the leading 1. |
data. required | string or null | One number of your account, digits without the leading 1. Known issue: it is the same number on every call event, not always the number that was dialed. |
data. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
data. required | string (date-time) or null | Null until the call ends. |
data. required | integer or null | Seconds from answer to hang-up. Null until the call ends, and on a call nobody answered. |
{
"id": "evt_6703a1f3d7b21.58214907",
"event_type": "call.answered",
"timestamp": "2026-09-24T14:03:33+00:00",
"company_id": 1234567890,
"data": {
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-24T14:03:12.000Z",
"end_time": null,
"duration": null
}
}Your answer
call.ended
POSTA call ended.
The call ended for an extension. duration is seconds from answer to hang-up, or null when nobody answered.
We look for new call events every 5 seconds, so it usually arrives within seconds. Each event is one extension's view of the call: a call that rings several extensions can send one event per extension. Numbers are digits without the leading 1.
Known issue: group_number is one fixed number of your account, the same on every call event, not always the number that was dialed. A number_filters entry for your own number can miss these events.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always call.ended. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | The phone system's id for the call. It ties a call's events together. It is not always the same as call_id in GET /v1/calls. |
data. required | string | incoming, outgoing, or unknown when the phone system did not say. One of incoming, outgoing or unknown. |
data. required | string or null | The extension this event is about. |
data. required | string or null | Its name, written First Last. |
data. required | string or null | The other party's name from caller ID. |
data. required | string or null | The other party's number, digits without the leading 1. |
data. required | string or null | One number of your account, digits without the leading 1. Known issue: it is the same number on every call event, not always the number that was dialed. |
data. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
data. required | string (date-time) or null | Null until the call ends. |
data. required | integer or null | Seconds from answer to hang-up. Null until the call ends, and on a call nobody answered. |
{
"id": "evt_6703a1f8e0c46.73920518",
"event_type": "call.ended",
"timestamp": "2026-09-24T14:09:43+00:00",
"company_id": 1234567890,
"data": {
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-24T14:03:12.000Z",
"end_time": "2026-09-24T14:09:40.000Z",
"duration": 369
}
}Your answer
call.transcription
POSTA recorded call has its transcript.
A recorded call leg has its transcript and AI summary. One event per recording: a call parked and picked up again is recorded in parts and sends one event per part.
It is sent once the finished transcript is ready, usually a few minutes after the call. We check every 2 minutes and wait up to 6 hours for the finished transcript. extension is the recorded leg's extension. The times and duration are the whole call's. direction reads as in GET /v1/calls.
recording_id, part, parts, recording_start_time and recording_duration say which recording the words are. Part N of a leg is GET /v1/media/rec_<n>?part=N and the same entry of recordings in GET /v1/calls. parts counts the parts saved when the event was sent. part is null for a recording of another call leg that is linked to the same leg of the report.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always call.transcription. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | The phone system's id for the call. |
data. required | string | incoming or outgoing, as GET /v1/calls shows it. |
data. required | string or null | The extension on the recorded leg. |
data. required | string or null | |
data. required | string or null | |
data. required | string or null | Digits without the leading 1. |
data. required | string or null | Your number on the call, digits without the leading 1. |
data. required | string (date-time) or null | The call's start. UTC, ISO 8601 with milliseconds. |
data. required | string (date-time) or null | The call's end. UTC, ISO 8601 with milliseconds. |
data. required | integer | The call's length in seconds. |
data. required | string or null | The AI summary. Null when there is none. |
data. required | string | The transcript, with speaker labels. |
data. | integer | The recording these words are, as in recordings in GET /v1/calls. |
data. | integer or null | This recording's part of the leg, from 1. Null for a recording of another call leg linked to the same leg of the report. |
data. | integer or null | How many parts the leg's recording had when the event was sent. Nearly always 1. |
data. | string (date-time) or null | When this recording started. UTC, ISO 8601 with milliseconds. |
data. | integer or null | This recording's length in seconds. |
{
"id": "evt_6703a2b41f9d2.30481726",
"event_type": "call.transcription",
"timestamp": "2026-09-24T14:13:05+00:00",
"company_id": 1234567890,
"data": {
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-24T14:03:12.000Z",
"end_time": "2026-09-24T14:09:40.000Z",
"duration": 388,
"summary": "Jordan Reyes asked to move the Thursday appointment to Friday at 10 AM. Maya Chen confirmed the new time and said a reminder text will follow.",
"transcription": "Speaker 1: Good morning, thanks for calling. This is Maya.\nSpeaker 2: Hi Maya, this is Jordan Reyes. I need to move my Thursday appointment.\nSpeaker 1: No problem. Would Friday at 10 AM work?\nSpeaker 2: Friday at 10 is perfect. Thank you.",
"recording_id": 10577702,
"part": 2,
"parts": 2,
"recording_start_time": "2026-09-24T14:04:31.000Z",
"recording_duration": 309
}
}Your answer
message.sent
POSTA text went out through the API or an automation.
A text left through the API or an automation: a send on a number in api or email mode, a picture message sent through the API, or a mass or group text. It is sent as soon as the carrier takes the message. message_id is the carrier's id, the same one the send returned. For a picture message sent through the API, attachments lists the URLs you sent.
Today a text sent from Webex does not fire message.sent. That includes POST /v1/messages on a Webex-mode number, replies your team types in Webex or sends by email, and WhatsApp replies. Those messages are in GET /v1/messages.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always message.sent. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string or null | For a text, the carrier's message id: the same one a send in api or email mode returns and GET /v1/messages shows. For WhatsApp, the WhatsApp message id. |
data. required | string | One of incoming or outgoing. |
data. required | string | One of text or whatsapp. |
data. required | string | E.164, like +17185550142. |
data. required | string | E.164. On a group text, the recipients. |
data. required | string | The message text. Empty on most delivery receipts. |
data. required | string | delivered on received messages, sent on sent ones. On status updates: for a text delivered or failed; for WhatsApp its status, for example delivered, read or failed. |
data. required | string or null | Why a message failed, from the carrier. Null otherwise. |
data. required | string or null | When the message was sent or received, ISO 8601 as the source reported it. The offset varies. |
data. required | array, each object or string (uri) | Files on the message. Received messages list objects. A picture message sent through the API lists the URLs you sent. |
data. required | string (uri) or null | https://api.vocatech.com/v1/media/att_<n>: call it with your key for a signed link. |
data. required | string or null | |
data. required | string or null | |
data. required | integer or null |
{
"id": "evt_6703a3d19b6f2.17394056",
"event_type": "message.sent",
"timestamp": "2026-09-24T14:22:06+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_9b2e5a",
"direction": "outgoing",
"channel": "text",
"from": "+17185550100",
"to": "+17185550142",
"body": "Friday at 10 AM works. See you then.",
"status": "sent",
"error": null,
"sent_at": "2026-09-24T10:22:05-04:00",
"attachments": []
}
}{
"id": "evt_6703a3e2b0d58.47213960",
"event_type": "message.sent",
"timestamp": "2026-09-24T14:06:45+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_5d8f1b",
"direction": "outgoing",
"channel": "text",
"from": "+17185550100",
"to": "+17185550142",
"body": "Here is the estimate we discussed.",
"status": "sent",
"error": null,
"sent_at": "2026-09-24T10:06:44-04:00",
"attachments": [
"https://files.example.com/estimates/estimate-2291.pdf"
]
}
}Your answer
message.received
POSTA text or WhatsApp message arrived.
A text or WhatsApp message arrived on one of your numbers. It is sent as soon as the message arrives.
attachments lists each picture or file with its link to GET /v1/media. A file we could not store has url set to null.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always message.received. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string or null | For a text, the carrier's message id: the same one a send in api or email mode returns and GET /v1/messages shows. For WhatsApp, the WhatsApp message id. |
data. required | string | One of incoming or outgoing. |
data. required | string | One of text or whatsapp. |
data. required | string | E.164, like +17185550142. |
data. required | string | E.164. On a group text, the recipients. |
data. required | string | The message text. Empty on most delivery receipts. |
data. required | string | delivered on received messages, sent on sent ones. On status updates: for a text delivered or failed; for WhatsApp its status, for example delivered, read or failed. |
data. required | string or null | Why a message failed, from the carrier. Null otherwise. |
data. required | string or null | When the message was sent or received, ISO 8601 as the source reported it. The offset varies. |
data. required | array, each object or string (uri) | Files on the message. Received messages list objects. A picture message sent through the API lists the URLs you sent. |
data. required | string (uri) or null | https://api.vocatech.com/v1/media/att_<n>: call it with your key for a signed link. |
data. required | string or null | |
data. required | string or null | |
data. required | integer or null |
{
"id": "evt_6703a3c07a5e1.64820193",
"event_type": "message.received",
"timestamp": "2026-09-24T14:20:32+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_7f3a9c",
"direction": "incoming",
"channel": "text",
"from": "+17185550142",
"to": "+17185550100",
"body": "Can we move my appointment to Friday?",
"status": "delivered",
"error": null,
"sent_at": "2026-09-24T14:20:31.512Z",
"attachments": [
{
"url": "https://api.vocatech.com/v1/media/att_90211",
"content_type": "image/jpeg",
"filename": "photo-0924.jpg",
"size": 184233
}
]
}
}Your answer
message.status_updated
POSTThe carrier reported on a text.
The carrier reported what happened to a text you sent, or WhatsApp reported a status change. It is sent as soon as the report arrives.
For a text, status is delivered, or failed with the carrier's reason in error. A text whose receipt never came back sends no event. For WhatsApp, status is the WhatsApp status, for example delivered, read or failed. body is empty except on a failed text. Match message_id to the send or to GET /v1/messages.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always message.status_updated. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string or null | For a text, the carrier's message id: the same one a send in api or email mode returns and GET /v1/messages shows. For WhatsApp, the WhatsApp message id. |
data. required | string | One of incoming or outgoing. |
data. required | string | One of text or whatsapp. |
data. required | string | E.164, like +17185550142. |
data. required | string | E.164. On a group text, the recipients. |
data. required | string | The message text. Empty on most delivery receipts. |
data. required | string | delivered on received messages, sent on sent ones. On status updates: for a text delivered or failed; for WhatsApp its status, for example delivered, read or failed. |
data. required | string or null | Why a message failed, from the carrier. Null otherwise. |
data. required | string or null | When the message was sent or received, ISO 8601 as the source reported it. The offset varies. |
data. required | array, each object or string (uri) | Files on the message. Received messages list objects. A picture message sent through the API lists the URLs you sent. |
data. required | string (uri) or null | https://api.vocatech.com/v1/media/att_<n>: call it with your key for a signed link. |
data. required | string or null | |
data. required | string or null | |
data. required | integer or null |
{
"id": "evt_6703a3d4c1a07.92057341",
"event_type": "message.status_updated",
"timestamp": "2026-09-24T14:22:09+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_9b2e5a",
"direction": "outgoing",
"channel": "text",
"from": "+17185550100",
"to": "+17185550142",
"body": "",
"status": "delivered",
"error": null,
"sent_at": "2026-09-24T14:22:07.880Z",
"attachments": []
}
}{
"id": "evt_6703a3d6e8b14.30958216",
"event_type": "message.status_updated",
"timestamp": "2026-09-24T14:25:40+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_1e7b4d",
"direction": "outgoing",
"channel": "text",
"from": "+17185550100",
"to": "+17185550143",
"body": "Friday at 10 AM works. See you then.",
"status": "failed",
"error": "Carrier rejected the message",
"sent_at": "2026-09-24T14:25:38.214Z",
"attachments": []
}
}{
"id": "evt_6703a3d9a2c75.11846230",
"event_type": "message.status_updated",
"timestamp": "2026-09-24T14:31:12+00:00",
"company_id": 1234567890,
"data": {
"message_id": "msg_6f0a2c",
"direction": "outgoing",
"channel": "whatsapp",
"from": "+17185550100",
"to": "+17185550142",
"body": "",
"status": "read",
"error": null,
"sent_at": "2026-09-24 14:31:10",
"attachments": []
}
}Your answer
fax.sent
POSTAn outgoing fax is in progress.
An outgoing fax was handed to the fax carrier and is in progress.
We look for new faxes on a schedule. Each fax is read once, when it first appears, and the event is chosen by its status at that moment. A later change sends no further event: a fax that finishes after we first saw it sends no fax.delivered or fax.failed. Read the final status with GET /v1/faxes.
Known issue: sent_at is Eastern time written with a Z, so it reads 4 or 5 hours early.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always fax.sent. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | Use it with GET /v1/media/{id} once the document is ready. Matches ^fax_[0-9]+$. |
data. required | string | One of incoming or outgoing. |
data. required | string | E.164. |
data. required | string | E.164. |
data. required | integer or null | |
data. required | string or null | |
data. required | string | One of in_progress, completed, failed, restricted or unknown. |
data. required | string or null | The fax carrier's job id. |
data. required | string (date-time) or null | When the fax was logged. Known issue: Eastern time written with a Z, so it reads 4 or 5 hours early. |
{
"id": "evt_6703a41e2d8b3.48102967",
"event_type": "fax.sent",
"timestamp": "2026-09-24T14:06:02+00:00",
"company_id": 1234567890,
"data": {
"fax_id": "fax_77120",
"direction": "outgoing",
"from": "+17185550100",
"to": "+17185550142",
"pages": null,
"subject": "Intake form",
"status": "in_progress",
"faxage_job_id": "93125501",
"sent_at": "2026-09-24T10:05:09.000Z"
}
}Your answer
fax.received
POSTAn incoming fax is arriving.
An incoming fax was logged while it was still arriving. An incoming fax that was logged already complete comes as fax.delivered instead.
We look for new faxes on a schedule. Each fax is read once, when it first appears, and the event is chosen by its status at that moment. A later change sends no further event: a fax that finishes after we first saw it sends no fax.delivered or fax.failed. Read the final status with GET /v1/faxes.
Known issue: sent_at is Eastern time written with a Z, so it reads 4 or 5 hours early.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always fax.received. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | Use it with GET /v1/media/{id} once the document is ready. Matches ^fax_[0-9]+$. |
data. required | string | One of incoming or outgoing. |
data. required | string | E.164. |
data. required | string | E.164. |
data. required | integer or null | |
data. required | string or null | |
data. required | string | One of in_progress, completed, failed, restricted or unknown. |
data. required | string or null | The fax carrier's job id. |
data. required | string (date-time) or null | When the fax was logged. Known issue: Eastern time written with a Z, so it reads 4 or 5 hours early. |
{
"id": "evt_6703a5a07e4c9.26039174",
"event_type": "fax.received",
"timestamp": "2026-09-24T15:39:31+00:00",
"company_id": 1234567890,
"data": {
"fax_id": "fax_77131",
"direction": "incoming",
"from": "+12125550187",
"to": "+17185550100",
"pages": null,
"subject": null,
"status": "in_progress",
"faxage_job_id": "93125870",
"sent_at": "2026-09-24T11:39:02.000Z"
}
}Your answer
fax.delivered
POSTA fax completed.
A fax was logged as completed when we first saw it. Fetch the document with GET /v1/media/{fax_id}.
We look for new faxes on a schedule. Each fax is read once, when it first appears, and the event is chosen by its status at that moment. A later change sends no further event: a fax that finishes after we first saw it sends no fax.delivered or fax.failed. Read the final status with GET /v1/faxes.
Known issue: sent_at is Eastern time written with a Z, so it reads 4 or 5 hours early.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always fax.delivered. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | Use it with GET /v1/media/{id} once the document is ready. Matches ^fax_[0-9]+$. |
data. required | string | One of incoming or outgoing. |
data. required | string | E.164. |
data. required | string | E.164. |
data. required | integer or null | |
data. required | string or null | |
data. required | string | One of in_progress, completed, failed, restricted or unknown. |
data. required | string or null | The fax carrier's job id. |
data. required | string (date-time) or null | When the fax was logged. Known issue: Eastern time written with a Z, so it reads 4 or 5 hours early. |
{
"id": "evt_6703a5b3f1d06.85216403",
"event_type": "fax.delivered",
"timestamp": "2026-09-24T15:41:02+00:00",
"company_id": 1234567890,
"data": {
"fax_id": "fax_77135",
"direction": "incoming",
"from": "+12125550187",
"to": "+17185550100",
"pages": 2,
"subject": null,
"status": "completed",
"faxage_job_id": "93125877",
"sent_at": "2026-09-24T11:40:00.000Z"
}
}Your answer
fax.failed
POSTA fax failed.
A fax was logged as failed or restricted when we first saw it, for example an outgoing fax the carrier refused at once.
We look for new faxes on a schedule. Each fax is read once, when it first appears, and the event is chosen by its status at that moment. A later change sends no further event: a fax that finishes after we first saw it sends no fax.delivered or fax.failed. Read the final status with GET /v1/faxes.
Known issue: sent_at is Eastern time written with a Z, so it reads 4 or 5 hours early.
Headers
| Name | In | Type | Description |
|---|---|---|---|
X-Vocatech-Signature required | header | string | t=<unix seconds>,v1=<hex HMAC-SHA256 of t=<t>.<raw body>, keyed with your secret_key>. Reject the delivery if t is more than 300 seconds from your clock or v1 does not match. For example t=1790259302,v1=4e1c9a7b2f5d8e3a6c0b9f2e5d8a1c4b7e0f3a6d9c2b5e8f1a4d7c0b3e6f9a2d. |
X-Vocatech-Event required | header | string | The event type, the same as event_type in the body. |
User-Agent required | header | string | Always Vocatech-Webhook/1.0. Always Vocatech-Webhook/1.0. |
Payload
| Field | Type | Description |
|---|---|---|
id required | string | A unique id for this delivery's event. Retries repeat it. Use it to skip duplicates. For example evt_6703a1f25c9e8.21736450. |
event_type required | string | Always fax.failed. |
timestamp required | string (date-time) | When we built the event. ISO 8601 with +00:00. |
company_id required | integer | Your company id. |
data required | object | |
data. required | string | Use it with GET /v1/media/{id} once the document is ready. Matches ^fax_[0-9]+$. |
data. required | string | One of incoming or outgoing. |
data. required | string | E.164. |
data. required | string | E.164. |
data. required | integer or null | |
data. required | string or null | |
data. required | string | One of in_progress, completed, failed, restricted or unknown. |
data. required | string or null | The fax carrier's job id. |
data. required | string (date-time) or null | When the fax was logged. Known issue: Eastern time written with a Z, so it reads 4 or 5 hours early. |
{
"id": "evt_6703a60c4a2e8.60371925",
"event_type": "fax.failed",
"timestamp": "2026-09-24T16:02:03+00:00",
"company_id": 1234567890,
"data": {
"fax_id": "fax_77140",
"direction": "outgoing",
"from": "+17185550100",
"to": "+17185550142",
"pages": null,
"subject": "Intake form",
"status": "failed",
"faxage_job_id": null,
"sent_at": "2026-09-24T12:01:40.000Z"
}
}