Help desk automation

Macros, triggers, automations, AI agents and AI assist for a help desk.

Three ways to run the same actions. A macro is a set of actions a person applies to a conversation, now. A trigger is a set an event applies, straight after the change that caused it. An automation is a set a clock applies, to every conversation matching its conditions. All three take the same action list and the same filter grammar as views, and every id an action names is checked against the desk when the rule is saved.

The AI agent answers widget conversations from the desk's published articles and linked knowledge bases, and hands a conversation to a person when it is not sure. Reply suggestions and summaries give agents the same help on demand. Which language model does the work is not part of the API, and a failure there is reported as 503 with nothing else.

Writes are attributed to the key's owner, who must staff the desk. Configuration needs help_desk:configure and a desk lead or admin.

List macros#

The macros the key's owner would see in the inbox picker: shared macros, their teams' macros, and their own personal ones.

GET/api/v1/help-desks/{helpDeskId}/macros

Path parameters

helpDeskIdstringrequired
Help desk id.

Responses

The macros.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/macros" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"macros": [
{
"id": "7d1e…",
"helpDeskId": "4ebf…",
"name": "Refund issued",
"folder": "Billing/Refunds",
"description": "Use after a refund is issued",
"body": "Hi {{contact.firstName}}, your refund is on its way.",
"bodyHtml": null,
"actions": [
{
"type": "set_status",
"value": "pending"
},
{
"type": "add_tag",
"tagId": "a19c…"
}
],
"scope": "shared",
"ownerAgentId": null,
"teamId": null,
"shortcut": ";refund",
"locale": null,
"usageCount": 12
}
]
},
"meta": {
"requestId": "req_…"
}
}

Create a macro#

A saved reply plus the field changes that go with it. `scope` is `shared` (everyone's picker, the default), `team` (needs `teamId`) or `personal` (only the author's). Any agent may keep personal macros with `help_desk:respond`. Shared and team macros need `help_desk:configure` and a desk lead or admin. Placeholders such as `{{contact.firstName}}` are checked when the macro is saved, and every id an action names must be on this desk.

POST/api/v1/help-desks/{helpDeskId}/macros

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
name
string
required
folder
string
description
string
body
string (supports placeholders)
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
scope
shared | team | personal
teamId
string (team scope)
shortcut
string
locale
string

Responses

The created macro.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/macros" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Refund issued",
"folder": "Billing/Refunds",
"body": "Hi {{contact.firstName}}, your refund is on its way.",
"actions": [
{
"type": "set_status",
"value": "pending"
}
]
}'
Response201
{
"data": {
"id": "7d1e…",
"helpDeskId": "4ebf…",
"name": "Refund issued",
"folder": "Billing/Refunds",
"description": "Use after a refund is issued",
"body": "Hi {{contact.firstName}}, your refund is on its way.",
"bodyHtml": null,
"actions": [
{
"type": "set_status",
"value": "pending"
},
{
"type": "add_tag",
"tagId": "a19c…"
}
],
"scope": "shared",
"ownerAgentId": null,
"teamId": null,
"shortcut": ";refund",
"locale": null,
"usageCount": 12
},
"meta": {
"requestId": "req_…"
}
}

Get a macro#

One macro. Someone else's personal macro is not found.

GET/api/v1/help-desks/{helpDeskId}/macros/{macroId}

Path parameters

helpDeskIdstringrequired
Help desk id.
macroIdstringrequired
Macro id.

Responses

The macro.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/macros/{macroId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"id": "7d1e…",
"helpDeskId": "4ebf…",
"name": "Refund issued",
"folder": "Billing/Refunds",
"description": "Use after a refund is issued",
"body": "Hi {{contact.firstName}}, your refund is on its way.",
"bodyHtml": null,
"actions": [
{
"type": "set_status",
"value": "pending"
},
{
"type": "add_tag",
"tagId": "a19c…"
}
],
"scope": "shared",
"ownerAgentId": null,
"teamId": null,
"shortcut": ";refund",
"locale": null,
"usageCount": 12
},
"meta": {
"requestId": "req_…"
}
}

Update a macro#

