Skip to navigation

Conversations

All the endpoints on this page are under /api/v1/accounts/{account_id}/developer/conversations. They take the same api_access_token header as the send endpoint.

Which conversation id to use

Every endpoint on this page takes the conversation number in the path. This number is the display_id of the conversation. It is the number in the dashboard URL: in /app/accounts/1/conversations/1234, the number is 1234. It is also the conversation_id that the send endpoint returns.

The conversation also has an internal id. The developer API does not take the internal id. The workflow trigger and the workflow webhook take the internal id, not the dashboard number. To get the internal id of a conversation, use Pre-call context. See Workflows.

Read a conversation

curl https://omni-channel.hams.ai/api/v1/accounts/1/developer/conversations/1234 \
-H "api_access_token: $HAMS_TOKEN"

The response has these fields, and more:

FieldMeaning
idThe conversation number in the dashboard URL (display_id). It is not the internal id
inbox_idThe id of the inbox
statusopen, resolved, pending, or snoozed
can_replytrue when the service window is open and the API accepts plain content
priorityurgent, high, medium, low, or null
labelsThe labels of the conversation
custom_attributesThe custom attributes of the conversation
snoozed_untilThe time when a snoozed conversation opens again
meta.senderThe contact of the conversation
meta.assigneeThe agent or the AI agent that owns the conversation, if it has one
meta.assignee_typeUser for an agent, Hams::Agent::Assistant for an AI agent, or AgentBot for another bot. A conversation that an AI agent or a bot owns counts as assigned
meta.teamThe team of the conversation, if it has one
messagesA list with the last message of the conversation

Read can_reply before you send plain content. If it is false, send a template. See Messages.

Create a conversation

POST /api/v1/accounts/{account_id}/developer/conversations
{
"inbox_id": 5,
"contact_id": 42,
"status": "open",
"message": { "content": "Hi, we received your request." }
}

inbox_id and contact_id are necessary. The optional fields are message, status, assignee_id, team_id, custom_attributes, additional_attributes, and snoozed_until. An assignee_id or a team_id that is not in your account returns 404.

If the inbox keeps 1 conversation for each contact, the API returns the latest conversation of the contact and does not create a new one. This endpoint does not check the service window for message. For most integrations, the send endpoint is better. It creates the conversation when necessary, and it checks the window.

Reply in a conversation

POST /api/v1/accounts/{account_id}/developer/conversations/{conversation_id}/messages
{ "content": "It is on its way." }

This endpoint does not check the service window. Use the send endpoint with conversation_id for a reply to the customer. It takes the same input and checks the window first.

Use this endpoint for a private note. Agents see a private note, and the customer never gets it:

{ "content": "The customer called about this too.", "private": true }

The message has the name of the key as its sender. A request cannot set another sender.

Change the status

POST /api/v1/accounts/{account_id}/developer/conversations/{conversation_id}/toggle_status
{ "status": "resolved" }

The values are open, resolved, pending, and snoozed. For snoozed, also send snoozed_until as a Unix timestamp in seconds. Do not send a date string such as ISO 8601. If you send no status, an open conversation becomes resolved, and any other conversation becomes open.

The response gives the new status:

{
"meta": {},
"payload": { "success": true, "conversation_id": 1234, "current_status": "resolved", "snoozed_until": null }
}

A resolved conversation changes where the next message goes. The next send to that contact opens a new conversation. It does not continue the resolved one. If the inbox keeps 1 conversation for each contact, the next send continues the resolved conversation.

Priority, labels, assignment, and custom attributes

Priority

POST .../toggle_priority with {"priority": "urgent"}. The values are urgent, high, medium, and low. Send null to remove the priority. The response has no body. PATCH .../{conversation_id} with priority does the same and returns the conversation.

Labels

GET .../labels returns the labels. POST .../labels with {"labels": ["vip", "refund"]} replaces all the labels. Send every label that you want to keep.

Assignment

POST .../assignments with {"assignee_id": 7} for an agent, or {"team_id": 3} for a team. Send {"assignee_id": null} to remove the agent.

Custom attributes

POST .../custom_attributes with {"custom_attributes": {"crm_id": "9912"}}. The object replaces all the custom attributes of the conversation.

Send only an agent id or a team id from your account. If the API does not find the assignee_id in your account, it removes the agent from the conversation. If it does not find the team_id, it removes the team. It does not return an error.

When both assignee_id and team_id are in 1 assignment request, the API uses assignee_id only. The response is the agent, the team, or null.