📌 O que essa funcionalidade permite?
Essa API permite que você crie um ticket no Cloud Chat a partir de qualquer sistema externo, como:
-
Um sistema de telefonia (ex: quando uma ligação chega)
-
Um formulário preenchido no seu site
-
Uma integração com CRM, ERP ou qualquer ferramenta personalizada
Ao usar essa rota, você pode:
-
Criar um novo ticket com status em aberto, pendente, ou fechado
-
Associar o ticket a um contato via e-mail, telefone ou identificador
-
Incluir uma mensagem inicial (inbound ou outbound)
-
Definir atributos customizados da conversa no momento da criação
🧭 Quando usar essa API?
Use quando for necessário iniciar uma conversa no Cloud Chat sem que o cliente tenha mandado uma mensagem por um canal ativo.
Exemplos:
-
Recebeu uma ligação fora do Cloud Chat? → Gere um ticket com o resumo da chamada.
-
Alguém preencheu um formulário? → Crie o ticket automaticamente e inicie a tratativa por e-mail.
-
Quer centralizar comunicações que vêm de outras fontes? → Use essa API como ponto de entrada.
Pré‑requisitos
-
api_access_tokenválido do usuário (ou agent bot), com acesso à conta -
ACCOUNT_IDeINBOX_IDda mesma conta -
Para alguns canais, a Inbox precisa estar com "Criar conversa via API" habilitado
-
Para canal E‑mail: existir o vínculo
ContactInboxentre o contato e a Inbox comsource_idcorreto

🔗 Endpoint
POST https://{{CLOUDCHAT_DOMAIN}}/api/v1/accounts/{{ACCOUNT_ID}}/conversations
🔐 Headers obrigatórios
{
"content-type": "application/json",
"api_access_token": "SEU_TOKEN_DE_API"
}
🧾 Corpo da requisição
{
"inbox_id": "1",
"contact_identifier": "id_123",
"contact_email": "[email protected]",
"contact_phone_number": "+12345",
"message": {
"content": "Olá, acabei de preencher o formulário no site e preciso de ajuda.",
"message_type": "incoming"
},
"status": "open", // Optional
"private": false, // Optional
"custom_attributes": { // Optional
"example1": "valueXPTO"
},
"additional_attributes": { // optional
"mail_subject": "Protocolo de atendimento ABCD"
},
"assignee_id": "1" // optional
}
Como definir source_id por tipo de canal
-
Canal E‑mail (
Channel::Email): o e‑mail do contato (ex.:[email protected]) -
Canal Telefone (Twilio/WhatsApp): número em formato E.164 (ex.:
+5511999998888) -
Canal Website (
Channel::WebWidget): identificador gerado pelo Chatwoot (obtido via webhooks/contactable inboxes) -
Canal API (
Channel::Api): qualquer string estável única (ex.:SHEET-<sheetId>-ROW-<row>,TICKET-12345)
🧠 Explicação dos campos principais
inbox_id: Identificador da Inbox que pode ser obtido da barra do navegador (URI/rota) ao acessar a configuração de caixa de entrada.
assignee_id(opcional): Identificador do agente que será atribuído no momento da criação.
Para referenciar o contato envie um dos três campos abaixo:
-
contact_identifier: Identificador único do contato -
contact_email: Email do contato -
contact_phone_number: Número do contato
message: A mensagem contendo seus campos:
-
content: que é o conteúdo da mensagem
-
message_type:
-
"incoming": mensagem vinda do cliente
-
"outgoing": enviada pelo agente
-
"activity": nota interna
-
-
private: se a mensagem é visível ao cliente (false) ou interna (true)
additional_attributes -> mail_subject (opcional)
Caso o ticket seja tratado via canal de email, você pode utilizar esse campo para customizar o assunto no email enviado ao contato quando a conversa se iniciar.
custom_attributes (opcional, mas poderoso)
Você pode adicionar qualquer campo customizado de conversa, já existente na sua configuração, direto aqui. Para saber como criar atributos customizados, veja essa FAQ.
🎯 O ticket já nasce como “em aberto”?
Sim. O ticket será criado com status “open” por padrão, a menos que seja informado o campo status na requisição, o que o torna visível e pronto para atendimento imediato na caixa de entrada (inbox) especificada.
🧪 Como testar?
-
Acesse seu api_access_token no painel de configurações
-
Copie o ACCOUNT_ID, INBOX_ID e CLOUDCHAT_DOMAIN conforme descrito nesta FAQ de import
-
Envie a requisição via Postman ou script
-
Verifique no Cloud Chat se o ticket apareceu na Inbox correta, com as informações completas
⚠️ Erros Comuns
Uso incorreto de identificadores únicos
Os campos identifier, phone_number e email são atributos únicos do contato. Não devem ser fixados em requisições de criação de tickets.
Como a request utiliza upsert, caso sejam fixados, o resultado será sempre um único contato sendo atualizado a cada chamada, com todas as conversas vinculadas a ele.
Criação de Ticket não cria contato
A criação manual de tickets via API não gera novos contatos. O sistema apenas utiliza contatos já existentes.
Portanto, se o contato não existir, é necessário criá-lo previamente antes de iniciar uma conversa. Crie seguindo esta FAQ