Change any field; fields you leave out keep their values. Your own personal macro needs `help_desk:respond`. A macro that is, or would become, shared or team-scoped needs `help_desk:configure` and a desk lead or admin.

PATCH/api/v1/help-desks/{helpDeskId}/macros/{macroId}

Path parameters

helpDeskIdstringrequired
Help desk id.
macroIdstringrequired
Macro id.

Body

application/json
name
string
body
string
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
scope
shared | team | personal

Responses

The updated macro.

curl -X PATCH "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/macros/{macroId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"description": "Use after a refund is issued"
}'
Response200
{
"data": {
"id": "7d1e…",
"helpDeskId": "4ebf…",
"name": "Refund issued",
"folder": "Billing/Refunds",
"description": "Use after a refund is issued",
"body": "Hi {{contact.firstName}}, your refund is on its way.",
"bodyHtml": null,
"actions": [
{
"type": "set_status",
"value": "pending"
},
{
"type": "add_tag",
"tagId": "a19c…"
}
],
"scope": "shared",
"ownerAgentId": null,
"teamId": null,
"shortcut": ";refund",
"locale": null,
"usageCount": 12
},
"meta": {
"requestId": "req_…"
}
}

Delete a macro#

Remove a macro from every picker. Same permission rule as updating it.

DELETE/api/v1/help-desks/{helpDeskId}/macros/{macroId}

Path parameters

helpDeskIdstringrequired
Help desk id.
macroIdstringrequired
Macro id.

Responses

Deleted.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/macros/{macroId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true
},
"meta": {
"requestId": "req_…"
}
}

Apply a macro#

Run a macro on a conversation as the key's owner, who must staff the desk. The field changes are applied first and the reply is sent last. Returns the updated conversation. A macro whose stored actions name something no longer on the desk is refused with `409`.

POST/api/v1/help-desks/{helpDeskId}/conversations/{conversationId}/macro

Path parameters

helpDeskIdstringrequired
Help desk id.
conversationIdstringrequired
Conversation id.

Body

application/json
macroId
string
required

Responses

The conversation after the macro ran.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/conversations/{conversationId}/macro" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"macroId": "7d1e…"
}'
Response200
{
"data": {
"id": "d4df…",
"status": "pending",
"priority": "high",
"tags": [
{
"id": "a19c…",
"name": "refund"
}
]
},
"meta": {
"requestId": "req_…"
}
}

List triggers#

The desk's triggers, in the order they run.

GET/api/v1/help-desks/{helpDeskId}/triggers

Path parameters

helpDeskIdstringrequired
Help desk id.

Responses

The triggers.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/triggers" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"triggers": [
{
"id": "c3a0…",
"helpDeskId": "4ebf…",
"name": "Urgent to escalations",
"description": null,
"event": "conversation.created",
"conditions": {
"op": "and",
"rules": [
{
"field": "priority",
"op": "eq",
"value": "urgent"
}
]
},
"actions": [
{
"type": "assign_team",
"teamId": "5b2e…"
}
],
"position": 100,
"fireCount": 41,
"lastFiredAt": "2026-09-30T14:02:11.000Z",
"isEnabled": true
}
]
},
"meta": {
"requestId": "req_…"
}
}

Create a trigger#

Actions applied straight after an event, when the conversation matches `conditions` (the same filter grammar as views). Events: `conversation.created`, `conversation.status_changed`, `conversation.assigned`, `conversation.priority_changed`, `conversation.tagged`, `message.from_contact`, `message.from_agent`, `sla.warned`, `sla.breached`, `csat.submitted`, `live_session.ended`. A trigger that would provoke itself, such as a reply on `message.from_agent`, is refused. `emit_event` names a help desk event without its `helpdesk.` prefix. Needs `help_desk:configure` and a desk lead or admin.

POST/api/v1/help-desks/{helpDeskId}/triggers

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
name
string
required
description
string
event
string
required
conditions
filter group or null
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
required
position
number
isEnabled
boolean (switched off, a rule stays listed and never runs)

Responses

