Conversations
The shared inbox: read threads, assign, resolve and reopen.
The shared inbox holds one conversation per customer and channel. Through the API you can route conversations from your own systems (a helpdesk, a CRM, an on-call rota), read threads, and close them, while your team keeps working in the portal.
How it works: Inbox & conversationsA conversation's life · Route conversations to the right person · Read a thread · Reply and close · Events
A conversation's life#
| State | Meaning |
|---|---|
bot | A flow or AI bot is answering |
needs_agent | Waiting for a person: the bot handed over, or the customer asked for someone |
assigned | Given to a team member who has not replied yet |
human | A person is handling it |
snoozed | Parked until snoozed_until |
resolved | Closed. If the customer writes again it reopens by itself |
open is true for every state but resolved, and unread says whether the customer wrote since someone last read the thread.
Route conversations to the right person#
A common integration: when a conversation needs a person, pick who takes it in your system and assign it.
- Subscribe an endpoint to
conversation.needs_agent. - Choose a member from
GET /members(viewers cannot be assigned). - Assign with
POST /conversations/{id}/assign:
{ "member_id": "usr_41" }The member must be able to see the conversation's number or account; otherwise the answer is assignee_invalid rather than a thread nobody can open.
Read a thread#
GET /conversationswith filters builds any queue:open=true&assignee=noneis everything waiting for someone;customer=0501234567finds one customer's thread.GET /conversations/{id}/messagesreturns the messages in both directions, newest first. Internal notes between agents are never included.
Reply and close#
Reply with POST /messages, sending to the conversation's customer.address (and channel for Instagram or Messenger). The reply appears in the thread in the portal like any other.
Close with POST /conversations/{id}/resolve, and reopen with POST /conversations/{id}/reopen (unassigned, or to member_id). Every action you take is recorded in the conversation's history as the API, with the key that made it.
Events#
| Event | When |
|---|---|
conversation.created | A customer started a new conversation |
conversation.needs_agent | It is waiting for a person |
conversation.assigned | It was assigned (by a person, a rule or the API) |
conversation.resolved | It was closed |
conversation.reopened | A closed conversation became active again |
message.received still arrives for every customer message, so you can mirror the thread in your own tool.
Endpoints
- getList conversations
/conversations - getGet a conversation
/conversations/{id} - postAssign a conversation
/conversations/{id}/assign - getList a conversation's messages
/conversations/{id}/messages - postReopen a conversation
/conversations/{id}/reopen - postResolve a conversation
/conversations/{id}/resolve - getList team members
/members
List conversations
https://api.saei.automize.sa/v1/conversations- Scope:
conversations:read - Live keys only
Threads in the shared inbox, newest first, on WhatsApp, Instagram and Messenger. Filter to build your own queue: open=true&assignee=none is everything waiting for someone.
Query parameters
limitintegeroptionalHow many objects to return, 1 to 100.
cursorstringoptionalThe
next_cursorfrom the previous page.openbooleanoptionaltruefor unresolved conversations,falsefor resolved ones.statestringoptionalOne of
botneeds_agentassignedhumanresolvedsnoozedchannelstringoptionalOne of
whatsappinstagrammessengerassigneestringoptionalA member id (
usr_…), ornonefor unassigned.customerstringoptionalThe customer's phone (any format) or Instagram / Messenger id.
unreadbooleanoptional
Response fields200· A page of conversations.
object"list"requireddataarray<Conversation>requiredChild fields (17)
idstringrequiredobject"conversation"requiredchannelstringrequiredOne of
whatsappinstagrammessengercustomerobjectrequiredChild fields (3)
contact_idstring | nulloptionaladdressstringoptionalThe phone (E.164) on WhatsApp; the customer's id on Instagram / Messenger. Send replies
tothis.namestring | nulloptional
number_idstring | nulloptionalstatestringrequiredbotthe automation is answering;needs_agentwaiting for a person;assignedhanded to someone who has not replied yet;humana person is on it;snoozedparked untilsnoozed_until;resolvedclosed.One of
botneeds_agentassignedhumanresolvedsnoozedopenbooleanrequiredassigneeobject | nulloptionalChild fields (2)
idstringoptionalnamestring | nulloptional
unreadbooleanoptionallabelstring | nulloptionallast_customer_message_atstring | nulloptionallast_agent_message_atstring | nulloptionalreply_window_expires_atstring | nulloptionalAfter this, only an approved template can reach the customer (WhatsApp) or nothing until they write (Instagram / Messenger).
resolved_atstring | nulloptionalsnoozed_untilstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return3
- 403test_mode_unsupportedNot in test mode
- 422parameter_invalidInvalid parameter
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/conversations \
-H "Authorization: Bearer $API_KEY"A page of conversations.
{
"object": "list",
"data": [
{
"id": "conv_311",
"object": "conversation",
"channel": "whatsapp",
"customer": {
"contact_id": "string",
"address": "string",
"name": "string"
},
"number_id": "string",
"state": "bot",
"open": false,
"assignee": {
"id": "string",
"name": "string"
},
"unread": false,
"label": "string",
"last_customer_message_at": "2026-10-01T09:30:00Z",
"last_agent_message_at": "2026-10-01T09:30:00Z",
"reply_window_expires_at": "2026-10-01T09:30:00Z",
"resolved_at": "2026-10-01T09:30:00Z",
"snoozed_until": "2026-10-01T09:30:00Z",
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}
],
"has_more": false,
"next_cursor": "string"
}Get a conversation
https://api.saei.automize.sa/v1/conversations/{id}- Scope:
conversations:read - Live keys only
Path parameters
idstringrequiredThe object's id.
Response fields200· The conversation.
idstringrequiredobject"conversation"requiredchannelstringrequiredOne of
whatsappinstagrammessengercustomerobjectrequiredChild fields (3)
contact_idstring | nulloptionaladdressstringoptionalThe phone (E.164) on WhatsApp; the customer's id on Instagram / Messenger. Send replies
tothis.namestring | nulloptional
number_idstring | nulloptionalstatestringrequiredbotthe automation is answering;needs_agentwaiting for a person;assignedhanded to someone who has not replied yet;humana person is on it;snoozedparked untilsnoozed_until;resolvedclosed.One of
botneeds_agentassignedhumanresolvedsnoozedopenbooleanrequiredassigneeobject | nulloptionalChild fields (2)
idstringoptionalnamestring | nulloptional
unreadbooleanoptionallabelstring | nulloptionallast_customer_message_atstring | nulloptionallast_agent_message_atstring | nulloptionalreply_window_expires_atstring | nulloptionalAfter this, only an approved template can reach the customer (WhatsApp) or nothing until they write (Instagram / Messenger).
resolved_atstring | nulloptionalsnoozed_untilstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return3
- 403test_mode_unsupportedNot in test mode
- 404resource_missingNot found
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/conversations/conv_311 \
-H "Authorization: Bearer $API_KEY"The conversation.
{
"id": "conv_311",
"object": "conversation",
"channel": "whatsapp",
"customer": {
"contact_id": "ct_1052",
"address": "+966501234567",
"name": "سارة القحطاني"
},
"number_id": "num_3",
"state": "assigned",
"open": true,
"assignee": {
"id": "usr_41",
"name": "نورة العتيبي"
},
"unread": true,
"label": "شكوى",
"last_customer_message_at": "2026-10-01T09:29:10Z",
"last_agent_message_at": "2026-10-01T09:20:00Z",
"reply_window_expires_at": "2026-10-02T09:29:10Z",
"resolved_at": null,
"snoozed_until": null,
"created_at": "2026-09-28T14:00:00Z",
"updated_at": "2026-10-01T09:29:10Z"
}Assign a conversation
https://api.saei.automize.sa/v1/conversations/{id}/assign- Scope:
conversations:write - Live keys only
Hands the conversation to a team member. They must be able to see its number or account; viewers cannot be assigned.
Path parameters
idstringrequiredThe object's id.
Request body
member_idstringrequiredFrom
GET /v1/members.
Response fields200· The conversation, now assigned.
idstringrequiredobject"conversation"requiredchannelstringrequiredOne of
whatsappinstagrammessengercustomerobjectrequiredChild fields (3)
contact_idstring | nulloptionaladdressstringoptionalThe phone (E.164) on WhatsApp; the customer's id on Instagram / Messenger. Send replies
tothis.namestring | nulloptional
number_idstring | nulloptionalstatestringrequiredbotthe automation is answering;needs_agentwaiting for a person;assignedhanded to someone who has not replied yet;humana person is on it;snoozedparked untilsnoozed_until;resolvedclosed.One of
botneeds_agentassignedhumanresolvedsnoozedopenbooleanrequiredassigneeobject | nulloptionalChild fields (2)
idstringoptionalnamestring | nulloptional
unreadbooleanoptionallabelstring | nulloptionallast_customer_message_atstring | nulloptionallast_agent_message_atstring | nulloptionalreply_window_expires_atstring | nulloptionalAfter this, only an approved template can reach the customer (WhatsApp) or nothing until they write (Instagram / Messenger).
resolved_atstring | nulloptionalsnoozed_untilstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return6
- 403test_mode_unsupportedNot in test mode
- 422parameter_missingMissing parameter
- 404resource_missingNot found
- 409state_conflictNot allowed in the current state
- 422assignee_invalidMember cannot take this conversation
- 429rate_limitedToo many requests
Try it
curl -X POST https://api.saei.automize.sa/v1/conversations/conv_311/assign \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"member_id": "usr_41"
}'The conversation, now assigned.
{
"id": "conv_311",
"object": "conversation",
"channel": "whatsapp",
"customer": {
"contact_id": "string",
"address": "string",
"name": "string"
},
"number_id": "string",
"state": "bot",
"open": false,
"assignee": {
"id": "string",
"name": "string"
},
"unread": false,
"label": "string",
"last_customer_message_at": "2026-10-01T09:30:00Z",
"last_agent_message_at": "2026-10-01T09:30:00Z",
"reply_window_expires_at": "2026-10-01T09:30:00Z",
"resolved_at": "2026-10-01T09:30:00Z",
"snoozed_until": "2026-10-01T09:30:00Z",
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}List a conversation's messages
https://api.saei.automize.sa/v1/conversations/{id}/messages- Scope:
conversations:read - Live keys only
Every message in the thread, both directions, newest first. Internal notes between agents are never included.
Path parameters
idstringrequiredThe object's id.
Query parameters
limitintegeroptionalHow many objects to return, 1 to 100.
cursorstringoptionalThe
next_cursorfrom the previous page.
Response fields200· A page of messages.
object"list"requireddataarray<Message>requiredChild fields (28)
idstringrequiredUnique id. Opaque: store it as a string of up to 64 characters.
object"message"requiredlivemodebooleanrequireddirectionstringrequiredoutboundfor messages you send,inboundfor customer messages.One of
outboundinboundchannelstringrequiredOne of
whatsappinstagrammessengerfromstring | nulloptionalSender, in E.164 for WhatsApp.
tostring | nulloptionalRecipient, in E.164 for WhatsApp.
typestringrequiredWhat kind of content the message carries.
textobjectoptionalChild fields (1)
bodystringoptional
templateobjectoptionalChild fields (4)
namestringoptionallanguagestringoptionalvariablesobjectoptionalbodystringoptional
imageobjectoptionalMedia messages carry
link(ormedia_id),caption,filenameandmime_typewhen known.videoobjectoptionalaudioobjectoptionaldocumentobjectoptionalstickerobjectoptionallocationobjectoptionalcontactsarrayoptionalinteractiveobjectoptionalWhat you sent (
type,body,buttons…), or for a customer's tap,reply: {id, title}.reactionobjectoptionalstatusstringrequiredaccepted→sent→delivered→read, orfailed. Customer messages arereceived. Status changes arrive as webhook events.One of
acceptedsentdeliveredreadfailedreceivederrorobject | nulloptionalWhy delivery failed, when
statusisfailed.Child fields (3)
codestring | nulloptionaltitlestring | nulloptionalmessagestring | nulloptional
referencestring | nulloptionalYour own reference, echoed back from the send request and in every event.
conversation_idstring | nulloptionalprovider_message_idstring | nulloptionalWhatsApp's own message id (wamid).
contactobject | nulloptionalChild fields (1)
namestring | nulloptional
contextobject | nulloptionalFor a reply, the message being replied to.
Child fields (1)
provider_message_idstringoptional
created_atstring | nullrequiredupdated_atstring | nulloptional
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return3
- 403test_mode_unsupportedNot in test mode
- 404resource_missingNot found
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/conversations/conv_311/messages \
-H "Authorization: Bearer $API_KEY"A page of messages.
{
"object": "list",
"data": [
{
"id": "msg_48213",
"object": "message",
"livemode": false,
"direction": "outbound",
"channel": "whatsapp",
"from": "+966112345678",
"to": "+966501234567",
"type": "text",
"text": {
"body": "string"
},
"template": {
"name": "string",
"language": "string",
"variables": {},
"body": "string"
},
"image": {},
"video": {},
"audio": {},
"document": {},
"sticker": {},
"location": {},
"contacts": [],
"interactive": {},
"reaction": {},
"status": "accepted",
"error": {
"code": "string",
"title": "string",
"message": "string"
},
"reference": "string",
"conversation_id": "string",
"provider_message_id": "string",
"contact": {
"name": "string"
},
"context": {
"provider_message_id": "string"
},
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}
],
"has_more": false,
"next_cursor": "string"
}Reopen a conversation
https://api.saei.automize.sa/v1/conversations/{id}/reopen- Scope:
conversations:write - Live keys only
Reopens a resolved conversation, unassigned in the team queue, or assigned to member_id.
Path parameters
idstringrequiredThe object's id.
Request body
member_idstring | nulloptional
Response fields200· The reopened conversation.
idstringrequiredobject"conversation"requiredchannelstringrequiredOne of
whatsappinstagrammessengercustomerobjectrequiredChild fields (3)
contact_idstring | nulloptionaladdressstringoptionalThe phone (E.164) on WhatsApp; the customer's id on Instagram / Messenger. Send replies
tothis.namestring | nulloptional
number_idstring | nulloptionalstatestringrequiredbotthe automation is answering;needs_agentwaiting for a person;assignedhanded to someone who has not replied yet;humana person is on it;snoozedparked untilsnoozed_until;resolvedclosed.One of
botneeds_agentassignedhumanresolvedsnoozedopenbooleanrequiredassigneeobject | nulloptionalChild fields (2)
idstringoptionalnamestring | nulloptional
unreadbooleanoptionallabelstring | nulloptionallast_customer_message_atstring | nulloptionallast_agent_message_atstring | nulloptionalreply_window_expires_atstring | nulloptionalAfter this, only an approved template can reach the customer (WhatsApp) or nothing until they write (Instagram / Messenger).
resolved_atstring | nulloptionalsnoozed_untilstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return4
- 403test_mode_unsupportedNot in test mode
- 404resource_missingNot found
- 409state_conflictNot allowed in the current state
- 429rate_limitedToo many requests
Try it
curl -X POST https://api.saei.automize.sa/v1/conversations/conv_311/reopen \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"member_id": "usr_41"
}'The reopened conversation.
{
"id": "conv_311",
"object": "conversation",
"channel": "whatsapp",
"customer": {
"contact_id": "string",
"address": "string",
"name": "string"
},
"number_id": "string",
"state": "bot",
"open": false,
"assignee": {
"id": "string",
"name": "string"
},
"unread": false,
"label": "string",
"last_customer_message_at": "2026-10-01T09:30:00Z",
"last_agent_message_at": "2026-10-01T09:30:00Z",
"reply_window_expires_at": "2026-10-01T09:30:00Z",
"resolved_at": "2026-10-01T09:30:00Z",
"snoozed_until": "2026-10-01T09:30:00Z",
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}Resolve a conversation
https://api.saei.automize.sa/v1/conversations/{id}/resolve- Scope:
conversations:write - Live keys only
Closes the conversation. If the customer writes again it reopens by itself, and you get conversation.reopened.
Path parameters
idstringrequiredThe object's id.
Response fields200· The resolved conversation.
idstringrequiredobject"conversation"requiredchannelstringrequiredOne of
whatsappinstagrammessengercustomerobjectrequiredChild fields (3)
contact_idstring | nulloptionaladdressstringoptionalThe phone (E.164) on WhatsApp; the customer's id on Instagram / Messenger. Send replies
tothis.namestring | nulloptional
number_idstring | nulloptionalstatestringrequiredbotthe automation is answering;needs_agentwaiting for a person;assignedhanded to someone who has not replied yet;humana person is on it;snoozedparked untilsnoozed_until;resolvedclosed.One of
botneeds_agentassignedhumanresolvedsnoozedopenbooleanrequiredassigneeobject | nulloptionalChild fields (2)
idstringoptionalnamestring | nulloptional
unreadbooleanoptionallabelstring | nulloptionallast_customer_message_atstring | nulloptionallast_agent_message_atstring | nulloptionalreply_window_expires_atstring | nulloptionalAfter this, only an approved template can reach the customer (WhatsApp) or nothing until they write (Instagram / Messenger).
resolved_atstring | nulloptionalsnoozed_untilstring | nulloptionalcreated_atstring | nulloptionalupdated_atstring | nulloptional
Errors this can return4
- 403test_mode_unsupportedNot in test mode
- 404resource_missingNot found
- 409state_conflictNot allowed in the current state
- 429rate_limitedToo many requests
Try it
curl -X POST https://api.saei.automize.sa/v1/conversations/conv_311/resolve \
-H "Authorization: Bearer $API_KEY"The resolved conversation.
{
"id": "conv_311",
"object": "conversation",
"channel": "whatsapp",
"customer": {
"contact_id": "string",
"address": "string",
"name": "string"
},
"number_id": "string",
"state": "bot",
"open": false,
"assignee": {
"id": "string",
"name": "string"
},
"unread": false,
"label": "string",
"last_customer_message_at": "2026-10-01T09:30:00Z",
"last_agent_message_at": "2026-10-01T09:30:00Z",
"reply_window_expires_at": "2026-10-01T09:30:00Z",
"resolved_at": "2026-10-01T09:30:00Z",
"snoozed_until": "2026-10-01T09:30:00Z",
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z"
}List team members
https://api.saei.automize.sa/v1/members- Scope:
conversations:read - Works in test mode
The people in this workspace, to assign conversations to. Viewers can read the inbox but cannot be assigned.
Query parameters
rolestringoptionalOne of
owneradmineditorviewercustomer_service
Response fields200· Every member.
object"list"requireddataarray<Member>requiredChild fields (5)
idstringrequiredobject"member"requirednamestring | nulloptionalemailstring | nulloptionalrolestringrequiredOne of
owneradmineditorviewercustomer_service
has_morebooleanrequirednext_cursorstring | nullrequired
Errors this can return2
- 422parameter_invalidInvalid parameter
- 429rate_limitedToo many requests
Try it
curl -X GET https://api.saei.automize.sa/v1/members \
-H "Authorization: Bearer $API_KEY"Every member.
{
"object": "list",
"data": [
{
"id": "usr_41",
"object": "member",
"name": "نورة العتيبي",
"email": "noura@example.com",
"role": "customer_service"
}
],
"has_more": false,
"next_cursor": null
}