Conversations
22 endpoints in this family.
List the labels of the inbox
GET/api/v1/inbox/categories
Key role admin or above
Labels are how threads are actually sorted — more than the open/closed state. A label can also keep its threads out of the queue (skipProcedure); what the AI collaborator does lives on the procedure each thread follows.
Response
The labels, with their name and colour.
data.itemsobject[]The labels.
Show fields
keystringWhat
categoryholds on a conversation.namestringIts name.
colorstringIts colour.
skipProcedurebooleanThe procedure skips these threads: out of the queue at reception.
data.countsobjectConversations per label key over the last 30 days.
curl https://coplace.io/api/v1/inbox/categories \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "items": [ { "key": "…", "name": "…", "color": "…", "skipProcedure": true } ], "counts": {} }}List conversations
GET/api/v1/inbox/conversations
Returns conversations, most recently active first, with a cursor for the next page.
Filters combine. folder picks the view (default inbox); mine and starred are personal and refused for a key (422 personal_folder) — a key is not a person. Trial conversations are excluded unless folder=trials or sandbox says otherwise. Counts per folder, label and channel: GET /inbox/overview.
Query parameters
limitintegerHow many to return, 100 at most. Defaults to 50.
cursorstringOpaque cursor from the previous page. Omit for the first page.
folderstringThe view. Defaults to
inbox.inboxmissionswaitingsentdonespamtrialsallboxstringOnly conversations on this channel id (
GET /inbox/channels).labelstringOnly conversations filed under this label key (
GET /inbox/categories).agentstringOnly conversations of this AI collaborator (its id).
qstringSearch in message text, contact name, phone or email, reference and subject.
externalIdstringOnly conversations linked to this record of your software (
link.externalId), exact. Usefolder=allto include closed ones.referencestringOnly conversations whose reference or link label equals this, case-insensitive.
emailstringOnly conversations of the contact holding this email address, exact.
phonestringOnly conversations of the contact holding this phone number (any format; digits are compared).
sandboxstringTrial conversations: leave them out, show only them, or show all.
excludeonlyall
Response
A page of conversations and the cursor for the next one.
data.itemsConversation[]The conversations, most recent activity first.
data.nextCursorstringPass it as
cursorfor the next page;nullat the end.data.hasMorebooleanWhether another page exists.
data.totalintegerHow many match, on the first page only;
nullafter.
curl https://coplace.io/api/v1/inbox/conversations \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "items": [ {} ], "nextCursor": "…", "hasMore": true, "total": 0 }}Write first to someone who has not written yet
POST/api/v1/inbox/conversations
Key role agent or above
Opens a conversation and sends the first message. On WhatsApp, if that person already wrote in the past, their existing thread is reused — one thread per person and channel.
On email, each call opens a new thread (a thread is a subject). To add to an existing thread, pass its id as threadId (find it with GET /inbox/conversations?externalId=…&folder=all) or use POST /inbox/conversations/{id}/messages.
On WhatsApp, only an approved template can be sent here. The 24-hour service window is closed by definition when nobody has written to you. This is Meta's rule, not ours: free text would be rejected by the gateway after letting you believe it had been sent. Pass templateId and its variables.
On email, send text and subject instead — or html for a formatted body (bold, italics, lists, quotes, links; anything else is removed). Attachments: attachments lists files your software hosts (fetched by Coplace), and/or one file rides along when the call is multipart/form-data: the JSON body in a payload field and the file in file (4 MB at most).
With queue: true the call returns at once (HTTP 202) and the message leaves within a minute.
Body
channelIdstringrequiredWhich number or mailbox to speak from. See
GET /inbox/channels.tostringrequiredPhone number in E.164 form, or an email address.
idempotencyKeystringrequiredYour own key, 8 to 200 characters. Sending twice with the same key sends once and returns the first message (
duplicate: true) — even if the body differs.templateIdstringWhatsApp: the approved template to send. This or
templateNameis required there.templateNamestringWhatsApp: the template, by its name at Meta, instead of
templateId.templateLanguagestringWith
templateName: its language code. Defaultfr.variablesobjectWhatsApp: the values filling the template placeholders — by number for
{{1}}, by name for{{client_name}}:{ "1": "Karim" }or{ "client_name": "Karim" }.buttonsarrayWhatsApp: the values of the template's dynamic buttons:
{ index, type, … }—indexis the button's position in the template (from 0),typeisurl(withtext, the link suffix filling{{1}}),quick_reply(withpayload) orcopy_code(withcode, 15 characters at most). A link button with{{1}}and a copy-code button must be given.textstringEmail: the body, as plain text.
htmlstringEmail: the body as HTML. From an API key, a full layout is kept — tables, inline styles,
httpsimages (no<style>block, no script). From the console, only bold, italics, lists, quotes and links. Cleaned on arrival;textis then derived from it.withSignaturebooleanEmail:
falseleaves the mailbox signature off this message. Default true.subjectstringEmail: the subject line.
threadIdstringEmail: add this message to that existing thread instead of opening a new one. It must be a thread of this channel with the same contact.
ccstring[]Email only: addresses in copy, visible to the recipient. At most 10.
bccstring[]Email only: addresses in hidden copy.
attachmentsobject[]Email only: up to 5 files your software hosts, fetched by Coplace (public addresses only, 4 MB each, 10 MB in all). A file that cannot be read refuses the whole email (nothing is sent). Sent files are kept in the thread: they come back in the message
attachments. The call is synchronous — the files are fetched, then the email sent — so it cannot be combined withqueue.Show fields
urlstringrequiredWhere to fetch it,
https://.namestringThe file name shown to the recipient. Defaults to the end of the address.
mimestringIts type, when the host serves a generic one (
application/pdf).
queuebooleanReturn at once and send within a minute (HTTP 202). Default false.
linkobjectTies the thread to a record in your system, so you can find it back by
GET /inbox/conversations?externalId=…. A link set by hand in the console is never replaced.Show fields
externalIdstringrequiredYour identifier for the record — the booking id.
labelstringThe reference the customer quotes — the booking reference. Matched case-insensitively.
Response
The message as stored, its delivery status, and the id of the conversation it belongs to.
data.messageMessagedata.duplicatebooleantruewhen thisidempotencyKeywas already used: the message returned is the first one, nothing was sent again.data.conversationIdstringThe conversation it belongs to — new or reused.
Refusals
- 409
template_requiredWhatsApp: a first message must be an approved template. - 409
consent_missingA marketing template to a contact who opted out. - 422
template_holes_unfilledA placeholder has no value; `data.issues` lists them. - 422
template_buttons_invalidA button value is missing or does not match the template's buttons; the message says which. - 413
file_too_largeAn attachment is over 4 MB, or they total over 10 MB. - 422
not_email`html`, `cc`, `bcc`, `attachments` and `threadId` only exist on email. - 422
invalid_recipient`to` is not a readable email address or an international number (WhatsApp), or an address in `cc` or `bcc` is unreadable, or there are more than 10. - 422
invalid_attachmentAn attachment has no `url`, or there are more than 5. - 422
attachment_unreachableAn attachment address could not be read; `data.url` names it. - 422
invalid_thread`threadId` is not a thread of this channel with this contact. - 415
file_type_refusedThat type of file is not accepted. - 422
attachment_unsupportedWhatsApp: a first message is a template, without attachment. - 422
invalid_link`link` is not an object, or has no `externalId`. - 422
idempotency_key_requiredThe idempotency key is missing or outside 8-200 characters. - 409
idempotency_key_conflictTwo calls with the same key crossed at the same instant; retry, the first message comes back.
curl -X POST https://coplace.io/api/v1/inbox/conversations \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "channelId": "…", "to": "+33612345678", "idempotencyKey": "…", "templateLanguage": "fr" }'{ "data": { "message": { "id": "…", "conversationId": "…", "channelType": "whatsapp", "direction": "inbound", "sender": "contact", "senderName": "…", "apiKeyId": "…", "type": "…", "textContent": "…", "transcript": "…", "mediaUrl": "…", "subject": "…", "status": "queued", "providerMessageId": "…", "error": "…", "form": {}, "reply": {}, "location": {}, "createdAt": "…" }, "duplicate": true, "conversationId": "…" }}Get one conversation
GET/api/v1/inbox/conversations/{id}
Returns the conversation with its contact, channel, status, labels, and whether the AI collaborator is answering on it.
Path parameters
idstringThe conversation id.
Response
The conversation.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl https://coplace.io/api/v1/inbox/conversations/<id> \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Let the AI collaborator answer this thread, or stop it
POST/api/v1/inbox/conversations/{id}/ai
Key role agent or above
This is how you choose who replies. Set enabled: false and Coplace's collaborator goes quiet on this conversation: every message still reaches you by webhook, and your software answers. Set it back to true to hand the thread over again.
The setting touches this conversation only — not the collaborator, not the channel, not other threads.
Path parameters
idstringThe conversation id.
Body
enabledbooleanrequiredTrue: the collaborator answers. False: it stays silent and you answer.
Response
The conversation, with the collaborator on or off.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/ai \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Hand a conversation to someone
POST/api/v1/inbox/conversations/{id}/assign
Key role agent or above
Assigns the thread to a member of the workspace. An API key must name the person — it has no "me" to assign to — either with userId, or with the X-Coplace-Acting-User header (a member id or email), in which case an empty body means "that person takes it". Get the candidates from GET /inbox/members.
Path parameters
idstringThe conversation id.
Body
userIdstringThe workspace member who takes it over;
nullhands it back. Optional withX-Coplace-Acting-User.
Response
The conversation, assigned.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
Refusals
- 422
assignee_requiredNo target given, and `X-Coplace-Acting-User` is absent or not an active member who answers customers. A key cannot assign a thread to itself.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/assign \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "…" }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Unblock the contact of a conversation
DEL/api/v1/inbox/conversations/{id}/block
Key role agent or above
The contact's threads leave the spam folder and its next messages are received normally.
Path parameters
idstringThe conversation id.
Response
The conversation, its contact unblocked.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X DELETE https://coplace.io/api/v1/inbox/conversations/<id>/block \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Block the contact of a conversation
POST/api/v1/inbox/conversations/{id}/block
Key role agent or above
Moves every thread of the contact to the spam folder and drops its next messages on arrival, without any answer. Nothing is deleted: DELETE undoes it.
Path parameters
idstringThe conversation id.
Body
reasonstringWhy, 300 characters at most.
Response
The conversation, its contact blocked.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/block \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "…" }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Clear the label of a conversation
DEL/api/v1/inbox/conversations/{id}/category
Key role agent or above
Removes the label and lifts the lock: the AI collaborator may file the thread again.
Path parameters
idstringThe conversation id.
Response
The conversation, without label.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X DELETE https://coplace.io/api/v1/inbox/conversations/<id>/category \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Put a conversation in a queue
POST/api/v1/inbox/conversations/{id}/category
Key role agent or above
Files the thread under one of the workspace labels (GET /inbox/categories), or under none with category: null. A human filing locks the label: the AI collaborator can no longer move it (DELETE lifts the lock).
Path parameters
idstringThe conversation id.
Body
categorystringrequiredThe label key, or
nullfor no queue.alwaysbooleanAlso file this sender's next messages there. Needs a person: ignored without
X-Coplace-Acting-User.
Response
The conversation, filed.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
Refusals
- 422
invalid_categoryThe label does not exist in the workspace.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/category \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "category": "…" }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Detach the record of a conversation
DEL/api/v1/inbox/conversations/{id}/link
Key role agent or above
Clears the link and lifts its lock. Nothing is deleted in your software.
Path parameters
idstringThe conversation id.
Response
The conversation, unlinked.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X DELETE https://coplace.io/api/v1/inbox/conversations/<id>/link \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Attach a record to a conversation
POST/api/v1/inbox/conversations/{id}/link
Key role agent or above
Attaches the record of your software (a booking, an order) to an existing thread. It locks the link: no automatic rule replaces it afterwards. To link a thread at the moment you open it, pass link to POST /inbox/conversations instead. Find it back with GET /inbox/conversations?externalId=….
Path parameters
idstringThe conversation id.
Body
externalIdstringrequiredYour identifier for the record — the booking id.
labelstringThe reference the customer quotes — the booking reference.
urlstringA link to the record,
http://orhttps://.payloadobjectA display copy of the record, 64 KB at most. Never the source of truth.
Response
The conversation, linked.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/link \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "externalId": "…" }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Send a file in a conversation
POST/api/v1/inbox/conversations/{id}/media
Key role agent or above
Uploads an image, video, audio, document or voice note and sends it. Send it as multipart/form-data.
The 24-hour window applies as it does to text. Files are at most 4 MB; Coplace keeps its own copy so it stays readable after WhatsApp deletes theirs.
Path parameters
idstringThe conversation id.
Body
filestringrequiredThe file itself, as a multipart part.
idempotencyKeystringrequiredYour own key, 8 to 200 characters.
captionstringA caption shown under the file. WhatsApp shows none under audio.
voicebooleanTrue to send audio as a voice note, with its waveform.
Response
The message as stored, with its delivery status.
data.messageMessagedata.duplicatebooleantruewhen thisidempotencyKeywas already used: the message returned is the first one, nothing was sent again.
Refusals
- 409
window_closedMore than 24 hours since the customer last wrote. - 422
caption_unsupportedWhatsApp shows no caption under audio — send the text separately.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/media \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "file": "…", "idempotencyKey": "…" }'{ "data": { "message": {}, "duplicate": true }}List the messages of a conversation
GET/api/v1/inbox/conversations/{id}/messages
Returns messages oldest first; paging walks back into the past.
An email, received or sent, whose layout was kept carries hasHtml: true; fetch the HTML separately with GET /inbox/messages/{id}/html — it is never inlined in the thread.
Path parameters
idstringThe conversation id.
Query parameters
limitintegerHow many messages to return.
cursorstringThe
nextCursorof the previous page, to go further back.sincestringDelta mode: an ISO date or an epoch (seconds or milliseconds). Returns what arrived after it, plus the outbound messages of the last 7 days not yet
readorfailed, so their ticks refresh. Merge byid; use the newestcreatedAtyou hold as the nextsince.hasMore: truemeans more thanlimitchanged: raiselimit.cursoris ignored.
Response
A page of messages.
data.itemsMessage[]The messages, oldest first.
data.nextCursorstringPass it as
cursorto go further back;nullat the start of the thread.data.hasMorebooleanWhether older messages exist.
curl https://coplace.io/api/v1/inbox/conversations/<id>/messages \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "items": [ {} ], "nextCursor": "…", "hasMore": true }}Reply in a conversation
POST/api/v1/inbox/conversations/{id}/messages
Key role agent or above
Sends free text, quick-reply buttons, a list, or a location request.
The 24-hour window is enforced here. On WhatsApp you may only send free text within 24 hours of the customer's last message. Outside it you get window_closed and must send an approved template instead (POST /inbox/conversations/{id}/template). Interactive forms count as free text for Meta — they are refused outside the window too.
The message is attributed to your key: the conversation shows the key's label, never a person who did nothing.
With queue: true the call returns at once with the message queued (HTTP 202) and it leaves within a minute; follow it with the message.sent / message.failed webhooks. Use it when you send many messages and do not want to wait for each round trip to WhatsApp.
Path parameters
idstringThe conversation id.
Body
textstringWhat to say, as plain text. Also the readable body when you send a form. Required unless
htmlis given.htmlstringEmail: the body as HTML. From an API key, a full layout is kept — tables, inline styles,
httpsimages (no<style>block, no script). From the console, only bold, italics, lists, quotes and links. Cleaned on arrival;textis then derived from it.withSignaturebooleanEmail only:
falseleaves the mailbox signature off this message. Default true.subjectstringEmail only: the subject line. Defaults to the thread subject.
idempotencyKeystringrequiredYour own key, 8 to 200 characters. Sending twice with the same key sends once.
formobjectAn interactive form, WhatsApp only: up to 3 buttons, a list of up to 10 rows, or a location request.
Show fields
kindstringrequiredWhich form.
buttonslistlocation_requestbodystringThe text above the form, 1024 characters at most. Defaults to
text.headerstringA line above the body, 60 characters at most.
footerstringA line below the body, 60 characters at most.
buttonsobject[]For
buttons: 1 to 3. The reply you receive carries the chosenid.Show fields
idstringYour identifier, returned when tapped.
titlestringrequired20 characters at most.
buttonLabelstringFor
list: the label of the button that opens it, 20 characters at most.sectionsobject[]For
list: sections of rows, 10 rows in all.Show fields
titlestringThe section title.
rowsobject[]Its rows.
Show fields
idstringYour identifier, returned when chosen.
titlestringrequired24 characters at most.
descriptionstring72 characters at most.
replyToIdstringQuote an earlier message of this thread.
ccstring[]Email only: addresses in copy, visible to the recipient. At most 10.
bccstring[]Email only: addresses in hidden copy.
attachmentsobject[]Email only: up to 5 files your software hosts, fetched by Coplace (public addresses only, 4 MB each, 10 MB in all). A file that cannot be read refuses the whole email (nothing is sent). Sent files are kept in the thread: they come back in the message
attachments. The call is synchronous — the files are fetched, then the email sent — so it cannot be combined withqueue.Show fields
urlstringrequiredWhere to fetch it,
https://.namestringThe file name shown to the recipient. Defaults to the end of the address.
mimestringIts type, when the host serves a generic one (
application/pdf).
queuebooleanReturn at once and send within a minute (HTTP 202). Default false.
Response
The message as stored, with its delivery status.
data.messageMessagedata.duplicatebooleantruewhen thisidempotencyKeywas already used: the message returned is the first one, nothing was sent again.
Refusals
- 409
window_closedMore than 24 hours since the customer last wrote. Send an approved template instead. - 422
no_recipientThis contact has no usable phone number or email address. - 422
idempotency_key_requiredThe idempotency key is missing or outside 8-200 characters. - 422
invalid_formThe form breaks a WhatsApp limit; `detail` says which. - 422
not_whatsappForms only exist on WhatsApp. - 422
not_email`html`, `cc`, `bcc` and `attachments` only exist on email. - 422
invalid_recipientAn address in `cc` or `bcc` is unreadable, or there are more than 10. - 422
invalid_attachmentAn attachment has no `url`, or there are more than 5. - 422
attachment_unreachableAn attachment address could not be read; `data.url` names it. - 413
file_too_largeAn attachment is over 4 MB, or they total over 10 MB. - 415
file_type_refusedAn attachment type is not accepted.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/messages \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "idempotencyKey": "…" }'{ "data": { "message": {}, "duplicate": true }}Flag a conversation as needing a person
POST/api/v1/inbox/conversations/{id}/needs-human
Key role agent or above
Raises the thread in the Coplace inbox so an advisor picks it up, and silences the AI collaborator on it. Use it when your software decides it cannot handle a case on its own. false clears the flag but does not wake the collaborator (POST /inbox/conversations/{id}/ai).
Path parameters
idstringThe conversation id.
Body
needsHumanbooleanrequiredtruecalls a person (the AI collaborator goes quiet on this thread);falsesays it is handled.
Response
The conversation, flagged.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
Refusals
- 422
invalid_request`needsHuman` is missing or not a boolean.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/needs-human \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "needsHuman": true }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Mark a conversation as read
POST/api/v1/inbox/conversations/{id}/read
Key role agent or above
Clears the unread count. On WhatsApp this also sends a read receipt to the customer — their two ticks turn blue — for the last message they sent.
Path parameters
idstringThe conversation id.
Response
The conversation, with its unread count back to zero.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/read \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Change the state of a conversation
POST/api/v1/inbox/conversations/{id}/status
Key role agent or above
Moves a conversation between open, pending and closed. Closing does not stop anything: a new message from the customer reopens the thread by itself.
Path parameters
idstringThe conversation id.
Body
statusstringrequiredThe new state.
openpendingclosed
Response
The conversation in its new state.
data.idstringThe conversation id.
data.channelIdstringThe channel it lives on.
data.channelTypestringThe kind of channel.
whatsappemaildata.channelNamestringThe channel's name in Coplace.
data.statusstringWhere it stands.
openpendingcloseddata.subjectstringEmail subject;
nullelsewhere.data.categorystringThe label key it is filed under, or
null.data.aiEnabledbooleanWhether the AI collaborator may answer in this conversation.
data.needsHumanbooleanSomeone was asked to take over.
data.assignedUserIdstringThe member it is assigned to, or
null.data.agentNamestringThe collaborator's name on this conversation, or
null.data.contactobjectWho you are talking to.
Show fields
idstringThe contact id.
displayNamestringTheir name, or
null.identitystringTheir phone number (WhatsApp) or email address.
identityKindstringWhat
identityis.phoneemailexternalblockedbooleanBlocked contacts are kept out of the inbox.
data.windowobjectThe WhatsApp 24-hour customer service window.
Show fields
appliesbooleanfalseoutside WhatsApp.openbooleanWhether free text can be sent now. Always
truewhen the rule does not apply.expiresAtstringWhen it closes, ISO 8601, or
null.minutesLeftintegerMinutes left,
0when closed,nullwhen the rule does not apply.
data.unreadCountintegerMessages from the contact not yet read by your team.
data.lastMessageAtstringISO 8601, or
null.data.lastInboundAtstringWhen the contact last wrote, ISO 8601. This opens the 24-hour window.
data.createdAtstringISO 8601.
data.lastMessageobjectThe latest message, or
null.Show fields
idstringThe message id.
directionstringFrom the contact, or to them.
inboundoutboundtextContentstringIts text.
statusstringIts delivery status.
createdAtstringISO 8601.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/status \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "open" }'{ "data": { "id": "…", "channelId": "…", "channelType": "whatsapp", "channelName": "…", "status": "open", "subject": "…", "category": "…", "aiEnabled": true, "needsHuman": true, "assignedUserId": "…", "agentName": "…", "contact": { "id": "…", "displayName": "…", "identity": "…", "identityKind": "phone", "blocked": true }, "window": { "applies": true, "open": true, "expiresAt": "…", "minutesLeft": 0 }, "unreadCount": 0, "lastMessageAt": "…", "lastInboundAt": "…", "createdAt": "…", "lastMessage": { "id": "…", "direction": "inbound", "textContent": "…", "status": "…", "createdAt": "…" } }}Send an approved template
POST/api/v1/inbox/conversations/{id}/template
Key role agent or above
The only thing that reaches a WhatsApp customer outside the 24-hour window. A template is text Meta reviewed and approved in advance; its placeholders are filled at send time.
List what is available with GET /templates. A template that is not yet approved is refused.
A marketing template is refused for a contact who opted out — on WhatsApp by tapping "Stop", or through PATCH /contacts/{id} — with consent_missing.
With queue: true the call returns at once (HTTP 202) and the message leaves within a minute.
Path parameters
idstringThe conversation id.
Body
templateIdstringrequiredThe approved template to send.
variablesobjectThe values filling its placeholders: by number for
{{1}}({ "1": "Karim" }), by name for{{client_name}}({ "client_name": "Karim" }). A named placeholder left out takes the field of the same name from the record linked to the conversation.buttonsarrayWhatsApp: the values of the template's dynamic buttons:
{ index, type, … }—indexis the button's position in the template (from 0),typeisurl(withtext, the link suffix filling{{1}}),quick_reply(withpayload) orcopy_code(withcode, 15 characters at most). A link button with{{1}}and a copy-code button must be given.idempotencyKeystringrequiredYour own key, 8 to 200 characters.
queuebooleanReturn at once and send within a minute (HTTP 202). Default false.
Response
The message as stored, with the rendered text and its delivery status.
data.messageMessagedata.duplicatebooleantruewhen thisidempotencyKeywas already used: the message returned is the first one, nothing was sent again.
Refusals
- 409
template_not_applicableTemplates only exist on WhatsApp. - 409
consent_missingA marketing template to a contact who opted out. - 422
template_not_approvedThe template is not approved by Meta yet. - 422
template_holes_unfilledA placeholder has no value; `data.issues` lists them. - 422
template_buttons_invalidA button value is missing or does not match the template's buttons; the message says which.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/template \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "templateId": "…", "idempotencyKey": "…" }'{ "data": { "message": {}, "duplicate": true }}Show "typing…" to the customer
POST/api/v1/inbox/conversations/{id}/typing
Key role agent or above
Shows the typing indicator in the customer's WhatsApp while your software prepares the answer. It disappears when your message arrives, or after 25 seconds — call it again for a longer wait.
WhatsApp ties it to the read receipt: the customer's last message also turns blue. Nothing changes in Coplace.
Path parameters
idstringThe conversation id.
Response
Whether the indicator was shown.
data.shownbooleanfalsewhen the customer has not written yet: there is nothing to attach it to.
Refusals
- 422
not_whatsappOnly WhatsApp has a typing indicator. - 502
upstream_errorWhatsApp refused it; `detail` carries its reason.
curl -X POST https://coplace.io/api/v1/inbox/conversations/<id>/typing \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "shown": true }}List the people who can take a conversation
GET/api/v1/inbox/members
Returns the active members of the workspace, to be used as the target of an assignment. A key sees every member: it belongs to no team.
Response
The members, with their id, name and role.
data.itemsMember[]The members.
curl https://coplace.io/api/v1/inbox/members \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "items": [ {} ] }}Count the folders, labels and mailboxes
GET/api/v1/inbox/overview
The numbers of the inbox sidebar in one call: how many threads and how many unread per folder, per label, and per channel (boxes, joined to GET /inbox/channels by channelId — group by channel type for a per-network total).
Each count is exactly what the same folder returns in GET /inbox/conversations. Trials and blocked contacts never count. mine and starred are personal: a key has no "me", they are 0.
Response
The counts by folder, label and channel.
data.foldersobjectCounts per folder.
Show fields
inboxobjectOpen threads of the folder.
Show fields
totalintegerHow many threads.
unreadintegerHow many have unread messages.
mineobjectOpen threads of the folder.
Show fields
totalintegerHow many threads.
unreadintegerHow many have unread messages.
missionsobjectOpen threads of the folder.
Show fields
totalintegerHow many threads.
unreadintegerHow many have unread messages.
waitingobjectOpen threads of the folder.
Show fields
totalintegerHow many threads.
unreadintegerHow many have unread messages.
starredobjectOpen threads of the folder.
Show fields
totalintegerHow many threads.
unreadintegerHow many have unread messages.
data.labelsobject[]The labels, with their counts.
Show fields
keystringThe label key.
namestringIts display name.
unreadintegerOpen threads with unread messages.
recentintegerThreads active in the last 30 days.
data.boxesobject[]Unread open threads per channel.
Show fields
channelIdstringThe channel id.
unreadintegerOpen threads with unread messages.
curl https://coplace.io/api/v1/inbox/overview \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "folders": { "inbox": { "total": 0, "unread": 0 }, "mine": { "total": 0, "unread": 0 }, "missions": { "total": 0, "unread": 0 }, "waiting": { "total": 0, "unread": 0 }, "starred": { "total": 0, "unread": 0 } }, "labels": [ { "key": "…", "name": "…", "unread": 0, "recent": 0 } ], "boxes": [ { "channelId": "…", "unread": 0 } ] }}