The created trigger.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/triggers" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Urgent to escalations",
"event": "conversation.created",
"conditions": {
"op": "and",
"rules": [
{
"field": "priority",
"op": "eq",
"value": "urgent"
}
]
},
"actions": [
{
"type": "assign_team",
"teamId": "5b2e…"
}
]
}'
Response201
{
"data": {
"id": "c3a0…",
"helpDeskId": "4ebf…",
"name": "Urgent to escalations",
"description": null,
"event": "conversation.created",
"conditions": {
"op": "and",
"rules": [
{
"field": "priority",
"op": "eq",
"value": "urgent"
}
]
},
"actions": [
{
"type": "assign_team",
"teamId": "5b2e…"
}
],
"position": 100,
"fireCount": 41,
"lastFiredAt": "2026-09-30T14:02:11.000Z",
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Get a trigger#

One trigger, with how often it has fired.

GET/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}

Path parameters

helpDeskIdstringrequired
Help desk id.
triggerIdstringrequired
Trigger id.

Responses

The trigger.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"id": "c3a0…",
"helpDeskId": "4ebf…",
"name": "Urgent to escalations",
"description": null,
"event": "conversation.created",
"conditions": {
"op": "and",
"rules": [
{
"field": "priority",
"op": "eq",
"value": "urgent"
}
]
},
"actions": [
{
"type": "assign_team",
"teamId": "5b2e…"
}
],
"position": 100,
"fireCount": 41,
"lastFiredAt": "2026-09-30T14:02:11.000Z",
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Update a trigger#

Change any field; fields you leave out keep their values. The loop check runs on the result.

PATCH/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}

Path parameters

helpDeskIdstringrequired
Help desk id.
triggerIdstringrequired
Trigger id.

Body

application/json
name
string
event
string
conditions
filter group or null
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
position
number
isEnabled
boolean (switched off, a rule stays listed and never runs)

Responses

The updated trigger.

curl -X PATCH "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"isEnabled": false
}'
Response200
{
"data": {
"id": "c3a0…",
"helpDeskId": "4ebf…",
"name": "Urgent to escalations",
"description": null,
"event": "conversation.created",
"conditions": {
"op": "and",
"rules": [
{
"field": "priority",
"op": "eq",
"value": "urgent"
}
]
},
"actions": [
{
"type": "assign_team",
"teamId": "5b2e…"
}
],
"position": 100,
"fireCount": 41,
"lastFiredAt": "2026-09-30T14:02:11.000Z",
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Delete a trigger#

Stop a trigger from running.

DELETE/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}

Path parameters

helpDeskIdstringrequired
Help desk id.
triggerIdstringrequired
Trigger id.

Responses

Deleted.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/triggers/{triggerId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true
},
"meta": {
"requestId": "req_…"
}
}

List automations#

The desk's automations, in the order they run.

GET/api/v1/help-desks/{helpDeskId}/automations

Path parameters

helpDeskIdstringrequired
Help desk id.

Responses

The automations.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/automations" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"automations": [
{
"id": "e81f…",
"helpDeskId": "4ebf…",
"name": "Close stale pending",
"description": null,
"conditions": {
"op": "and",
"rules": [
{
"field": "status",
"op": "eq",
"value": "pending"
},
{
"field": "lastMessageAt",
"op": "older_than_minutes",
"value": 4320
}
]
},
"actions": [
{
"type": "set_status",
"value": "solved"
}
],
"intervalMinutes": 60,
"position": 100,
"lastRunAt": "2026-09-30T14:00:00.000Z",
"lastRunMatched": 3,
"isEnabled": true
}
]
},
"meta": {
"requestId": "req_…"
}
}

Create an automation#

Actions applied on a schedule to every conversation matching `conditions`, at most once per `intervalMinutes` (default 60). At least one action has to change something the conditions test, or the automation would act on the same conversations forever; such an automation is refused with an explanation. Needs `help_desk:configure` and a desk lead or admin.

POST/api/v1/help-desks/{helpDeskId}/automations

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
name
string
required
description
string
conditions
filter group
required
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
required
intervalMinutes
number (1 to 1440)
position
number
isEnabled
boolean (switched off, a rule stays listed and never runs)

Responses