Fluxo exemplo para criar um E-mail com mensagem do usuário
- Garantir/obter o contato
-
Buscar por e‑mail/telefone/identificador:
GET
/api/v1/accounts/{account_id}/contacts/search?q={chave} -
Criar contato caso não exista:
POST
/api/v1/accounts/{account_id}/contacts
- Vincular o contato à Inbox (ContactInbox)
-
POST
/api/v1/accounts/{account_id}/contacts/{id}/contact_inboxes -
Body:
{ "inbox_id": "INBOX_ID", "source_id": "<conforme canal>" }
- Criar a conversa (sem mensagem inicial, se quiser registrar como cliente depois)
-
POST
/api/v1/accounts/{account_id}/conversations -
Body mínimo:
{ "source_id": "<...>", "inbox_id": "INBOX_ID", "status": "open" }
- Postar mensagem como cliente (incoming)
-
POST
/api/v1/accounts/{account_id}/conversations/{conversation_id}/messages -
Body:
{ "content": "Mensagem do cliente", "message_type": "incoming" }
- Opcional: responder como agente (outgoing)
-
Mesmo endpoint de mensagens, com
message_type: "outgoing" -
Para canal E‑mail,
content_attributespode aceitarto_emails,cc_emails,bcc_emailsconforme sua configuração
Exemplo (Apps Script) — Fluxo exemplo para criar um E-mail com mensagem do usuário a partir do preenchimento de um Google Forms
function criarConversaEMensagemIncoming() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form_Responses");
var lastRow = sheet.getLastRow();
var nome = sheet.getRange(lastRow, 3).getValue();
var email = sheet.getRange(lastRow, 4).getValue();
var descricao = sheet.getRange(lastRow, 5).getValue();
var assunto = sheet.getRange(lastRow, 2).getValue();
var accountId = ACCOUNT_ID; // substitua pelo ID da conta
var inboxId = INBOX_ID; // substitua pelo ID da inbox
var base = "https://CLOUDCHAT_DOMAIN/api/v1/accounts/" + accountId;
var token = "SEU_API_ACCESS_TOKEN";
// 1) Buscar/criar contato
var resSearch = UrlFetchApp.fetch(base + "/contacts/search?q=" + encodeURIComponent(email), {
method: "get",
headers: { api_access_token: token, Accept: "application/json" },
muteHttpExceptions: true
});
var s = JSON.parse(resSearch.getContentText());
var contactId = (s && s.payload && s.payload[0] && s.payload[0].id) ? s.payload[0].id : null;
if (!contactId) {
var resCreate = UrlFetchApp.fetch(base + "/contacts", {
method: "post",
contentType: "application/json",
payload: JSON.stringify({ name: nome, email: email }),
headers: { api_access_token: token, Accept: "application/json" },
muteHttpExceptions: true
});
var c = JSON.parse(resCreate.getContentText());
contactId = (c && c.payload && c.payload.contact && c.payload.contact.id) ? c.payload.contact.id : null;
}
// 2) Vincular ContactInbox
UrlFetchApp.fetch(base + "/contacts/" + contactId + "/contact_inboxes", {
method: "post",
contentType: "application/json",
payload: JSON.stringify({ inbox_id: inboxId, source_id: String(email) }),
headers: { api_access_token: token, Accept: "application/json" },
muteHttpExceptions: true
});
// 3) Criar conversa (sem mensagem inicial)
var resConv = UrlFetchApp.fetch(base + "/conversations", {
method: "post",
contentType: "application/json",
payload: JSON.stringify({
source_id: String(email),
inbox_id: inboxId,
status: "open",
custom_attributes: { subject: assunto, requester_name: nome, requester_email: email }
}),
headers: { api_access_token: token, Accept: "application/json" },
muteHttpExceptions: true
});
var conv = JSON.parse(resConv.getContentText());
var conversationId = conv && conv.id ? conv.id : null;
// 4) Postar mensagem como cliente (incoming)
UrlFetchApp.fetch(base + "/conversations/" + conversationId + "/messages", {
method: "post",
contentType: "application/json",
payload: JSON.stringify({
content: "Assunto: " + assunto + "\n" +
"Solicitante: " + nome + " <" + email + ">\n\n" +
descricao,
message_type: "incoming"
}),
headers: { api_access_token: token, Accept: "application/json" },
muteHttpExceptions: true
});
sheet.getRange(lastRow, 7).setValue(conversationId);
}