Principal APIs Como criar tickets via API no Cloud Chat

Como criar tickets via API no Cloud Chat

Última atualização em May 21, 2026

Quando usar

  • Você quer iniciar uma conversa no Cloud Chat sem que o cliente tenha enviado uma mensagem por canal ativo
  • Você precisa centralizar comunicações que vêm de outras fontes (telefonia, formulário, CRM, ERP)
  • Você quer associar atributos customizados ao ticket no momento da criação

Pré-requisitos

  • API Key válido (do usuário ou agent bot) com acesso à conta — ver Como encontrar sua API Key no Cloud Chat

  • ACCOUNT_ID e INBOX_ID da mesma conta

  • Para alguns canais, a Inbox precisa ter "Criar conversa via API" habilitado

  • Para canal e-mail: vínculo ContactInbox entre o contato e a Inbox com source_id correto


Sobre este artigo

Esta API permite criar um ticket no Cloud Chat a partir de qualquer sistema externo — sistema de telefonia (ligação recebida), formulário web, integração com CRM/ERP. Você pode:

  • Criar ticket com status open, pending ou resolved

  • Associar a um contato via e-mail, telefone ou identificador

  • Incluir uma mensagem inicial (incoming ou outgoing)

  • Definir atributos customizados no momento da criação

Exemplos de uso

  • 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 de outras fontes? → Use esta API como ponto de entrada


Endpoint

POST https://{{CLOUDCHAT_DOMAIN}}/api/v1/accounts/{{ACCOUNT_ID}}/conversations

Headers

Header Valor
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",
  "private": false,
  "custom_attributes": {
    "example1": "valueXPTO"
  },
  "additional_attributes": {
    "mail_subject": "Protocolo de atendimento ABCD"
  },
  "assignee_id": "1"
}

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 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

inbox_id

Identificador da Inbox, obtido na URL ao acessar a configuração da caixa de entrada.

assignee_id (opcional)

Identificador do agente que será atribuído na criação.

Identificação do contato

Envie um dos três abaixo:

  • contact_identifier — identificador único do contato

  • contact_email — e-mail do contato

  • contact_phone_number — telefone do contato

message

  • content — conteúdo da mensagem

  • message_type:

    • "incoming" — mensagem vinda do cliente

    • "outgoing" — enviada pelo agente

    • "activity" — nota interna

  • privatefalse para visível ao cliente, true para nota interna

additional_attributes.mail_subject (opcional)

Para canal de e-mail, customiza o assunto enviado ao contato quando a conversa se inicia.

custom_attributes (opcional)

Adicione qualquer atributo customizado de conversa já existente na sua configuração. Para criar atributos: Criando campos customizados de contatos e conversas.


Status do ticket criado

O ticket nasce com status open por padrão (a menos que status seja informado), o que o torna visível e pronto para atendimento imediato na Inbox especificada.


Como testar

  1. Pegue seu api_access_token no painel de configurações

  2. Copie o ACCOUNT_ID, INBOX_ID e CLOUDCHAT_DOMAIN (ver Como importar histórico de tickets via API seção de parâmetros)

  3. Envie a requisição via Postman ou script

  4. 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 usa upsert, fixar esses campos resulta em um único contato sendo atualizado a cada chamada — 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 usa apenas contatos já existentes.

Se o contato não existir, é necessário criá-lo previamente via Como importar um contato individual via API.


Fluxo exemplo: criar ticket de e-mail com mensagem do usuário

Etapa 1 — Garantir/obter o contato

Buscar por chave (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

Etapa 2 — Vincular o contato à Inbox (ContactInbox)

POST /api/v1/accounts/{account_id}/contacts/{id}/contact_inboxes

Body: { "inbox_id": "INBOX_ID", "source_id": "<conforme canal>" }

Etapa 3 — Criar a conversa (sem mensagem inicial)

POST /api/v1/accounts/{account_id}/conversations

Body mínimo: { "source_id": "<...>", "inbox_id": "INBOX_ID", "status": "open" }

Etapa 4 — Postar mensagem como cliente (incoming)

POST /api/v1/accounts/{account_id}/conversations/{conversation_id}/messages

Body: { "content": "Mensagem do cliente", "message_type": "incoming" }

Etapa 5 (opcional) — Responder como agente (outgoing)

Mesmo endpoint de mensagens, com message_type: "outgoing". Para canal e-mail, content_attributes aceita to_emails, cc_emails, bcc_emails conforme sua configuração.


Exemplo prático: integração Google Forms via Apps Script

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;
  var inboxId = INBOX_ID;
  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
  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);
}

Observações