The created automation.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/automations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Close stale pending",
"conditions": {
"op": "and",
"rules": [
{
"field": "status",
"op": "eq",
"value": "pending"
},
{
"field": "lastMessageAt",
"op": "older_than_minutes",
"value": 4320
}
]
},
"actions": [
{
"type": "set_status",
"value": "solved"
}
]
}'
Response201
{
"data": {
"id": "e81f…",
"helpDeskId": "4ebf…",
"name": "Close stale pending",
"description": null,
"conditions": {
"op": "and",
"rules": [
{
"field": "status",
"op": "eq",
"value": "pending"
},
{
"field": "lastMessageAt",
"op": "older_than_minutes",
"value": 4320
}
]
},
"actions": [
{
"type": "set_status",
"value": "solved"
}
],
"intervalMinutes": 60,
"position": 100,
"lastRunAt": "2026-09-30T14:00:00.000Z",
"lastRunMatched": 3,
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Get an automation#

One automation, with when it last ran and how many conversations it matched.

GET/api/v1/help-desks/{helpDeskId}/automations/{automationId}

Path parameters

helpDeskIdstringrequired
Help desk id.
automationIdstringrequired
Automation id.

Responses

The automation.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/automations/{automationId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"id": "e81f…",
"helpDeskId": "4ebf…",
"name": "Close stale pending",
"description": null,
"conditions": {
"op": "and",
"rules": [
{
"field": "status",
"op": "eq",
"value": "pending"
},
{
"field": "lastMessageAt",
"op": "older_than_minutes",
"value": 4320
}
]
},
"actions": [
{
"type": "set_status",
"value": "solved"
}
],
"intervalMinutes": 60,
"position": 100,
"lastRunAt": "2026-09-30T14:00:00.000Z",
"lastRunMatched": 3,
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Update an automation#

Change any field; fields you leave out keep their values. The loop check runs on the result.

PATCH/api/v1/help-desks/{helpDeskId}/automations/{automationId}

Path parameters

helpDeskIdstringrequired
Help desk id.
automationIdstringrequired
Automation id.

Body

application/json
name
string
conditions
filter group
actions
array of actions, each `{ type, … }`: `set_status`, `set_priority`, `assign_agent`, `assign_team`, `route`, `add_tag`, `remove_tag`, `set_custom_field`, `set_brand`, `reply`, `note`, `apply_macro`, `snooze`, `handoff_to_human`, `send_csat`, `notify`, `emit_event`
intervalMinutes
number
isEnabled
boolean (switched off, a rule stays listed and never runs)

Responses

The updated automation.

curl -X PATCH "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/automations/{automationId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"intervalMinutes": 120
}'
Response200
{
"data": {
"id": "e81f…",
"helpDeskId": "4ebf…",
"name": "Close stale pending",
"description": null,
"conditions": {
"op": "and",
"rules": [
{
"field": "status",
"op": "eq",
"value": "pending"
},
{
"field": "lastMessageAt",
"op": "older_than_minutes",
"value": 4320
}
]
},
"actions": [
{
"type": "set_status",
"value": "solved"
}
],
"intervalMinutes": 60,
"position": 100,
"lastRunAt": "2026-09-30T14:00:00.000Z",
"lastRunMatched": 3,
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Delete an automation#

Stop an automation from running.

DELETE/api/v1/help-desks/{helpDeskId}/automations/{automationId}

Path parameters

helpDeskIdstringrequired
Help desk id.
automationIdstringrequired
Automation id.

Responses

Deleted.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/automations/{automationId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true
},
"meta": {
"requestId": "req_…"
}
}

List AI agents#

The desk's AI agents.

GET/api/v1/help-desks/{helpDeskId}/ai-agents

Path parameters

helpDeskIdstringrequired
Help desk id.

Responses

The AI agents.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai-agents" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"aiAgents": [
{
"id": "0a77…",
"helpDeskId": "4ebf…",
"name": "Billing assistant",
"publicName": "Billing helper",
"avatarUrl": null,
"voiceAgentId": null,
"persona": "Warm and brief.",
"instructions": "Answer billing questions from the help center.",
"tools": [],
"minConfidence": 0.6,
"maxTurns": 6,
"handoffPhrases": [
"speak to a human",
"talk to a person"
],
"answerOutsideHours": true,
"channels": [
"chat"
],
"isEnabled": true
}
]
},
"meta": {
"requestId": "req_…"
}
}

