All API updates are backwards compatible. We reserve the right to introduce new JSON keys in existing API responses at any time. We recommend handling responses defensively by disregarding any unrecognized keys to ensure continued functionality.
Requests use basic authentication. To create API credentials go to Settings-> Developer Settings-> API Credentials
The subdomain is used as the username ({{username}} variable)
The token is used as the password ({{password}} variable)
Every installation will have their own subdomain. To find the subdomain, locate the url in your browser, it should look like:
Take that subdomain, the most left value, and substitute it into the {{subdomain}} variable. The remainder would be substituted into the {{domain}} variable.
In the above example, {{subdomain}} would be “customer” and {{domain}} would be “rest.of.url.com”
The API uses the following base URL for all of its API requests
https://{{subdomain}}.{{domain}}/apps/api/v1
where a mention to “/calls” means https://{{subdomain}}.{{domain}}/apps/api/v1/calls
A call object is created for every single call that is made into, or out of the system.
{
"id": 0,
"parent_id": 0,
"lang": "en",
"call_type": "Voice Scheduled (API)",
"status": "scheduled",
"created_at": "2018-06-07T19:49:52.896Z",
"queued_at": "2018-06-07T19:49:52.896Z",
"assigned_at": "2018-06-07T19:49:52.896Z",
"connected_at": "2018-06-07T19:49:52.896Z",
"ends_at": "2018-06-07T19:49:52.896Z",
"scheduled_at": "2018-06-07T19:49:52.896Z",
"wait_duration": 0,
"call_duration": 0,
"hold_duration": 0,
"rating": 0,
"has_feedback": true,
"voip_provider": "voip_provider_twilio",
"out_ticket_id": "string",
"out_ticket_url": "string",
"verified": true,
"recording_url": "string",
"recording_permission": "not_asked",
"voicemail_reason": "not_voicemail",
"deflection": "no_deflection",
"disconnected_by": "disconnected_by_unknown",
"finish_reason": "no_reason",
"fail_details": "string",
"fail_reason": "nothing",
"support_number": "string",
"selected_menu": {
"id": 0,
"name": "string",
"parent_id": 0,
"position": 0,
"deleted": true,
"hidden": "string",
"menu_type": "ivr_menu",
"output_msg": "string"
},
"menu_path": {
"items_count": 0,
"name": "string",
"materialized_path": "string"
},
"agent_info": {
"id": 0,
"name": "string",
"last_name": "string",
"first_name": "string",
"agent_number": "string",
"avatar_url": "string"
},
"end_user": {
"id": 0,
"identifier": "string",
"out_contact_id": "string"
},
"photos": [
{
"id": 0,
"photo_type": "photo",
"url": "string"
}
],
"videos": [
{
"id": 0,
"url": "string"
}
],
"transfers": [
{
"id": 0,
"status": "transferring",
"fail_reason": "nothing",
"created_at": "2018-06-07T19:49:52.896Z",
"from_menu": {
"items_count": 0,
"name": "string",
"materialized_path": "string"
},
"to_menu": {
"items_count": 0,
"name": "string",
"materialized_path": "string"
},
"from_agent": {
"id": 0,
"name": "string",
"last_name": "string",
"first_name": "string",
"agent_number": "string",
"avatar_url": "string"
},
"to_agent": {
"id": 0,
"name": "string",
"last_name": "string",
"first_name": "string",
"agent_number": "string",
"avatar_url": "string"
}
}
],
"participants": [
{
"id": 0,
"type": "end_user",
"status": "waiting",
"call_id": 0,
"user_id": 0,
"end_user_id": 0,
"call_duration": 0,
"hold_duration": 0,
"connected_at": "2018-06-07T19:49:52.896Z",
"ended_at": "2018-06-07T19:49:52.896Z",
"fail_reason": "nothing"
}
]
}
]
The status field can be in any of the following states
| Call Status | Description |
|---|---|
| Selecting | State that occurs when an end user has called into the contact center, but is still navigating the menu options prior to being placed in a leaf menu. |
| Queued | State that occurs after the end user has selected a leaf menu node and initiated a call request to be deltcasted or multicasted to an agent. |
| Assigned | State that occurs when an agent is selected to receive the end user call. This occurs when a call is picked up by an agent. |
| Connecting | State that occurs after an agent is assigned, and a connection is being established between the end user and the agent. |
| Connected | State that occurs when the call has established a connection and the agent and end user are both placed into a call. |
| Finished | State that occurs when a call ends after it has been connected. |
| Failed | State that occurs when a call ends before it was successfully connected. A fail reason will also be provided for additional details. |
| Switching | State that occurs when a call fails while trying to connect and the system attempts to connect the call with a different VOIP provider. |
| Recovered | State that occurs when a failed call is called back. This new call is a child to the original call. Recovered notes that the call back is finished without error. |
| Scheduled | State that occurs when an end user has scheduled a future call via In-Web or In-App. |
| Action Only | State that occurs when a call that is handled by our client’s own telephony provider is connected to our iOS or Android SDK. |
| Action Only Finished | State that occurs when a call that is handled by our client’s own telephony provider is connected to our iOS or Android SDK and finishes |
| Deflected | State that occurs based on the configuration for overcapacity queues or after hour calls. Deflection options include voicemail, schedule call among others. Deflection will vary based on channel (In-app, IVR, In-web) |
| Voicemail | State that occurs when an end user is deflected to a voicemail option, and opts to leave a voicemail message to listened to later. This state is present when the end user is leaving the voicemail |
| Voicemail Received | State that occurs after an end user has left a voicemail and an agent has not listened to the voicemail |
| Voicemail Read | State that occurs when an agent has opened the voicemail to listen to. |
The call_type field can only be one of the following values
| Call Type | Description |
|---|---|
| Voice Outbound (API) | Call made from Outbound Call API. |
| Voice Inbound (API) | Call made from Incoming Call API. |
| Voice Scheduled (API) | Call made from Scheduled Call API. |
The parent_id field links a call to the call it was created from. It holds the id of the call this call is a call back of, for example when the agent used Hang up & Call back, when a failed or very short call was called back, or when a virtual agent callback was placed for the end user. Call backs made by Hang up & Call back, or of a failed or very short call, all carry the original call’s id, even when they are made from a call that was itself a call back. Any other call back, such as a virtual agent callback, carries the id of the call it was placed from, so when that call was itself a call back, follow its parent_id to reach the original call. For every other call, parent_id is null or not present at all, so treat a missing parent_id the same as null. The Scheduled Calls endpoints (/v1/scheduled_calls and /v1/calls/scheduled/...) return neither parent_id nor finish_reason: a scheduled callback links to the call it came from through callback_data.original_call_id.
On its own, a call back looks like any other outbound call, so use parent_id to tell them apart: a call with parent_id set is a call back of the call with that id, and the finish_reason on the original call says why it ended (for example ag_hung_up_to_callback).
The finish_reason field is null when no reason was recorded, and otherwise one of the following values
| Finish Reason | Description |
|---|---|
| no_reason | No specific finish reason was recorded. Most calls end with this value; use disconnected_by and fail_reason to see how they ended. |
| ag_hung_up_to_callback | The agent hung up in order to call the end user back. The call back is a separate call whose parent_id is the id of the original call: this call’s id, or this call’s own parent_id if this call is itself a call back. |
| virtual_agent_escalation_failed | The virtual agent tried to escalate the call to a human agent, the escalation failed and the call ended. |
| ivr_presession_deflection_complete | The end user was deflected from the IVR to another channel (such as SMS) before reaching an agent, and the deflection completed. |
| internal_call_declined_by_agent | The receiving agent declined an internal (agent to agent) call. |
| force_ended_by_admin | An admin or manager force-ended the call. |
| force_ended_call_stuck | The platform ended the call automatically because it had been stuck in progress for too long. |
| ended_by_emergency_shutdown | The call was ended because emergency shutdown was activated on its queue. |
| ended_by_dcr_receiver_hold_timeout | Deprecated. No longer recorded; it can still appear on older calls. |
| call_declined_by_agent | The agent declined a direct inbound call or an extension call. |
| call_ended_by_blocked_number | The call was ended because the end user’s phone number is blocked. |
| scheduled_call_canceled_by_config | The scheduled call was canceled because the linked CRM record is closed. |
| scheduled_call_canceled_by_unreachable_crm | The scheduled call was canceled because the CRM could not be reached. |
| va_callback_machine_detected | A virtual agent callback reached an answering machine instead of the end user, so the call ended. |
| callback_initiated | The end user accepted a virtual agent callback. This call ended and the callback is a separate call whose parent_id is this call’s id. |
| scheduled_callback_submitted | The end user was handed to the booking virtual agent and a callback was scheduled. |
| scheduled_callback_abandoned | The end user was handed to the booking virtual agent and the call ended without a callback being scheduled. |
The following are the most common API Responses:
| Response Code | Meaning |
|---|---|
| 201 | The API request has been successful and will create a call |
| 202 | The API request has been successful, but manual intervention is required inside of the widget to complete the action |
| 400 | invalid call type - ensure call_type is supported |
| 400 | Agent is not available to take this call |
| 400 | Missing parameter - check to ensure that the required parameters have been added |
| 404 | Resource not found - Please check your subdomain |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| call_type | TRUE | String | Call type to create. “Voice Outbound (API)”, “OutboundCall” (deprecated) are available for now | Voice Outbound (API) |
| menu_id | FALSE | String / Integer | Selected menu id for outbound call to grab settings from queue instead of global settings | |
| agent_email | TRUE | String | Email address for the agent who will be assigned to the outbound call. | {{agent_email}} |
| ticket_id | FALSE | String | CRM ticket ID and it will dial to the end user who is tied to the ticket. | {{ticket_id}} |
| end_user_number | FALSE | String | End user phone number which will be dialing. ticket_id has a higher priority than end_user_number. | {{end_user_number}} |
| outbound_number | FALSE | String | Well-formed outbound number which is managed from Settings > Phone Numbers > Phone Number Management. Default outbound number will be used when empty | {{outbound_number}} |
| lang | FALSE | String | Language of the call. Uses ISO 639-1 codes. (Default: “en”) | {{lang}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| call_type | TRUE | String | Call type to create. “Voice Outbound (API)”, “OutboundCall” (deprecated) are available for now | Voice Outbound (API) |
| menu_id | FALSE | String / Integer | Selected menu id for outbound call to grab settings from queue instead of global settings | |
| agent_email | TRUE | String | Email address for the agent who will be assigned to the outbound call. | {{agent_email}} |
| ticket_id | FALSE | String | CRM ticket ID and it will dial to the end user who is tied to the ticket. | {{ticket_id}} |
| end_user_number | FALSE | String | End user phone number which will be dialing. ticket_id has a higher priority than end_user_number. | {{end_user_number}} |
| outbound_number | FALSE | String | Well-formed outbound number which is managed from Settings > Phone Numbers > Phone Number Management. Default outbound number will be used when empty | {{outbound_number}} |
| lang | FALSE | String | Language of the call. Uses ISO 639-1 codes. (Default: “en”) | {{lang}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| call_type | TRUE | String | Call type to create. Use “Voice Inbound (API)” or “IncomingCall” (deprecated) to create an incoming call. | Voice Inbound (API) |
| menu_id | TRUE | Integer | The ID of the menu to attribute the call to. Only IVR and Web menu IDs are accepted. | {{menu_id}} |
| end_user_number | TRUE | String | The end user phone number that will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{end_user_number}} |
| lang | FALSE | String | Language of the call. Uses ISO 639-1 codes. (Default: “en”) | {{lang}} |
| ticket_id | FALSE | String | CRM ticket ID. The end user phone number tied to the ticket will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{ticket_id}} |
| outbound_number | FALSE | String | The outbound phone number to be used for the call. The default global outbound phone number will be used if input is not passed in or invalid. Outbound numbers are managed from Settings > Queue > EDIT / VIEW > Select a queue > Outbound Phone Numbers. | {{outbound_number}} |
| recording_permission | FALSE | String | The value is only evaluated if the “Call Recording Options” feature is set to “Ask User for Permission to Record”. Configurable at Settings > Queue > EDIT / VIEW > Select a queue > Call Recording Options. If the value is either “recording_permission_not_asked” (default) or “recording_permission_denied”, the call will not be recorded. If the value is “recording_permission_granted”, the call will be recorded. | {{recording_permission}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| call_type | TRUE | String | Call type to create. Use “Voice Scheduled (API)” or “ScheduledCall” (deprecated) to create a scheduled call. | Voice Scheduled (API) |
| menu_id | TRUE | Integer | The ID of the menu to attribute the call to. Only Mobile and Web menu IDs are accepted. | {{menu_id}} |
| call_id | FALSE | Integer | Call ID of previous call, which will be linked as the parent call of the new created scheduled call. When call ID is being used, menu_id can be optional. | {{call_id}} |
| end_user_number | TRUE | String | The end user phone number that will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{end_user_number}} |
| lang | FALSE | String | Language of the call. Uses ISO 639-1 codes. (Default: “en”) | {{lang}} |
| ticket_id | FALSE | String | CRM ticket ID. The end user phone number tied to the ticket will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{ticket_id}} |
| scheduled_at | TRUE | String | Scheduled time of the call. Uses ISO 8601 format to a valid future time. | {{scheduled_at}} |
| recording_permission | FALSE | String | The value is only evaluated if the “Call Recording Options” feature is set to “Ask User for Permission to Record”. Configurable at Settings > Queue > EDIT / VIEW > Select a queue > Call Recording Options. If the value is either “recording_permission_not_asked” (default) or “recording_permission_denied”, the call will not be recorded. If the value is “recording_permission_granted”, the call will be recorded. | {{recording_permission}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| call_type | TRUE | String | Call type to create. Use “Voice Scheduled (API)” or “ScheduledCall” (deprecated) to create a scheduled call. | Voice Scheduled (API) |
| menu_id | TRUE | Integer | The ID of the menu to attribute the call to. Only Mobile and Web menu IDs are accepted. | {{menu_id}} |
| call_id | FALSE | Integer | Call ID of previous call, which will be linked as the parent call of the new created scheduled call. When call ID is being used, menu_id can be optional. | {{call_id}} |
| end_user_number | TRUE | String | The end user phone number that will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{end_user_number}} |
| lang | FALSE | String | Language of the call. Uses ISO 639-1 codes. (Default: “en”) | {{lang}} |
| ticket_id | FALSE | String | CRM ticket ID. The end user phone number tied to the ticket will be dialed. If both a ticket_id and end_user_number are passed in, the ticket_id will take precedence. | {{ticket_id}} |
| scheduled_at | TRUE | String | Scheduled time of the call. Uses ISO 8601 format to a valid future time. | {{scheduled_at}} |
| recording_permission | FALSE | String | The value is only evaluated if the “Call Recording Options” feature is set to “Ask User for Permission to Record”. Configurable at Settings > Queue > EDIT / VIEW > Select a queue > Call Recording Options. If the value is either “recording_permission_not_asked” (default) or “recording_permission_denied”, the call will not be recorded. If the value is “recording_permission_granted”, the call will be recorded. | {{recording_permission}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
Create a new scheduled callback. IVR menus skip the scheduled_call_enabled check since the setting is not yet available in IVR queue settings.
original_call_id is the canonical request-body field for the ID of the original call that triggered this scheduled callback. UJET stores this reference and makes it available to downstream virtual agent and CRM integrations as the original_call_id data parameter. call_id and parent_call_id are kept as deprecated legacy aliases for backwards compatibility — when multiple aliases are sent, resolution order is original_call_id -> call_id -> parent_call_id. Prefer original_call_id for new integrations.
Selected request fields
end_user_number (required, string) — E.164; the consumer number to call back.scheduled_at (required, string) — ISO 8601; must be in the future.menu_id (integer) — required unless one of original_call_id / call_id / parent_call_id is supplied.ani (string, optional) — E.164 caller line identity. Honored only when phone-number retention is enabled for the tenant; otherwise ignored. Duplicate detection also matches on ani. Supplying ani inside custom_parameters does NOT populate the ANI field.recording_permission — one of recording_permission_not_asked, recording_permission_granted, recording_permission_denied.user_authenticated — Y or N.The response includes a callback_data object echoing the callback metadata (including ani, ticket_id, and call_id).
Error responses
400 — invalid menu/language/call reference (menu_id is required, queue {id} does not exist, Only mobile, web, and IVR menu IDs are permitted, Language '{lang}' is not available).422 — request validation failed, or a booking conflict; body is { "message": "<text>" }. One of:end_user_number / dnis / ani, malformed scheduled_at, invalid enum, Queue ID does not exist)Scheduled time is before minimum wait time. Minimum scheduled time: {iso8601}Scheduled time is outside business hoursA scheduled callback already exists for this phone number (matched on end_user_number or ani)409 — slot at capacity — { "code": "slot_unavailable", "sub_code": "at_capacity", "message": "slot_at_capacity", "display_message": "The selected time slot is no longer available." }Note: the reschedule (PATCH) endpoint does not re-run the minimum-wait, hours-of-operation, or capacity checks.
Used to update the end_user associated with the current active call session. Additionally, it also updates the contact information linked to the CRM ticket. _Identifier is required, while name, email, and phone are optional. Note: If a phone number is already set, providing a phone parameter will not update the phone number.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| call_id |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
Adds a third party participant to an existing call. The agent must be connected to the call to initiate the third party dial.
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| agent_email | TRUE | String | Email address of the agent who is connected to the call and initiating the third party dial | {{agent_email}} |
| phone_number | TRUE | String | Phone number of the third party to dial. Can be formatted (e.g., +1 (226) 336-1437) or unformatted (e.g., 12263361437) |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | 123 | Call ID |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| chat_type | TRUE | String | Chat type to create. “Messaging (API)”, “SMS” (deprecated) are available for now | Messaging (API) |
| end_user_number | TRUE | String | Number the text message is to be sent to | {{end_user_number}} |
| outbound_number | TRUE | String | Outbound phone number to be used for sending the SMS message | {{outbound_number}} |
| message | TRUE | String | SMS message to be sent to consumer | {{message}} |
| ticket_id | FALSE | String | CRM ticket ID that will be associated with session | {{ticket_id}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| lang | TRUE | String | Language code of the queue. (e.g. ‘en’) | {{lang}} |
| menu_id | FALSE | Integer | Response will filter all menus in that menu’s subtree, including that menu. | {{menu_id}} |
| menu_type | FALSE | String | Returns menus of specific types. Possible values: ivr_menu, mobile_menu, web_menu). | {{menu_type}} |
| channel_type | FALSE | String | Returns menus of a specific channel. Possible values: voice_call, chat). | {{channel_type}} |
| wait[from] | FALSE | Integer | Returns records if they have a wait greater than the value. | {{wait[from]}} |
| wait[to] | FALSE | Integer | Returns records if they have a wait less than the value. | {{wait[to]}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| lang | TRUE | String | Language code of the queue. (e.g. ‘en’) | {{lang}} |
| menu_id | FALSE | Integer | Response will filter all menus in that menu’s subtree, including that menu. | {{menu_id}} |
| menu_type | FALSE | String | Returns menus of specific types. Possible values: ivr_menu, mobile_menu, web_menu). | {{menu_type}} |
| channel_type | FALSE | String | Returns menus of a specific channel. Possible values: voice_call, chat). | {{channel_type}} |
| wait[from] | FALSE | Integer | Returns records if they have a wait greater than the value. | {{wait[from]}} |
| wait[to] | FALSE | Integer | Returns records if they have a wait less than the value. | {{wait[to]}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
Create/Update a large number of users through the Bulk User Management collection.
Supports JSON files. Sample json data can be obtained through the Template API.
Only api_user authentication is supported. You must enter the api user token in the password variable. Lagacy authentication(using a company secret) is not supported.
When a JSON file is uploaded through the upload API, a job is created and validates the json file scheme.
The JSON file format is shown below and also can be checked through the GET Template API.
| Field(s) name | Values | Required | Validation |
|---|---|---|---|
| String(Email) | Yes | Must be a valid email. Must be unique within the file within Email column (no duplicates). so only 1 update per email address per file | |
| new_email | String(Email) | No | Must be a valid email. Must be unique within the file within New Email column (no duplicates). so only 1 update per email address per file |
| agent_number | String | No | A string with no validation |
| first_name | String | Yes | Non-empty string |
| last_name | String | Yes | Non-empty string |
| status | Active, Inactive, Empty | No | Must be “Active”, “Inactive”, or empty |
| location | A string that is a location name, Empty, Null | No | Must exactly match one of the existing locations (case-insensitive), or Null, or empty |
| max_chat_limit | 1 to X (where X is configured value), Empty | No | Must be 1 to X (inclusively), or empty |
| max_chat_limit_enabled | 0, 1, Empty | No | Must be 0, 1 or empty |
| roles | name: Role name / value: 0, 1, Empty | No | Must be 0, 1 or empty |
| teams | name: Team name / value: 0, 1, Empty | No | Must be 0, 1 or empty |
When the scheme check is successful, the Proceed API can be executed, and user creation/modification work is in progress.
Upload and Proceed are asynchronously performed by the worker, and you can check the status through the Job API with a job_id.
The status field of Job can be in any of the following states.
| Job status | Description |
|---|---|
| created | A job is created and waiting for validation. |
| valid_scheme | Scheme validation is successful and proceed is possible. |
| invalid_scheme | Scheme validation failed. Detailed information can be checked through the Scheme error log API. |
| in_progress | Performing bulk user update/create. |
| finished | Bulk user update/create complete. |
| Key | Value | Description |
|---|---|---|
| file |
| Key | Value | Description |
|---|---|---|
| id | {{job_id}} | |
| file |
| Key | Value | Description |
|---|---|---|
| id | {{job_id}} |
A campaign refers to an outbound auto-dialer feature that sequentially reaches out to a list of contacts, initiates outbound calls, and connects each contact to an available agent. Campaign endpoints provide access to campaign-related data, allowing retrieval of campaign and contact objects.
Currently, the campaign endpoints allow users to add, update, and delete contacts of an existing campaign. In future releases, the campaign endpoints will allow users to create, edit and delete campaigns.
[
{
"assigned_call_id": 32001,
"assigned_participant_id": 54321,
"campaign_id": 240,
"created_at": "2023-04-01T17:15:38.000Z",
"id": 16312,
"name": "string",
"outbound_number": null,
"priority": null,
"status": "Upcoming",
"unique_id": "string",
"updated_at": "2023-04-01T17:15:38.000Z"
},
{
"assigned_call_id": 32002,
"assigned_participant_id": 54330,
"campaign_id": 240,
"created_at": "2023-04-01T17:15:38.000Z",
"id": 16313,
"name": "string",
"outbound_number": null,
"priority": null,
"status": "Finished",
"unique_id": "string",
"updated_at": "2023-04-01T17:25:00.000Z"
}
]
The status field can be in any of the following states
| Campaign Contact Status | Description |
|---|---|
| Upcoming | Contact is next to be dialed. |
| Dialing | Contact is right now being dialed. |
| Queued | Call for a given contact is queued. |
| Connected | Contact is connected with an agent. |
| Finished | Call has completed. |
| Transferred | Call has been transferred. |
| Transferred and Finished | Call has been transferred and then completed. |
| Not Picked Up | No answer from end user or never reached the end user. |
| Not Reached to Contact | Call never reached the contact . |
| Abandoned by Contact | For preview, end user hangs up before connected to an agent. For both progessive and predictive, end user hangs up the call within 5 seconds after connecting to the agent. |
| Skipped | Contact has been skipped by agent and will be available to be connected to another agent. |
| Skipped & Closed | On Preview, agent skips and close a contact. This contact should now be always skipped in this campaign. |
| Invalid Number | Contact with invalid phone number. |
| Carrier Error | This error is driven by carrier. |
| Abandoned by Dialer | Contact has been abandoned by dialer. |
| Voicemail Hung Up | On Predictive, the dialer determines the end user is a machine (ie. voicemail). |
| Dialer General Error | Call failed due to dialer error. |
| Redial Scheduled | Temporary status. Redial scheduled in the future. |
| Do Not Call | The number was in Do-Not-Call number list. |
| Invalid Outbound Number | Contact with invalid outbound number. |
| Blocked Phone Number | Contact with invalid/blocked international number. |
| Key | Value | Description |
|---|---|---|
| file | some/path/to/multi_contacts.json |
Agent Status Endpoint
The Agent Status endpoint allows you to modify the status of agents. It enables changes to and from ‘Available’ to any custom status. Transitions to and from system-defined statuses like ‘In-Call’ will trigger an error. Additionally, this endpoint supports bulk updates, allowing status modifications for entire teams or selected groups of agents simultaneously.
Force Logout Agents Endpoint
The Force Logout Agents endpoint provides the functionality to forcibly log out online agents. Agents engaged in active calls or chats will be logged out automatically upon the completion of their current interactions, whereas idle agents are logged out immediately. This endpoint supports forced logouts of specific agents, entire teams, or agents identified by IP addresses with CIDR notation, a list of IPv4/IPv6 addresses, or IP ranges (see the request examples). For a large number of agents, a background job is created to manage the logout process efficiently.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id |
Creates or updates an end user based on a given identifier
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
Get End User external identifier and internal ID, given one of the fields
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | Internal ID for the End User |
| identifier | string | External identifier for the End User |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
Send a message in a chat.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
Escalate a chat from a Virtual Agent to a Human Agent.
id — escalation ID. Pass it to PATCH /chats/{chat_id}/escalations/{id} to record a deflection choice, or as chat.escalation_id when ending the chat.chat_id — ID of the chat the escalation belongs to.status — one of escalating, escalated, canceled, deflecting, deflected.deflection — the alternative UJET is offering because the queue is closed or over capacity. no_deflection when the escalation is proceeding to an agent; otherwise one of over_cap, over_cap_email, over_cap_virtual_agent, over_cap_human_agent, after_hours, after_hours_email, after_hours_virtual_agent.| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) Chat ID to escalate |
Records the end user’s deflection choice on an escalation. Used only for selecting a deflection channel currently. PUT is accepted as well as PATCH.
id — escalation ID.chat_id — ID of the chat the escalation belongs to.status — one of escalating, escalated, canceled, deflecting, deflected.deflection — the recorded outcome. no_deflection when no deflection applies; otherwise one of over_cap, over_cap_email, over_cap_virtual_agent, over_cap_human_agent, after_hours, after_hours_email, after_hours_virtual_agent.| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
| id | integer | (Required) |
Add a photo that has been uploaded to media storage to a chat
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
Retrieves media ID’s and storage url’s for all photos attached to the chat
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id |
Used for fetching a presigned upload URL
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
Add a video that has been uploaded to media storage to a chat
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
Retrieves media ID’s and storage url’s for all videos attached to the chat
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id |
Fetches a single media file (photo, video, audio, document) attached to the chat and returns the raw binary content. The response exposes the file name via the X-File-Name header.
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| media_id | {{media_id}} | (Required) |
| media_type | {{media_type}} | (Required) photo / video / audio / document |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
Used for fetching a presigned upload URL for the company’s configured cloud storage service
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id | integer | (Required) |
Start a new chat.
| Parameter | Required | Data Type | Definition |
|---|---|---|---|
| chat.client_reference | FALSE | Object | Opaque correlation reference. Requires the chat-api-client-reference-id feature flag. Echoed on this response and at the top level of every chat webhook envelope. Omitted (not null) when not supplied. |
| chat.client_reference.id | Required if client_reference present | String | Consumer-supplied correlation key. Max 255 chars. Stored verbatim; non-unique across chats. |
| chat.client_reference.metadata | FALSE | Object | Flat string key/value map echoed with id. Values must be strings (nested objects rejected). Serialized size at most 8192 bytes. |
Chat DAP and orchestration (optional)
Everything above is unchanged. This section applies only to tenants that have Chat DAP (API Request Direct Access Point for Chat) configured; for everyone else the endpoint behaves exactly as described above and the chat is created in menu_id.
When Chat DAP is configured, this endpoint resolves the DAP before the chat is created: the platform calls your DAP endpoint (API Response mode), matches the returned key-value pairs against the queue Access Points and, on a match, creates the chat directly in the matched queue instead of menu_id. Orchestration actions returned in events (send_response, assign_to_queue, end_chat) are applied to the created chat exactly as for web and mobile chats. When nothing matches, or the DAP request fails or times out, the chat is created in menu_id as usual.
Prerequisites — without all three the section does not apply:
See the Support Center article API Request Direct Access Point for Chats for the configuration steps and the DAP request/response contract.
Additional optional fields on the chat object — all are forwarded to your DAP endpoint and have no effect when Chat DAP is not configured:
| Parameter | Required | Data Type | Definition |
|---|---|---|---|
| chat.direct_access_key | FALSE | String | General Access Point label evaluated by the DAP routing logic’s General Access Point Label step. |
| chat.initial_message | FALSE | String | Consumer’s opening message, forwarded as initial_message. Ignored (not forwarded) when longer than 2000 characters. |
| chat.custom_data_signed | FALSE | String | Signed custom data (JWT), forwarded as custom_data_signed. Ignored (not forwarded) when larger than 16 KB. |
| chat.custom_data_unsigned | FALSE | Object | Unsigned custom data, forwarded as custom_data_unsigned. Ignored (not forwarded) when larger than 8 KB serialized or nested deeper than 5 levels. |
Reading the result. The routed queue is the last entry of menus in the response. send_response and end_chat are applied right after the chat is created; observe them through the chat webhooks (message_received with sender: "system", chat_ended) or GET /chats/:id.
Existing chat in queue. If the end user already has a chat waiting in a queue (created within the last 24 hours), that chat is returned instead of a new one — this is the Resumed chats case of the Chat Types setting. The DAP request is still made and recorded when Resumed chats are enabled, but its result does not move the existing chat.
Scope. Webhook Response mode applies to the web and mobile SDK channels; chats created through this endpoint use API Response mode. When the tenant is configured for Webhook Response, this endpoint skips the DAP and creates the chat in menu_id.
Latency. With Chat DAP active the request includes one round trip to your DAP endpoint, bounded by the tenant’s API Request Timeout (1–10 s). Set your HTTP client timeout above that value so a slow DAP response is not retried as a failed request.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
If a chat has been dismissed for inactivity, an end user may resume the same chat. Chat status must be “dismissed” or “va_dismissed”
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
| Key | Value | Description |
|---|---|---|
| id | integer | (Required) |
Send custom data in a chat
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | (Required) |
Used to update the end_user associated with the current active chat session. Additionally, it also updates the contact information linked to the CRM ticket. _Identifier is required, while name, email, and phone are optional. Note: If a phone number is already set, providing a phone parameter will not update the phone number.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| chat_id |
| Key | Value | Description |
|---|---|---|
| chat_id |
Returns CSAT eligibility for a finished chat along with localized survey messages.
Call this after PATCH /apps/api/v1/chats/:chat_id/end. When eligible is true, present the survey using the strings in messages, then submit via PATCH /apps/api/v1/chats/:chat_id/rating.
Eligibility gates (evaluated in order):
1. chat-api-csat feature flag is ON (else 404)
2. Operation Management CSAT is enabled
3. Chat is finished
4. Chat has not already been rated
5. Queue-level chat_api_csat resolves to true (Global > Parent > Queue inheritance)
Optional per-request message overrides:
Callers may supply an optional messages map to override any of the five admin-configured survey strings on a per-request basis. Each override key is independent — omitted keys fall back to the admin-configured Audible value. Unknown keys are silently dropped (forward-compat); empty or whitespace-only values fall back to the admin value rather than blanking the field.
Wire format is deepObject query parameters, e.g. ?messages[form_title]=Rate%20your%20chat&messages[result_subtitle]=Thanks!.
Override validation rules:
- Recognized keys: form_title, form_feedback, result_title, result_subtitle, feedback_label
- Each value: must be a string, max 300 raw characters
- Forbidden characters: Unicode control characters (category Cc) except TAB, LF, CR. Zero-width chars, BIDI controls, joiners, BOM, and emoji ZWJ sequences are accepted.
- Override values are HTML-escaped server-side before being returned in messages. Admin-resolved (non-override) values pass through raw.
- Validation failures return 400 with validation_errors[] listing each offending field and a wire-format code (invalid_type, too_long, invalid_characters). Partner integrations may parse the code values directly.
Override of a null admin value flips a previously-ineligible chat to eligible — but a per-field override cannot rescue an entirely absent admin config (the 5-field completeness check still ineligibles out if messages cannot be fully resolved).
Response keys:
- eligible (boolean): whether to show the CSAT survey
- messages (object|null): localized strings keyed by form_title, form_feedback, result_title, result_subtitle, feedback_label. null when ineligible. form_feedback and feedback_label are omitted when feedback_enabled is false.
- feedback_enabled (boolean): client-side presentation hint sourced from Operation Management csat_settings.feedback_enabled. Not enforced server-side.
| Key | Value | Description |
|---|---|---|
| chat_id |
Returns the current CSAT rating for a chat.
Response body:
- rating (number|null): float between 0 and 5 (e.g. 4.0, 3.7), or null until the consumer submits one via PATCH /apps/api/v1/chats/:chat_id/rating.
Returns 404 when the chat-api-csat feature flag is OFF or the chat is not found.
| Key | Value | Description |
|---|---|---|
| chat_id |
Submits a CSAT rating for a finished chat.
Request body:
- rating (number, required): 0 to 5. Float values are accepted (e.g. 3.7).
- feedback (string, optional): free-text feedback. Stored regardless of feedback_enabled; the toggle only controls whether the survey UI prompts for it.
Server re-runs the same eligibility checks as GET /apps/api/v1/chats/:chat_id/csat. A stale or hostile client cannot submit a rating to a chat the eligibility endpoint would refuse.
Errors:
- 400 — rating is missing or not a number
- 404 — feature flag OFF or chat not found
- 422 — eligibility check failed; rating out of range; chat became unfinished or was rated between eligibility check and submit; or rating not permitted by company CSAT settings / time window
On success the chat’s chat_csat_submitted event is created and the rating is forwarded to CRM and reporting.
| Key | Value | Description |
|---|---|---|
| chat_id |
Customer-side ingress for Chat DAP (Direct Access Point) Webhook Response routing mode.
Scope. This callback serves the web and mobile SDK flow. Chats created through POST /apps/api/v1/chats use API Response mode and never involve this endpoint.
Flow
1. The end-user SDK calls GET /v2/menus and the platform places the chat on hold.
2. The platform sends your configured DAP endpoint the DAP request payload with two extra fields: chat_dap_id (the hold id) and webhook_url (the absolute URL of this endpoint for your tenant). Your endpoint must answer with a 2xx acknowledgment within the API Request Timeout.
3. Your system does its own lookup (CRM, segmentation, business rules) and POSTs the result to webhook_url within the API Callback Timeout.
4. The platform resolves the hold against the tenant’s DAP routing logic order (api_response → general_access_point_label → user_segmentation) and the SDK’s polling on GET /v2/menus?dap_request_id=… unblocks. chat_dap_id on this callback and dap_request_id on the SDK path are the same value.
Available when Chat DAP is enabled for your tenant — contact Support.
HTTP Basic, same as the rest of Apps API.
- Username: company subdomain ({{username}})
- Password: API token from Settings → Developer Settings → API Credentials ({{password}})
| Header | Required | Notes |
|---|---|---|
Authorization | yes | Set automatically by Postman from the Basic auth above. |
Content-Type: application/json | yes | Body must be JSON. |
Accept: application/json | no | Recommended. |
UJET-SUBDOMAIN | no | Tenant identifier. Normally inferred from the host; only needed when calling through a host that does not carry the tenant subdomain. Disabled by default. |
| Field | Type | Required | Notes |
|---|---|---|---|
chat_dap_id | string | yes | The hold id received in the outbound DAP request. Max 255 chars. |
key_value_pairs | object | one of key_value_pairs / events | Routing payload matched against the queue Access Points of type API Response (dotted paths are supported, e.g. user.tier). |
events | array | one of key_value_pairs / events | Orchestration actions — see Orchestration actions below. |
error | string | null | no | Optional customer-side error message recorded on the inbound audit row. Max 1024 chars; non-string values are ignored. |
The serialized body must not exceed 65,535 bytes.
Minimal example (routing only):
{
"chat_dap_id": "a3f8e2c5d9b6f4e2a1c8b3a5d7f9e2b4",
"key_value_pairs": {
"region": "us-east"
}
}
events)events is an ordered array of actions. The same array is accepted at the root of an API Response mode response (next to the key-value pairs) and here, as a sibling of key_value_pairs.
{
"chat_dap_id": "a3f8e2c5d9b6f4e2a1c8b3a5d7f9e2b4",
"events": [
{ "type": "send_response", "message": "Thanks for reaching out — one moment." },
{ "type": "assign_to_queue", "key_value_pairs": { "team": "billing" }, "human_agent": true, "skills": ["billing", "en"], "skills_operator": "AND" },
{ "type": "end_chat" }
]
}
type | Required | Optional | Behavior |
|---|---|---|---|
assign_to_queue | key_value_pairs (object) | human_agent (bool), virtual_agent (bool), skills (array of up to 100 strings), skills_operator (AND | OR) | Routes to the queue whose API Response Access Point matches key_value_pairs. human_agent bypasses the queue’s virtual agent; virtual_agent sends the chat to the virtual agent even when human agents are available; the two are mutually exclusive. skills narrow the agent choice inside the queue when the Access Point’s Prioritize skills if available is enabled. |
send_response | message (string, max 2000 chars) | — | Delivers the message to the consumer as a system message. |
end_chat | — | — | Ends the chat before it is offered to any agent or virtual agent. Always executes last when combined with other actions. |
Rules:
- When the root key-value pairs match an Access Point, that routing wins and events are not applied. Key-value pairs that match nothing do not suppress events.
- An events array that fails validation (unknown type, both agent flags true, oversized skills or message, non-array value) is ignored as a whole and standard routing applies. The chat is never left in a stuck state.
The success body is intentionally minimal — the webhook caller only needs an ACK:
{
"ack": "ok"
}
Hold-resolution detail (direct_access_key_id, matched step) is not returned to the customer. It is surfaced to the end-user SDK via its polling on GET /v2/menus?dap_request_id=… and recorded server-side on the inbound audit row and in structured logs for operations visibility.
| Code | When |
|---|---|
400 | chat_dap_id missing, empty or over 255 chars; neither key_value_pairs nor events present; serialized body over 65,535 bytes. |
401 | Basic auth credentials missing or invalid. |
404 | Chat DAP is not enabled for this tenant. |
422 | No callback target for chat_dap_id: unknown id, or the hold was already resolved by an earlier callback, timed out, or the outbound request had failed. |
A callback rejected with 400 leaves the hold untouched, so a corrected retry inside the API Callback Timeout is still accepted (the last valid callback within the window wins). A retry after a callback was already accepted returns 200 again. A retry after the hold closed (timeout or request failure) returns 422.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | Required. Body must be JSON. |
| Accept | application/json | Recommended. |
The Company DNC (Do Not Call) list will allow blocking direct, manual, outbound calls as well as outbound and scheduled calls created by the Apps API depending on configuration.
Currently, the Company DNC endpoints allow users to:
add multiple phone numbers to the DNC list
remove phone numbers from the DNC list
check whether a phone number is in the DNC list
| Key | Value | Description |
|---|---|---|
| phone_number | {{$randomPhoneNumber}} |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
Queue Status Endpoint: Provides the status of a specific queue, allowing you to check the queue’s status before deflection.
Returns comprehensive, real-time status for one or more leaf queues, including the callback time slots a virtual agent can offer for scheduling a callback.
Query parameters
menu_id[] (required) — 1–10 leaf menu IDs, e.g. menu_id[]=1&menu_id[]=2.lang (required) — ISO 639-1 language code enabled for the company.menu_type (required) — one of ivr_menu, mobile_menu, web_menu.callback_period_hours (optional, integer 1–24) — length of the future window for which callback slots are returned.callback_start_from (optional, ISO 8601) — start of the callback search window; must be in the future.Response
Each queue object includes callback_periods[] and a scheduling_config object.
callback_periods[]: date (yyyyMMdd), start_time / end_time (HH:mm, queue timezone), scheduled_calls (booked count), max_slots, and available_slots (max_slots - scheduled_calls, floored at 0). When capacity is unlimited, callback_periods is [] and max_slots / available_slots are null.scheduling_config: scheduled_callback_enabled, availability_interval (minutes; null = unlimited), availability_days, capacity_type (calculated | static | unlimited), calculated_capacity_percentage, enforce_minimum_wait_time_ewt, minimum_wait_time_minutes.Errors: 400 invalid/missing params; 404 menu not found / not a leaf.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| lang | {{lang}} | (ISO 639-1 string, required) The language code for the queue, e.g., |
| menu_id[] | {{menu_id}} | (string, required) A single Queue ID or an array of multiple Queue IDs. |
| menu_type | {{menu_type}} | (string, required) One of |
| callback_period_hours | (integer, optional, 1–24) Total future window length in hours for which to return callback-slot periods. | |
| callback_start_from | (ISO 8601 datetime string in queue/company timezone, optional) Start of the callback-slot search window. If omitted, defaults to “now” (server time converted to queue/company timezone). Must not be in the past. |
Fetches availability information for a specific queue.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| menu_id | {{menu_id}} | (integer, required) The ID of the menu to fetch availability for. |
| lang | {{lang}} | (string, required) The language code (e.g., ‘en’) |
| channel_type | {{channel_type}} | (string, required) The channel type, either call or chat. |
The API user is able to:
manage Contact lists via API
create a Custom Contact List
edit a Custom Contact List
delete a Custom Contact List
manage custom and global Contact List entries
add entries
edit entries
delete entries
A contact list entry can route to a queue. Set type to queue and send the queue settings in the nested queue_destination_attributes object.
| Field | Type | Notes |
|---|---|---|
menu_id | integer | Required when first creating the queue destination. The queue this contact routes to. Must be a queue in your tenant. |
lang | string | Required when first creating the queue destination. Language code, for example en. Must be a language the target queue is configured for. |
greeting_message | string | Text greeting played before the queue is joined. Up to 450 characters. Must not contain control characters or markup. |
use_voice_file | boolean | Defaults to false. When true, an audio greeting must already be stored or be uploaded in the same request. |
voice_file | file | Audio greeting, mp3 or wav, up to 15 MB. Can only be sent with multipart/form-data. |
remove_voice_file | boolean | Send true to delete the stored audio greeting. |
bypass_queue_permissions | boolean | Defaults to false. Lets agents transfer to this queue even when they do not hold the usual permission for it. |
When creating or updating, type accepts sip_uri, phone_number, and queue. Agent contacts are managed by UJET and are not supported on this endpoint; existing ones are returned with type: agent.
Send the request as multipart/form-data and bracket the nested keys, for example queue_destination_attributes[menu_id] and queue_destination_attributes[voice_file]. application/json stays valid for every request that does not carry a file.
Queue contacts are returned with menu_id, lang, greeting_message, use_voice_file, voice_file_url, and bypass_queue_permissions.
Those six keys are absent from the response for every other contact type — they are not returned as null, so test for the key rather than for a null value. The older type-specific fields (sip_uri, phone_number, extension_number, extension_digits_length, user_id) behave the other way round: they are always present and carry null when they do not apply. use_refer is always present and defaults to false; sip_params is always present and is an object, with every option off when no SIP parameters were configured.
Treat a missing key and a null value as the same thing (“not set”).
A queue contact that fails validation is rejected with 400, for example: type: queue without queue_destination_attributes; queue_destination_attributes on a contact whose type is not queue; a duplicate queue contact (same name, queue and language already in the list); an unknown menu_id; a lang the queue is not configured for; a greeting_message over 450 characters; or a voice_file that is not mp3/wav or is over 15 MB.
If queue destinations are not enabled for your tenant, creating or updating a contact with type: queue (or with queue_destination_attributes) is rejected with 422:
{
"errors": [
{
"reason": "feature_disabled",
"message": "Queue contacts are not enabled for this tenant."
}
]
}
Updating a contact that already is a queue contact is rejected the same way. Deleting one is always allowed. Match on reason; the message wording can change.
| Key | Value | Description |
|---|---|---|
| id | integer | The ID of updating contact list |
| Key | Value | Description |
|---|---|---|
| id | integer | The ID of deleting contact list |
| Key | Value | Description |
|---|---|---|
| contact_list_id | integer | The ID of selected contact list |
| Key | Value | Description |
|---|---|---|
| contact_list_id | integer | The ID of contact list |
| id | integer | The ID of updating contact record |
| Key | Value | Description |
|---|---|---|
| contact_list_id | integer | The ID of contact list |
| id | integer | The ID of deleting contact record |
| Key | Value | Description |
|---|---|---|
| menu_id | Interger | (Required) The ID of the menu to fetch availability for |
| lang | string | (Required) The language code (e.g., “en”) |
| channel_type | string | (Required) The channel type, either call or chat |
Users Endpoints provide a means to get user objects. Each user object represents a single user inside of our platform. Please review the model below to see which fields may be considered PII.
Default page size is 100 if no page parameters are sent.
{
"id": 1,
"email": "string", //This may be considered PII
"first_name": "string", //This may be considered PII
"last_name": "string", //This may be considered PII
"agent_number": "string",
"location": "string",
"max_chat_limit": 5,
"max_chat_limit_enabled": false,
"unrestricted_international_calling": true,
"deactivated_at": "2018-05-30T20:46:31.333Z",
"ucaas_user_name": "string",
"ucaas_sip_uri": "string",
"external_user": false,
"phone_numbers": ["string"],
"extension_numbers": [
0
],
"teams": [
{
"name": "string"
}
],
"roles": [
{
"name": "string"
}
]
}
| Response Code | Meaning |
|---|---|
| 200 | The API request has been successful |
| 400 | Invalid page size request - check to ensure the max page size is a valid integer less than 1000 |
| 400 | Cannot paginate filtered results - ensure that you are not using a filter and pagination parameters |
| 400 | Only one filter should be configured at a time |
| 400 | Ensure you are not filtering more than 1000 values at a time |
| Parameter | Required | Data Type | Definition | Postman Variable |
|---|---|---|---|---|
| page | FALSE | String | Pairs with per to note what page of records. For instance if per is made to be 200 and page is 2, the response would contain record 201-400, as page 1 would contain 1-200. | {{page}} |
| per | FALSE | String | Pairs with page to note how many records would be included in a page of records. For instance if per is made to be 200 and page is 2, the response would contain record 201-400, as page 1 would contain 1-200. | {{per}} |
| id[] | FALSE | Array[String] | Array[Strings]. Id of records to search and return | {{id[]}} |
| agent_number[] | FALSE | Array[String] | Agent numbers as assigned by the admin at the time of creating an agent | {{agent_number[]}} |
| status_id[] | FALSE | Array[String] | Filters by agent status | {{status_id[]}} |
| online[] | FALSE | Boolean | Filter by if agents are online or not | {{online[]}} |
| wrap_up[] | FALSE | Boolean | Filter by if agents are in wrap up status | {{wrap_up[]}} |
| location[] | FALSE | Array[String] | Filters by agent location | {{location[]}} |
| last_login_time[from] | FALSE | Time in UTC | creates a lower bound of the last login time field. All records returned will be after the inputted value. | {{last_login_time[from]}} |
| last_login_time[to] | FALSE | Time in UTC | creates a upper bound of the last login time field. All records returned will be before the inputted value. | {{last_login_time[to]}} |
| status_updated_at[from] | FALSE | Time in UTC | creates a lower bound of the status updated at field. All records returned will be after the inputted value. | {{status_updated_at[from]}} |
| status_updated_at[to] | FALSE | Time in UTC | creates a upper bound of the status updated at field. All records returned will be before the inputted value. | {{status_updated_at[to]}} |
Send a custom data in a call.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | (Required) |
Get Call List.
Introduced in version 3.39.
Get a Call
Introduced in version 3.39.
| Key | Value | Description |
|---|---|---|
| call_id | integer | call_id to search |
Cancel a Scheduled Call
Introduced in version 3.39.
| Key | Value | Description |
|---|---|---|
| call_id | integer | call_id to cancel |
Cancel Multi Scheduled Call
Introduced in version 3.39.
Update an existing scheduled callback. Allows modifying the scheduled time, end user number, recording permission, and other IVR-specific parameters. Requires the Scheduled Callback API to be enabled for your account.
ani (optional, E.164) is only validated and stored when phone-number retention is enabled for your account; otherwise it is ignored. The reschedule endpoint does not re-run the minimum-wait, hours-of-operation, or capacity checks that apply on create.
| Key | Value | Description |
|---|---|---|
| call_id | 8788 | Scheduled call ID to update |
Retrieve details of an existing scheduled callback by ID. Requires the Scheduled Callback API to be enabled for your account.
| Key | Value | Description |
|---|---|---|
| call_id | 8788 | Scheduled call ID |
List scheduled callbacks with optional filters. Requires the Scheduled Callback API to be enabled for your account.
| Key | Value | Description |
|---|---|---|
| end_user_number | string | End user phone number to filter scheduled calls |
| call_id | 8788 | Filter by parent call ID |
| id | 8788 | Filter by call ID |
| scheduled_from | 1977-03-22T23:59:59.670Z | Filter scheduled calls from this time (ISO8601 timestamp, inclusive) |
| scheduled_to | 1977-03-22T23:59:59.670Z | Filter scheduled calls up to this time (ISO8601 timestamp, inclusive). Time window between scheduled_from and scheduled_to must be at least 1 minute and at most 24 hours. |
| menu_id | 8788 | Filter by menu ID |
| lang | string | Filter by language code (e.g., en, es, fr) |
| ticket_id | string | Filter by ticket ID |
| page | 8788 | Page number for pagination (default: 1) |
| per_page | 8788 | Number of results per page (default: 100) |
| status | failed | Filter by callback status. Values: scheduled, completed, attempted (callback has remaining retries), failed (system attempted maximum number of retries), cancelled |
Get a Job state of Cancel Multi Scheduled Call
Introduced in version 3.39.
| Key | Value | Description |
|---|---|---|
| job_id | integer | job_id to search |
Retrieves the real-time status of a specific call in a queue, including its position and estimated wait time.
Introduced in version 3.42.
| field | description |
|---|---|
| position_in_queue | The current position of the call in the queue. The call at the front of the queue has a value of 1 (1-based). |
| ewt | The estimated wait time in seconds until the call is expected to be picked up from its current queue. |
| wait_duration_in_queue | The total time in seconds the call has been waiting in the queue since it was added. |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| call_id | The ID of the call used to get its current state in the queue. |
Retrieves the real-time status of a specific call in a queue, including its position and estimated wait time.
Introduced in version 3.42.
| field | description |
|---|---|
| position_in_queue | The current position of the call in the queue. The call at the front of the queue has a value of 1 (1-based). |
| ewt | The estimated wait time in seconds until the call is expected to be picked up from its current queue. |
| wait_duration_in_queue | The total time in seconds the call has been waiting in the queue since it was added. |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| call_id | :id |
Enable or disable emergency shutdown on one or more queues. This API allows external systems to remotely control queue availability during emergency situations.
| Parameter | Required | Data Type | Definition |
|---|---|---|---|
| menu_id | TRUE | Array | Array of Queue IDs to update |
| language | TRUE | String | ISO 639-1 language code (e.g., “en”, “es”) |
| emergency_shutdown.enabled | TRUE | Boolean | Enable (true) or disable (false) emergency shutdown |
| emergency_shutdown.message.type | FALSE | String | Message type: “tts” (text-to-speech) or “audio” (audio URL) |
| emergency_shutdown.message.content | FALSE | String | TTS text or audio file URL. Required if message.type is provided |
| emergency_shutdown.in_progress_calls | FALSE | String | How to handle in-progress calls: “allow_finish”, “end_and_redirect_to_after_hours”, “end_and_redirect_to_overcapacity” |
| emergency_shutdown.queued_calls | FALSE | String | How to handle queued calls: “disconnect”, “redirect_to_after_hours”, “redirect_to_overcapacity” |
Notes:
- If no message is provided when enabling, the global default emergency shutdown message will be used.
- The in_progress_calls and queued_calls parameters are optional; if not provided, global settings are inherited.
- The API requires the Emergency Shutdown feature to be enabled and Remote Shutdown API access to be enabled for the company.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
Returns the full forest of all active root-level disposition lists for the tenant and their descendants. Callers can identify roots by parent_path == "/" (or level == 1); root_list is null because no single list is selected.
Feature flag: Gated behind update-previous-acw. Returns 404 when the flag is off.
| Parameter | Required | Data Type | Definition |
|---|---|---|---|
| channel | FALSE | String | “voice_call” or “chat”. Default: “voice_call” |
| call_direction | FALSE | String | “inbound” or “outbound”. Default: “inbound”. Ignored for chat |
| lang | FALSE | String | ISO 639-1 language code. Default: “en” |
| page | FALSE | Integer | Pagination page (default 1) |
| per_page | FALSE | Integer | Items per page (default 100, max 100) |
Notes:
- The name field returned per code/list is the stored admin-authored string. lang selects the per-language assignment but does NOT translate names.
- Pagination is exposed via standard headers (Total, Per-Page, Link).
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| channel | voice_call | Channel for the tree. One of “voice_call” or “chat”. Defaults to “voice_call”. |
| call_direction | inbound | Call direction for voice_call. One of “inbound” or “outbound”. Defaults to “inbound”. Ignored when channel is “chat” but must still be a valid value if provided. |
| lang | en | Language code used to select the language-specific queue assignment. Defaults to “en”. Does NOT translate the returned code or list names — values are the admin-authored strings regardless of lang. |
| page | 1 | Page number for the disposition_codes array (default 1). |
| per_page | 100 | Items per page (default 100, max 100). Pagination metadata is returned via RFC-5988 response headers (Total, Per-Page, Link). |
Returns the disposition tree for a specific queue (menu). Resolves the most-specific enabled Menu::CodeMenuAssignment up the menu hierarchy and falls back to the tenant’s channel-scoped global list (voice-inbound / voice-outbound / chat) when no assignment is found.
Feature flag: Gated behind update-previous-acw. Returns 404 when the flag is off OR when the menu doesn’t exist.
| Parameter | In | Required | Data Type | Definition |
|---|---|---|---|---|
| menu_id | path | TRUE | Integer | Queue (menu) ID |
| channel | query | FALSE | String | “voice_call” or “chat”. Default “voice_call” |
| call_direction | query | FALSE | String | “inbound” or “outbound”. Default “inbound”. Ignored for chat |
| lang | query | FALSE | String | ISO 639-1. Default “en” |
| page | query | FALSE | Integer | Pagination page (default 1) |
| per_page | query | FALSE | Integer | Items per page (default 100, max 100) |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| channel | voice_call | “voice_call” or “chat”. Default: “voice_call”. |
| call_direction | inbound | “inbound” or “outbound”. Default: “inbound”. Ignored for chat. |
| lang | en | ISO 639-1. Default: “en”. Selects the per-language queue assignment; does NOT translate names. |
| page | 1 | |
| per_page | 100 |
| Key | Value | Description |
|---|---|---|
| menu_id | 123 | Queue (menu) ID |
Returns the disposition tree that applies to a specific session, resolved from the session’s comm via the same logic the agent UI uses. The response channel, call_direction, and lang are derived from the resolved comm; query-param overrides for those fields are NOT honored on this endpoint.
Feature flag: Gated behind update-previous-acw. Returns 404 when the flag is off, when the session doesn’t exist, or when the session has no resolvable comm.
| Parameter | In | Required | Data Type | Definition |
|---|---|---|---|---|
| session_id | path | TRUE | Integer | Session ID |
| comm_type | query | FALSE* | String | “call” or “chat”. *Required when the session has both a call and a chat. |
| page | query | FALSE | Integer | Pagination page (default 1) |
| per_page | query | FALSE | Integer | Items per page (default 100, max 100) |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| comm_type | call | “call” or “chat”. Required when the session is omnichannel (has both a call and a chat); otherwise auto-resolves. |
| page | 1 | |
| per_page | 100 |
| Key | Value | Description |
|---|---|---|
| session_id | 9876 | Session ID |
Updates the disposition code and/or notes of a previously completed session. At least one of disposition_code or notes must be present in the request body.
Writes: - CRM: a new note record is attached on every call (additive, never an overwrite of prior notes). - External Storage: the existing session-metadata file is overwritten with the latest disposition state.
Feature flag: Gated behind update-previous-acw. Returns 404 when the flag is off.
| Field | In | Required | Data Type | Definition |
|---|---|---|---|---|
| session_id | path | TRUE | Integer | Session ID |
| comm_type | query | FALSE* | String | “call” or “chat”. *Required when the session is omnichannel. |
| disposition_code.id | body | conditional | Integer | Disposition code id from the read API. Use -1 for the synthetic Do-Not-Call sentinel (only valid when the tenant has DNC + DNC-disposition enabled). |
| disposition_code.full_path | body | conditional | String | parent_path of the membership (e.g. “/100/200”). Required when disposition_code is provided. |
| notes | body | conditional | String | Note text. Empty string is treated as an explicit clear; an omitted field leaves the prior note unchanged. |
Notes:
- Either disposition_code or notes must be present (or both).
- The resolved code’s canonical name is returned in the response; callers do NOT need to send a name field.
- The id == -1 sentinel triggers DNC list processing in addition to persisting the disposition row.
- Returns 422 if the resolved comm is still active (the CRM/storage writes only run after the comm has ended).
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| comm_type | call | “call” or “chat”. Required when the session is omnichannel (has both a call and a chat); otherwise auto-resolves. |
| Key | Value | Description |
|---|---|---|
| session_id | 9876 | Session ID |
Read-only Apps API for retrieving parsed email data. Two endpoints:
GET /apps/api/v1/email/sessions/:email_support_id — session metadata + its email_threads list.GET /apps/api/v1/email/messages/:email_thread_id — a single parsed message + email_attachments metadata.HTTP Basic auth.
Returns metadata for a single email support session plus its (non-draft) threads, ordered by received_at ascending.
Authentication: HTTP Basic — username = Apps API user name, password = API token.
| Name | Type | Required | Description |
|---|---|---|---|
email_support_id | integer | Yes | Numeric email session id. |
hidden and hidden_at are always present. A visible session renders hidden: false, hidden_at: null, so a consumer never has to branch on absence. hidden_at is one field over two internal mechanisms (an API hide and an orchestration delete); which one hid the row is not part of this contract.
The session’s orchestration run: your external workflow was asked what to do with the email — reply, close, delete, or move it to another queue — and UJET carried out the answer or fell back to regular routing.
The key is absent — not null — when the session has no orchestration run, or when orchestration reporting is not enabled for your tenant; read it with a presence check rather than a null check. Only runs made while reporting is enabled are reported, and turning reporting off hides runs already reported, so an absent key does not by itself mean that your workflow did not handle the email. When it is present, every field below is present, and a field with no value is null. A field the table does not describe as always having a value can be null.
status, exit_at and duration_ms are null until UJET records the run’s end, which may never happen. A run that ended completed and whose move to another queue is then refused or fails renders as status: failed, with fallback.applied: true and fallback.reason: delivery_failed — so a run’s status can differ on a later read.routing.forwarded_from_email_support_id names the source session, and the routing.original_* fields are the source session’s.custom_params, routing.match_params and flow_id become null 7 days after they were recorded — a fixed period, not your email storage period — and also after the end user’s data has been removed.| Field | Type | Notes |
|---|---|---|
status | string | One of completed, timed_out, failed, invalid_response, fallback_default. How the run ended; null until UJET records the run’s end, which may never happen. completed — UJET carried out the run, though a step can settle without effect; see outcome.applied_types. Every other value means regular routing took over: timed_out — the workflow did not answer in time; invalid_response — its answer could not be used; failed — calling the workflow, processing its answer or carrying it out failed, which can include a move to another queue that was refused or failed; fallback_default — UJET applied regular routing by default, for example because the answer planned nothing. fallback.reason says why. A run that moves the session to another queue can report a different status on a later read. |
entry_at | string (date-time) | When the run started (UTC). |
response_received_at | string (date-time) | When UJET received the workflow’s answer (UTC) — its API response, or its callback in webhook_response mode; null when UJET has recorded no answer — for example while it is still waiting for one, or after an HTTP error or a timeout. |
exit_at | string (date-time) | When the run ended (UTC); null until UJET records the run’s end, which may never happen. |
duration_ms | integer | Milliseconds from entry_at to exit_at; null until UJET records the run’s end, which may never happen. In webhook_response mode it includes the wait for your callback. |
provider | string | The kind of workflow integration. Currently always google_workflows; it does not identify the endpoint that answered. |
flow_id | string | The execution_id your workflow returned at the root of its answer, kept only when it is an identifier: 1 to 1,024 characters, each an ASCII letter, a digit or one of ., _, :, /, -. null when the answer carried none or one of any other shape, or UJET could not use or process the answer, and 7 days after it was recorded or after the end user’s data has been removed. |
mode | string | How your workflow is configured to answer: api_response — in its API response; webhook_response — later, through the Email DAP Webhook Callback. |
outcome.types | array of string | Each one of send_email_response, end_email, transfer_to_queue, delete_email, no_action. The steps UJET planned from the workflow’s answer, in execution order — replies first. Events in your answer map to steps as follows: send_response → send_email_response; end_email → end_email, plus delete_email when it carries delete: true; assign_to_queue → transfer_to_queue, which a move made by top-level key-value routing also plans. This can differ from what the answer asked for: for example, a close supersedes a move to another queue. ["no_action"] when nothing was planned, including when the answer could not be used (status: invalid_response). null when UJET has recorded no plan — for example before the workflow answers, or when the run ended before an answer could be read, such as after an HTTP error, a timeout or refused authentication. |
outcome.applied_types | array of string | The planned steps that took effect, in the same order and vocabulary: ["no_action"] when nothing was planned (including when the answer could not be used), [] when none took effect, null when UJET has recorded no plan. transfer_to_queue means the move to the destination queue was handed off, not that it arrived, and may be removed later, for example when that move failed or went to another queue. |
outcome.destination_queue_id | integer | The queue the workflow’s answer routed the session to; null when it routed to none. Kept when the move later failed. |
outcome.destination_queue_lang | string | The language of that queue. |
outcome.destination_queue_name | string | The name of that queue in that language, as it is when you read it; null when there is no destination queue or it no longer exists. |
routing.original_email_account_id | integer | The inbound email account the run’s session arrived on (the source session’s, on a move’s destination). |
routing.original_queue_id | integer | The queue the run’s session was in when the run started (the source session’s, on a move’s destination). |
routing.match_result | string | One of matched, no_match, not_applicable. Whether the workflow’s answer matched a configured queue routing rule: matched when it did; no_match when an assign_to_queue event matched no rule; not_applicable otherwise, for example when the answer’s top-level key-value pairs matched no rule or the answer closed the case. Can be null when UJET did not evaluate an answer. |
routing.match_params | object | The key-value pairs that matched a routing rule: each path of the rule, with the value your answer held there as text (object and array values are left out). Empty or null when there are none to show, and 7 days after it was recorded or after the end user’s data has been removed. |
routing.forwarded_from_email_support_id | integer | On the destination session of a move the workflow made, the source session’s email_support_id; null otherwise. |
custom_params | object | The custom_params object your workflow returned at the root of its answer, within its bounds (see Email DAP Webhook Callback): string, number, boolean or null values. null when the answer carried none, or UJET could not use or process the answer, and 7 days after it was recorded or after the end user’s data has been removed. |
fallback.applied | boolean | True when regular routing took over, which can include a move to another queue that was refused or failed; false while the run is in progress and when status is completed. |
fallback.reason | string | One of callback_timeout, timeout, http_4xx, http_5xx, network_error, configuration_error, malformed_response, no_matching_queue, no_action, auth_error, system_error, delivery_failed. Why regular routing took over: always set when applied is true, and null when it is false. callback_timeout and timeout — the workflow did not answer in time; http_4xx, http_5xx, network_error — the request to the workflow failed; auth_error — authentication with the workflow failed (no token could be obtained, or the token was rejected); configuration_error — the tenant’s workflow settings need attention; malformed_response — the answer could not be used; no_matching_queue — the answer asked for a queue that matched none; no_action — the answer asked for nothing UJET acts on; delivery_failed — a planned step could not be carried out; system_error — a failure or decision on UJET’s side. |
Call this, then for each email_threads[].email_thread_id call GET /apps/api/v1/email/messages/:email_thread_id.
| Status | Body | When |
|---|---|---|
| 400 | { "error": "invalid_email_support_id" } | email_support_id ≤ 0 |
| 401 | — | Missing/invalid credentials |
| 404 | { "error": "not_found" } | Not found in tenant |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| email_support_id | 12345 | (Required) Numeric email session id. |
Returns a single parsed email message — headers, body, and attachment metadata.
Authentication: HTTP Basic — username = Apps API user name, password = API token.
| Name | Type | Required | Description |
|---|---|---|---|
email_thread_id | integer | Yes | Numeric email message id (the email_thread_id from the sessions endpoint’s email_threads[]). The RFC 5322 Message-ID is returned separately as message_id. |
email_attachments[].url is null until the attachment-URL prerequisite ships.email_attachments[].data (base64) or body_formatted field.to/cc/bcc are always arrays.| Status | Body | When |
|---|---|---|
| 400 | { "error": "invalid_email_thread_id" } | email_thread_id ≤ 0 |
| 401 | — | Missing/invalid credentials |
| 404 | { "error": "not_found" } | Not found in tenant, a draft, or its content could not be retrieved |
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| email_thread_id | 9001 | (Required) Numeric email message id (from sessions’ email_threads[].email_thread_id). Not the RFC 5322 Message-ID — that is |
Customer-side ingress for Email DAP (Direct Access Point) Webhook Response routing mode — the email twin of Chat DAP Webhook Callback.
Scope. This callback serves inbound email sessions invoked asynchronously. Tenants on API Response mode answer the outbound request directly and never involve this endpoint.
Flow
1. An inbound email arrives and is held in the workflow window (status In Analysis); the agent adapter shows it read-only.
2. The platform POSTs the DAP request to your configured endpoint with callback_url — the absolute URL of this endpoint for your tenant, with the correlation id already in the path. Your endpoint must answer with a 2xx acknowledgment within the API Request Timeout.
3. Your system does its own lookup (CRM, segmentation, business rules) and POSTs the verdict to callback_url before the webhook deadline.
4. The platform records the verdict, acknowledges, and applies it off the request thread. Your POST never waits on mail delivery.
The correlation id in the path is minted by UJET and published only in callback_url. It is a lookup key, not a secret — the request is authenticated by Basic auth, exactly as every other Apps API call.
Available when Email DAP is enabled for your tenant — contact Support.
HTTP Basic, same as the rest of Apps API. - Username / Password — the tenant’s Apps API credential. No per-call token is issued for this endpoint.
| Header | Required | Notes |
|---|---|---|
Authorization: Basic … | yes | Apps API credential, as above. |
Content-Type: application/json | yes | Body must be JSON. |
Accept: application/json | no | Recommended. |
UJETSUBDOMAIN | no | Tenant identifier. Normally inferred from the host; only needed when calling through a host that does not carry the tenant subdomain. Disabled by default. |
| Parameter | Type | Notes |
|---|---|---|
webhook_request_id | string | The correlation id UJET minted for this invocation. Already present in callback_url; do not construct it yourself. Max 255 chars, A-Z a-z 0-9 _ - only. |
Any JSON object. The body is stored verbatim and interpreted after the acknowledgment, so this endpoint validates only what storage cannot survive: a body that is not a JSON object or is nested too deeply to be read, and a serialized size over 65,535 bytes.
| Field | Type | Required | Notes |
|---|---|---|---|
events | array | no | Orchestration actions — see Orchestration actions below. |
error | string | null | no | Optional customer-side error message recorded by UJET. Truncated at 1024 chars; non-string values are ignored. |
custom_params | object | no | Business context to record with the run; returned as orchestration.custom_params by the Email Parsed Data API. Values must be strings, numbers, booleans or null: object and array values are dropped, as are keys longer than 100 characters, and at most 50 keys are kept; string values are cut to 1,000 characters; keys are dropped from the end until the object fits in 64 KB. Any value that is not an object is not recorded. Expires 7 days after it is recorded, or earlier when the end user’s data is removed. |
execution_id | string | no | An identifier for your workflow’s execution; returned as orchestration.flow_id by the Email Parsed Data API. Recorded only when it is 1 to 1,024 characters, each an ASCII letter, a digit or one of ., _, :, /, - — a UUID, for example; any other value is not recorded. Expires 7 days after it is recorded, or earlier when the end user’s data is removed. |
Neither custom_params nor execution_id is recorded from a verdict that fails validation (see Rules below) or that UJET could not process, or while orchestration reporting is not enabled for your tenant.
The body is read at its root, the same as an API Response mode response: put events, custom_params, execution_id and any routing keys at the top level, not inside a wrapper object.
Every top-level key is routing input. All of the body’s top-level keys — events, error, custom_params and execution_id included — form the plain key-value routing input matched against the queue Access Points of type API Response. Those four names are reserved: do not write a routing rule that targets any of them. A misspelled events therefore becomes a routing field rather than an error, and the verdict applies no actions — check the spelling before assuming the platform dropped your events.
Minimal example (routing only):
{
"region": "us-east"
}
events)events is an ordered array of actions, applied in the order given. The same array is accepted at the root of an API Response mode response.
{
"events": [
{ "type": "send_response", "message": "Thanks for reaching out — a specialist will follow up shortly." },
{ "type": "assign_to_queue", "key_value_pairs": { "team": "billing" }, "skills": ["billing", "en"], "skills_operator": "AND" }
]
}
type | Required | Optional | Behavior |
|---|---|---|---|
assign_to_queue | key_value_pairs (object) | skills (array of up to 100 strings), skills_operator (AND | OR) | Forwards the email to the queue whose API Response Access Point matches key_value_pairs. In email a queue owns its own mailbox, so this is a queue-to-queue forward, not a relabel. skills narrow the agent choice inside the destination queue when the Access Point’s Prioritize skills if available is enabled. No agent-targeting flags: email has no virtual agent. |
send_response | message (string, max 2000 chars) | subject (string) | Sends the message to the consumer as a reply on the thread. An empty message is honoured as “ran, sent nothing” and cancels every end_email in the verdict as well as any later send_response, so the email is handed to an agent instead of being resolved. Omit subject to keep the thread’s own. |
end_email | — | delete (bool) | Resolves the email before it is offered to any agent. Planned last, and it supersedes routing entirely: when end_email is present no queue is resolved at all, so a sibling assign_to_queue and any root key-value routing are silently not applied. Do not combine them expecting both. |
Rules:
- end_email in the array cancels routing before any match is attempted — neither the event nor the root key-value pairs route the email.
- When the root key-value pairs match an Access Point, that routing wins and the assign_to_queue event is not used for the match. Key-value pairs that match nothing do not suppress events.
- A verdict that fails validation (unknown type, missing key_value_pairs or message, oversized skills or message, non-array events) is discarded whole — including any plain key-value routing sent alongside it, so a malformed action can never misroute the email. The email is released to the inbox unchanged and is never left in a stuck state. This differs from Chat DAP, where a rejected events array still leaves the key-value routing in effect.
- A body nested deeper than 32 levels cannot be used either: it is still acknowledged, and the run falls back to regular routing as for a verdict that fails validation. A body nested too deeply to be read at all is answered 400.
- Validation runs after the acknowledgment, so it is not visible in the HTTP response. A verdict that fails validation is still answered 200 {"ack":"ok"} and consumed; only the 400 cases in the table below are reported to you. Resending a corrected verdict for the same correlation id is treated as a duplicate and ignored, so a validation failure cannot be repaired by retrying — check orchestration.status (invalid_response) on the session instead, when orchestration reporting is enabled for your tenant.
The success body is intentionally minimal — the webhook caller only needs an ACK:
{
"ack": "ok"
}
What the verdict actually did is not returned. It is applied asynchronously; when orchestration reporting is enabled for your tenant, read the session’s orchestration object through the Email Parsed Data API to see how the run ended.
| Code | When | Retry? |
|---|---|---|
400 | Body is not a JSON object, is nested too deeply to be read, or the serialized body is over 65,535 bytes. | Not unchanged — fix the body first. |
401 | Basic auth credentials missing or invalid. | No. |
404 | Unknown correlation id, or Email DAP is not enabled for this tenant. Also returned — not 400 — when the id is over 255 characters or outside the route charset, and when it belongs to an invocation whose outbound call never succeeded. | No. |
410 | The callback arrived after the webhook deadline. Expiry is checked before delivery state, so a duplicate sent after the deadline is answered 410 even when your first callback was accepted and applied — a 410 is not evidence that the verdict was lost. It also does not mean the email has been released yet; release is done afterwards by the deadline worker or the reaper. | No. |
500 | The verdict was not durably recorded, or was recorded but could not be handed to a worker. | Yes — this is the one outcome you must retry. |
The webhook deadline is currently a fixed 10 minutes, measured from when the platform issues the outbound request. It is not tenant-configurable today — no setting is wired to it — so do not design a longer callback window.
A duplicate callback inside the window is accepted and ignored — it returns 200 {"ack":"ok"} like the first one, so an at-least-once caller is safe. A callback rejected with 400 leaves the pending hold untouched, so a corrected retry before the deadline is still accepted. After the deadline the answer is 410; see the note on that row for what it does and does not tell you.
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | Required. Body must be JSON. |
| Accept | application/json | Recommended. |
| Key | Value | Description |
|---|---|---|
| webhook_request_id | b7c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5 | Correlation id UJET minted for this invocation, already present in |
Agent Skills API — the tenant skills roster: create, list, update, and delete skills. Per-agent assignments are under User Skills; per-queue requirements are under Menu Skill Requirements.
Returns the tenant skills roster with per-skill aggregates (agent count, average proficiency, in-queue usage).
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
Creates a skill in the tenant roster. Returns 409 when the skill name already exists.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json | |
| Content-Type | application/json |
Updates an existing skill. Returns 404 when the skill does not exist.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json | |
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | 5 | (Required) Skill ID |
Replaces an existing skill (PUT equivalent of the PATCH update).
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json | |
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| id | 5 | (Required) Skill ID |
Deletes a skill from the tenant roster. Returns 409 when the skill is still used by a queue requirement.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| id | 5 | (Required) Skill ID |
Agent Skills API — per-agent skill assignments: upsert (assign) or remove a skill for a user.
Creates or updates one skill assignment for the agent. Returns 404 if the user or skill is not found, 422 if the level is out of range.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json | |
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| user_id | 42 | (Required) Agent (user) ID |
Removes a single skill assignment from the agent.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| user_id | 42 | (Required) Agent (user) ID |
| skill_id | 5 | (Required) Skill ID |
Agent Skills API — per-queue skill requirements: upsert (set) or remove a skill requirement on a menu cascade queue group.
Creates or updates a skill requirement term on a queue cascade group.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json | |
| Content-Type | application/json |
| Key | Value | Description |
|---|---|---|
| menu_id | 12 | (Required) Menu (queue) ID |
Removes a skill requirement term from a queue cascade group.
Authentication: HTTP Basic — username = Apps API user key, password = Apps API token.
| Key | Value | Description |
|---|---|---|
| Accept | application/json |
| Key | Value | Description |
|---|---|---|
| menu_id | 12 | (Required) Menu (queue) ID |
| cascade_group_id | 101 | (Required) Cascade group ID |
| skill_id | 5 | (Required) Skill ID |
Bulk email status management Apps API. Transition one or more email sessions to a target status in a single call, with per-session results.
Bulk-transition one or more email sessions to a single target status. Returns a per-session result array (one entry per input id, in request order). HTTP 200 is returned even when some items fail, so inspect each result.
Authentication: HTTP Basic — username = Apps API user name, password = API token.
| Name | Type | Required | Description |
|---|---|---|---|
session_ids | string or string[] | Yes | One or more email session ids (numeric EmailSupport ids as strings, e.g. “12345”). Max 100 per request. |
new_email_status | string | Yes | Target status: active, paused, resolved, or closed. |
existing_email_status | string | No | Optional expected current status. If it does not match the session’s actual status, that item is reported stale_state and left unchanged. |
active → paused, resolved · paused → active, closed · resolved → closed · unopened → active · reopened → active. Any other pair is reported invalid_transition.
Each results[] entry has a result of:
success — transitioned (from_status, to_status).noop — already at the target status (current_status).failure — not applied, with reason: not_found, invalid_transition (current_status), stale_state (current_status), or hidden (current_status) — the session is hidden, so its status cannot change until it is un-hidden. A hidden session reports hidden rather than noop, invalid_transition or stale_state.| Status | Body | When |
|---|---|---|
| 400 | { "message": "..." } | Missing/invalid session_ids, invalid new_email_status / existing_email_status, or more than 100 ids |
| 401 | { "message": "Not Authorized" } | Missing/invalid credentials |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
Email session hiding Apps API. Hide email sessions from every agent surface, and make them visible again, by email session id, with per-session results. Hiding never changes a session’s status. Hide and un-hide are available only through this API.
Hide one or more email sessions. A hidden session leaves every agent surface (lists, counts, search and drafts), is no longer auto-assigned, auto-paused or auto-closed, and refuses agent actions. Its status does not change. Returns a per-session result array (one entry per input id, in request order). HTTP 200 is returned even when some items fail, so inspect each result.
Authentication: HTTP Basic — username = Apps API user name, password = API token. Company-key credentials are rejected.
Availability: until email session hiding is enabled for the tenant, this endpoint returns 404.
| Name | Type | Required | Description |
|---|---|---|---|
session_ids | string or string[] | Yes | One or more email session ids: the numeric EmailSupport id as a string (e.g. “12345”), the same id GET /apps/api/v1/email/sessions/:email_support_id takes. A JSON number is rejected. Max 100 per request. |
Each results[] entry has a result of:
success — hidden now (status, hidden_at).noop — already hidden by an earlier call (status, hidden_at).failure — not hidden, with reason:not_found — no such session.orchestration_in_progress (status) — an email workflow is still processing the session. Retry later.forward_in_progress (status) — a transfer to another queue is still in flight. Retry later.internal_error — retry.A hidden session stays readable through GET /apps/api/v1/email/sessions/:email_support_id, which reports hidden: true. A customer reply to a hidden session un-hides it automatically.
| Status | Body | When |
|---|---|---|
| 400 | { "message": "..." } | Missing or empty session_ids, an id that is not a 1–64 character string (A–Z, a–z, 0–9, _, -), or more than 100 ids |
| 401 | { "message": "..." } | Missing or invalid credentials, or company-key credentials |
| 404 | { "error": "not_found" } | Email session hiding is not enabled for the tenant |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
Make one or more hidden email sessions visible again, with the status they already have. Un-hide clears either kind of hide: one made through POST /apps/api/v1/email/hide, and one made by an email workflow’s end_email event with delete: true. Returns a per-session result array (one entry per input id, in request order). HTTP 200 is returned even when some items fail, so inspect each result.
Authentication: HTTP Basic — username = Apps API user name, password = API token. Company-key credentials are rejected.
Availability: until email session hiding is enabled for the tenant, this endpoint returns 404.
| Name | Type | Required | Description |
|---|---|---|---|
session_ids | string or string[] | Yes | One or more email session ids: the numeric EmailSupport id as a string (e.g. “12345”), the same id GET /apps/api/v1/email/sessions/:email_support_id takes. A JSON number is rejected. Max 100 per request. |
Each results[] entry has a result of:
success — visible now (status, hidden_at: null).noop — was not hidden (status, hidden_at: null).failure — with reason not_found (no such session) or internal_error (retry).| Status | Body | When |
|---|---|---|
| 400 | { "message": "..." } | Missing or empty session_ids, an id that is not a 1–64 character string (A–Z, a–z, 0–9, _, -), or more than 100 ids |
| 401 | { "message": "..." } | Missing or invalid credentials, or company-key credentials |
| 404 | { "error": "not_found" } | Email session hiding is not enabled for the tenant |
| Key | Value | Description |
|---|---|---|
| Content-Type | application/json | |
| Accept | application/json |
| Key | Value | Type |
|---|---|---|
| subdomain | ||
| domain | string | |
| username | ||
| password | ||
| call_type | ||
| agent_email | ||
| ticket_id | ||
| end_user_number | ||
| outbound_number | ||
| lang | ||
| menu_id | ||
| wait[from] | ||
| wait[to] | ||
| channel_type | ||
| menu_type | ||
| recording_permission | ||
| job_id |