Create an AI agent#

The first responder on widget conversations. It answers from the desk's published articles and linked knowledge bases, and hands the conversation to a person below `minConfidence`, on a `handoffPhrases` match, or after `maxTurns` replies. An enabled agent needs something to answer from: link a knowledge base or publish an article first. `voiceAgentId` and `tools` must be ones this key can read. Needs `help_desk:configure` and a desk lead or admin.

POST/api/v1/help-desks/{helpDeskId}/ai-agents

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
name
string
required
publicName
string
avatarUrl
https URL
voiceAgentId
string
persona
string
instructions
string
tools
string[]
minConfidence
number (0 to 1, default 0.6)
maxTurns
number (1 to 30, default 6)
handoffPhrases
string[]
answerOutsideHours
boolean
channels
string[] (chat, email, voice, video, api)
isEnabled
boolean (default true)

Responses

The created AI agent.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai-agents" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Billing assistant",
"publicName": "Billing helper",
"minConfidence": 0.7
}'
Response201
{
"data": {
"id": "0a77…",
"helpDeskId": "4ebf…",
"name": "Billing assistant",
"publicName": "Billing helper",
"avatarUrl": null,
"voiceAgentId": null,
"persona": "Warm and brief.",
"instructions": "Answer billing questions from the help center.",
"tools": [],
"minConfidence": 0.6,
"maxTurns": 6,
"handoffPhrases": [
"speak to a human",
"talk to a person"
],
"answerOutsideHours": true,
"channels": [
"chat"
],
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Get an AI agent#

One AI agent's configuration.

GET/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}

Path parameters

helpDeskIdstringrequired
Help desk id.
aiAgentIdstringrequired
AI agent id.

Responses

The AI agent.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"id": "0a77…",
"helpDeskId": "4ebf…",
"name": "Billing assistant",
"publicName": "Billing helper",
"avatarUrl": null,
"voiceAgentId": null,
"persona": "Warm and brief.",
"instructions": "Answer billing questions from the help center.",
"tools": [],
"minConfidence": 0.6,
"maxTurns": 6,
"handoffPhrases": [
"speak to a human",
"talk to a person"
],
"answerOutsideHours": true,
"channels": [
"chat"
],
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Update an AI agent#

Change any field; fields you leave out keep their values.

PATCH/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}

Path parameters

helpDeskIdstringrequired
Help desk id.
aiAgentIdstringrequired
AI agent id.

Body

application/json
minConfidence
number
isEnabled
boolean
instructions
string

Responses

The updated AI agent.

curl -X PATCH "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"minConfidence": 0.8
}'
Response200
{
"data": {
"id": "0a77…",
"helpDeskId": "4ebf…",
"name": "Billing assistant",
"publicName": "Billing helper",
"avatarUrl": null,
"voiceAgentId": null,
"persona": "Warm and brief.",
"instructions": "Answer billing questions from the help center.",
"tools": [],
"minConfidence": 0.6,
"maxTurns": 6,
"handoffPhrases": [
"speak to a human",
"talk to a person"
],
"answerOutsideHours": true,
"channels": [
"chat"
],
"isEnabled": true
},
"meta": {
"requestId": "req_…"
}
}

Delete an AI agent#

An AI agent that has never handled a conversation is deleted. One that has is turned off instead, so its conversations keep recording that it answered them. `effect` says which happened.

DELETE/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}

Path parameters

helpDeskIdstringrequired
Help desk id.
aiAgentIdstringrequired
AI agent id.

Responses

What happened.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai-agents/{aiAgentId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true,
"effect": "deactivated",
"message": "Turned off \"Billing assistant\"."
},
"meta": {
"requestId": "req_…"
}
}

List reply suggestions#

Draft replies still on offer to the key's owner for one conversation.

GET/api/v1/help-desks/{helpDeskId}/ai/suggest

Path parameters

helpDeskIdstringrequired
Help desk id.

Query parameters

conversationIdstringrequired
Conversation id.

Responses

The suggestions.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai/suggest" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"suggestions": [
{
"id": "91c2…",
"conversationId": "d4df…",
"kind": "reply",
"body": "Refunds for a duplicate charge arrive within five business days.",
"sources": [
{
"kind": "article",
"id": "2b7f…",
"title": "How refunds work"
}
],
"confidence": 0.82,
"state": "offered",
"createdAt": "2026-09-30T14:03:00.000Z"
}
]
},
"meta": {
"requestId": "req_…"
}
}

Suggest a reply#

Draft an answer to the customer's latest message from the desk's articles and linked knowledge bases, for the key's owner to review and send. `suggestion` is null when there is nothing to answer. Answers `503` if the assistant is unavailable.

POST/api/v1/help-desks/{helpDeskId}/ai/suggest

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
conversationId
string
required

Responses

The draft.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai/suggest" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversationId": "d4df…"
}'
Response200
{
"data": {
"suggestion": {
"id": "91c2…",
"kind": "reply",
"body": "Refunds arrive within five business days.",
"state": "offered"
}
},
"meta": {
"requestId": "req_…"
}
}

Dismiss a reply suggestion#

Record that a draft was not used.

DELETE/api/v1/help-desks/{helpDeskId}/ai/suggest

Path parameters

helpDeskIdstringrequired
Help desk id.

Query parameters

suggestionIdstringrequired
Suggestion id.

Responses

Dismissed.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai/suggest" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"dismissed": true
},
"meta": {
"requestId": "req_…"
}
}

Summarise a conversation#

A short summary for someone picking the conversation up, the customer's sentiment from -100 to 100, and the most useful next step. The summary and sentiment are also stored on the conversation. Answers `503` if the assistant is unavailable.

POST/api/v1/help-desks/{helpDeskId}/ai/summary

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
conversationId
string
required

Responses

The summary.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/ai/summary" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversationId": "d4df…"
}'
Response200
{
"data": {
"summary": "The customer was charged twice this month and wants the duplicate refunded.",
"sentiment": -35,
"nextStep": "Confirm the duplicate charge and issue the refund."
},
"meta": {
"requestId": "req_…"
}
}

List linked knowledge bases#

The knowledge bases this desk's AI agent and reply suggestions answer from.

GET/api/v1/help-desks/{helpDeskId}/knowledge-bases

Path parameters

helpDeskIdstringrequired
Help desk id.

Responses

The links.

curl -X GET "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/knowledge-bases" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"knowledgeBases": [
{
"knowledgeBaseId": "3c90…",
"name": "Plan documents 2026",
"description": "Summary of benefits and formulary.",
"documentCount": 41,
"linkedAt": "2026-09-30T14:00:00.000Z"
}
]
},
"meta": {
"requestId": "req_…"
}
}

Link a knowledge base#

Let the desk answer from an existing knowledge base. It has to be one this key can read, in its own organization. Needs `help_desk:configure` and a desk lead or admin.

POST/api/v1/help-desks/{helpDeskId}/knowledge-bases

Path parameters

helpDeskIdstringrequired
Help desk id.

Body

application/json
knowledgeBaseId
string
required

Responses

The link.

curl -X POST "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/knowledge-bases" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"knowledgeBaseId": "3c90…"
}'
Response201
{
"data": {
"knowledgeBaseId": "3c90…",
"name": "Plan documents 2026",
"documentCount": 41
},
"meta": {
"requestId": "req_…"
}
}

Unlink a knowledge base#

Stop answering from a knowledge base. The knowledge base itself is untouched.

DELETE/api/v1/help-desks/{helpDeskId}/knowledge-bases/{knowledgeBaseId}

Path parameters

helpDeskIdstringrequired
Help desk id.
knowledgeBaseIdstringrequired
Knowledge base id.

Responses

Unlinked.

curl -X DELETE "https://voice.evryhealth.com/api/v1/help-desks/{helpDeskId}/knowledge-bases/{knowledgeBaseId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true
},
"meta": {
"requestId": "req_…"
}
}