Skip to content

Chat e atendimento ​

O domínio chat cobre o ciclo operacional completo: localizar ou criar um contato, iniciar uma conversa, consultar histórico, enviar mensagens, classificar, transferir e encerrar o atendimento. As operações respeitam canais, setores e permissões do usuário selecionado em x-underchat-user-id; a chave identifica somente a conta.

Fluxo recomendado ​

  1. Localize o contato por lista, telefone ou ID.
  2. Crie o contato se ele ainda não existir.
  3. Inicie o chat escolhendo worker/canal e, opcionalmente, setor.
  4. Entre no atendimento quando a situação exigir.
  5. Consulte o histórico antes de responder.
  6. Envie texto, mídia, localização ou contato.
  7. Adicione etiquetas ou transfira para outro destino.
  8. Finalize o atendimento com status e comentário de encerramento.

1. Listar conversas ​

GET /v1/chat

status é obrigatório. Use my_chats para obter os chats atribuídos ao usuário executor ou uma situação do fluxo: ura, queue, in_chat, ura_output, ura_schedule, ura_webhook, closed ou transmission.

bash
curl --get "$UNDERCHAT_API_URL/v1/chat" \
  --header "keyapi: $UNDERCHAT_API_TOKEN" \
  --header "x-underchat-user-id: $UNDERCHAT_USER_ID" \
  --data-urlencode "status=in_chat" \
  --data-urlencode "current_page=1" \
  --data-urlencode "per_page=20" \
  --data-urlencode "filter_unread_conversations=true"

Filtros opcionais permitem restringir por etiqueta, worker, usuário, setor, nome, telefone, protocolo, período e conversas não lidas. Consulte paginação e filtros.

Visualização Kanban ​

GET /v1/chat/kanban

O Kanban organiza as conversas nas colunas chatbot, queue, in_chat e closed. Cada coluna possui resultados e paginação independentes. Use filter_sector_id para exibir somente os cards vinculados a um setor; o filtro pode ser combinado com filter_worker_id, filter_name e filter_phone.

Sem filter_sector_id, a resposta mantém a visão agregada permitida ao executor, inclusive atendimentos sem setor quando suas permissões autorizarem. Mesmo com um ID de setor explícito, a API continua aplicando conta, canais, setores associados e permissões do usuário informado em x-underchat-user-id.

2. Localizar ou criar o contato ​

Use a busca mais específica disponível:

Método e endpointUso
GET /v1/chat/contactsLista contatos com filtros e paginação.
GET /v1/chat/contacts/:contact_idConsulta um contato da conta.
GET /v1/chat/contacts/by-phoneLocaliza por telefone nos canais permitidos.
POST /v1/chat/contacts/batchConsulta vários contatos em uma chamada.
POST /v1/chat/contactsCria um novo contato.
PATCH /v1/chat/contacts/:contact_idAtualiza os campos permitidos.

Também existem endpoints protegidos para email, telefone, documento, foto, validação e canais do contato. A API sempre aplica account_id e o escopo de canais do executor; um ID de outra conta não concede acesso ao registro.

3. Iniciar com um contato ​

POST /v1/chat/start-with-contact

json
{
  "contact_id": "cdd1518c-95b2-47f1-a1a6-51ab628d15e8",
  "worker_id": "743ef1bb-83b7-462a-8995-a6e1151437db",
  "sector_id": "4ae578ec-1556-4ea2-8056-5e5482f3c02c"
}
CampoTipoObrigatórioFinalidade
contact_idUUIDSimContato que receberá o atendimento.
worker_idUUIDSimCanal/worker usado para iniciar a conversa.
sector_idUUIDNãoSetor inicial do chat.
official_templateobjectNãoTemplate obrigatório para abrir algumas conversas oficiais.

Em official_template, name e language são obrigatórios. variables contém key, component_type (HEADER, BODY, FOOTER ou BUTTON), index, value e, para botões, button_index.

Templates com mídia, localização e carrossel ​

Os contextos de template retornam os campos esperados, incluindo parameter_type (TEXT, IMAGE, VIDEO, DOCUMENT ou LOCATION). O tipo do cabeçalho é detectado automaticamente. Campos de carrossel incluem card_index, começando em zero, e uma chave como CARD:0:HEADER:1. Use as chaves devolvidas pela API. Templates com supported: false devem apresentar o motivo de incompatibilidade.

Para anexar um arquivo, envie multipart/form-data para POST /v1/official-templates/media, com os campos file, parameter_type, context: chat e worker_id. Esse endpoint prepara o anexo sem enviar mensagem. Exemplo de upload de documento:

bash
curl --request POST 'https://api.exemplo.com/v1/official-templates/media' \
  --header 'Authorization: Bearer <token-da-integracao>' \
  --header 'x-underchat-user-id: <usuario-executor>' \
  --form 'file=@/caminho/catalogo.pdf;type=application/pdf' \
  --form 'parameter_type=DOCUMENT' \
  --form 'context=chat' \
  --form 'worker_id=743ef1bb-83b7-462a-8995-a6e1151437db'

Para importar um link público, use:

http
POST /v1/official-templates/media/import
Content-Type: application/json
Authorization: Bearer <token-da-integracao>
x-underchat-user-id: <usuario-executor>
json
{
  "url": "https://arquivos.exemplo.com/convite.jpg",
  "parameter_type": "IMAGE",
  "context": "chat",
  "worker_id": "743ef1bb-83b7-462a-8995-a6e1151437db"
}

A resposta contém data.url, name, extension, mimetype, size e dimensões quando disponíveis. O servidor valida o conteúdo real do arquivo. Cabeçalhos aceitam JPEG/PNG de até 5 MiB, vídeo MP4/3GP H.264 com até uma faixa AAC de até 16 MiB e documento PDF de até 100 MiB. Áudio não é um formato de cabeçalho de template suportado pelo conector.

Passe o objeto retornado em value, no envio para POST /v1/chat/:chat_id/official-template ou em official_template ao abrir um atendimento:

json
{
  "name": "convite_com_imagem",
  "language": "pt_BR",
  "variables": [
    {
      "key": "HEADER:1",
      "component_type": "HEADER",
      "index": 1,
      "parameter_type": "IMAGE",
      "value": {
        "url": "https://storage.exemplo.com/conta/official-template-runtime/convite.jpg",
        "name": "convite.jpg",
        "mimetype": "image/jpeg",
        "size": 123456
      }
    },
    { "key": "BODY:1", "component_type": "BODY", "index": 1, "value": "Maria" }
  ]
}

Em um carrossel, cada cabeçalho e variável usa o card_index do cartão correspondente; mantenha a quantidade e a ordem do template aprovado. Exemplo de envio com duas imagens já preparadas pelos endpoints acima:

json
{
  "name": "ofertas_carrossel",
  "language": "pt_BR",
  "variables": [
    { "key": "BODY:1", "component_type": "BODY", "index": 1, "value": "Maria" },
    {
      "key": "CARD:0:HEADER:1",
      "component_type": "HEADER",
      "card_index": 0,
      "index": 1,
      "parameter_type": "IMAGE",
      "value": {
        "url": "https://storage.exemplo.com/conta/official-template-runtime/oferta-1.jpg",
        "name": "oferta-1.jpg",
        "mimetype": "image/jpeg",
        "size": 123456
      }
    },
    {
      "key": "CARD:0:BODY:1",
      "component_type": "BODY",
      "card_index": 0,
      "index": 1,
      "value": "Cafeteira"
    },
    {
      "key": "CARD:1:HEADER:1",
      "component_type": "HEADER",
      "card_index": 1,
      "index": 1,
      "parameter_type": "IMAGE",
      "value": {
        "url": "https://storage.exemplo.com/conta/official-template-runtime/oferta-2.jpg",
        "name": "oferta-2.jpg",
        "mimetype": "image/jpeg",
        "size": 234567
      }
    },
    {
      "key": "CARD:1:BODY:1",
      "component_type": "BODY",
      "card_index": 1,
      "index": 1,
      "value": "Chaleira"
    }
  ]
}

Para um template aprovado com cabeçalho de localização:

json
{
  "name": "localizacao_da_loja",
  "language": "pt_BR",
  "variables": [
    {
      "key": "HEADER:1",
      "component_type": "HEADER",
      "index": 1,
      "parameter_type": "LOCATION",
      "value": {
        "latitude": -23.5505,
        "longitude": -46.6333,
        "name": "Nossa loja",
        "address": "São Paulo"
      }
    }
  ]
}

Coordenadas zero são válidas. Para parâmetros textuais nomeados, preserve parameter_name e a chave recebida na listagem, por exemplo { "key": "BODY:first_name", "component_type": "BODY", "index": 1, "parameter_name": "first_name", "value": "Maria" }. O nome usa letras minúsculas, números e sublinhado, começando por uma letra. Parâmetros de botões continuam posicionais. Valores de texto existentes continuam aceitando string ou number. Exemplos de mídia do cadastro na Meta não substituem os anexos escolhidos para cada envio.

Os endpoints de preparação exigem as permissões do contexto e acesso ao canal. As interfaces de agendamento, chatbot e automações CRM usam o mesmo contrato com context correspondente; chatbot também permite chatbot_id em vez de worker_id. Links estáticos são copiados para o armazenamento. Links com variáveis de automação são resolvidos e validados para cada destinatário antes do envio. Mídias de configuração permanecem disponíveis enquanto a conta estiver ativa; anexos de chat seguem a retenção normal do histórico. Ao reutilizar um anexo de chat em uma configuração, o servidor preserva uma cópia de configuração.

4. Consultar mensagens ​

GET /v1/chat/:chat_id

Essa operação retorna o histórico conforme paginação e filtros do contrato. Para buscar texto dentro de um chat, use GET /v1/chat/:chat_id/search; para uma busca mais ampla de chats, use GET /v1/chat/search.

Antes de responder, mantenha o chat_id, o ID da última mensagem e a situação atual. Esses dados reduzem respostas em chats já transferidos ou encerrados.

5. Enviar mensagem ​

POST /v1/chat/:chat_id

Mensagem de texto:

json
{
  "type": "text",
  "message": "Olá, Maria. Seu pedido foi localizado."
}

type é obrigatório. Os principais valores operacionais são text, image, video, video_note, audio, document, location, contact_card e contacts. Outros valores do enum atendem ações internas do fluxo; use apenas combinações descritas pelo OpenAPI.

Campos complementares:

CampoObrigatórioUso
messageConforme tipoTexto ou legenda.
message_quoted_idNãoID da mensagem respondida.
link_previewNãoPreview previamente validado por /chat/link-preview.
images, documents, videos, audiosConforme tipoArquivos em multipart.
location_latitude, location_longitudePara localizaçãoCoordenadas; nome e endereço são opcionais.
contactsPara contato(s)ID ou lista conforme schema.
quick_message_template_idNãoTemplate de mensagem rápida.

Veja uploads e mídia para exemplos multipart.

6. Reagir, editar, excluir ou encaminhar ​

Método e endpointAção
POST /v1/chat/:chat_id/message/:message_id/reactAdiciona ou remove reação conforme body.
POST /v1/chat/:chat_id/message/:message_id/editEdita mensagem quando o canal permite.
POST /v1/chat/:chat_id/message/:message_id/deleteSolicita exclusão no canal.
POST /v1/chat/:chat_id/message/:message_id/forwardEncaminha para destinos permitidos.
POST /v1/chat/:chat_id/message/:message_id/transcribeTranscreve áudio com a permissão correspondente.

Essas ações dependem da capacidade e da janela do canal. Uma resposta HTTP aceita indica que a Underchat processou a solicitação; leia o payload para o resultado específico.

Encaminhar várias mensagens ​

Use POST /v1/chat/:chat_id/messages/forward para encaminhar uma seleção em uma única requisição. O endpoint individual continua disponível.

json
{
  "message_ids": ["mensagem-foto", "mensagem-audio"],
  "target_chat_ids": ["019a0000-0000-7000-8000-000000000002"],
  "idempotency_key": "019a0000-0000-7000-8000-000000000001"
}

São permitidas até 50 mensagens e 200 combinações de mensagem e destino por requisição. Também é possível usar target_contact_ids junto de worker_id. Divida seleções maiores de destinos em requisições respeitando esses limites e mantenha a identidade de cada requisição nos retries.

As mensagens precisam pertencer à conversa de origem e já ter sido enviadas ou recebidas. Fotos, áudios, vídeos, documentos, texto, stickers, localização e contatos seguem as permissões do encaminhamento individual. Mensagens excluídas, de visualização única, com mídia indisponível ou ainda pendentes não podem ser encaminhadas. Todas as origens são validadas antes da abertura de atendimentos ou publicação.

O servidor preserva a ordem cronológica e recria os álbuns usando apenas os itens selecionados. A resposta contém requested, sent, failed e results. Cada resultado identifica source_message_id, o destino e seu status; sent indica publicação aceita, enquanto a entrega continua sendo acompanhada pelo estado da mensagem.

Destinos sem permissão ou indisponíveis aparecem como falhas parciais. Um chat também escolhido por contato recebe cada mensagem uma vez. Repita com o mesmo idempotency_key para continuar pares pendentes sem duplicar pares aceitos. Quando omitida, a chave UUIDv7 gerada é retornada no envelope. Uma nova chave representa um novo encaminhamento.

Os metadados commands e headers de aceitação seguem o encaminhamento individual. Em 503 com acceptance: "unknown", preserve a mesma chave e consulte accepted_commands; após a janela de retry, 410 indica que a mesma operação não pode ser repetida. retry_of vincula uma nova tentativa à identidade anterior.

No painel e no aplicativo, os domínios mantêm destinos próprios: atendimento para chats/contatos; grupos de WhatsApp para grupos (POST /groups/:id/messages/forward, com operation_id); chat interno para conversas/colegas (POST /internal-chat/:conversation_id/messages/forward, com idempotency_key). Os dois últimos endpoints são do manager e não integram a API pública.

7. Entrar, sair e transferir ​

Use POST /v1/chat/:chat_id/join para assumir e POST /v1/chat/:chat_id/leave para sair quando o fluxo exigir. Consulte destinos antes de transferir:

  • GET /v1/chat/transfer-options;
  • GET /v1/chat/transfer/users;
  • GET /v1/chat/transfer/sectors;
  • GET /v1/chat/transfer/sectors/:sector_id/users.

POST /v1/chat/:chat_id/transfer

json
{
  "sector_id": "4ae578ec-1556-4ea2-8056-5e5482f3c02c",
  "user_id": "41e3e61e-f816-4108-a5df-0d5ca497633e",
  "annotation": "Cliente solicitou análise financeira.",
  "keep_in_chat": false,
  "send_message_on_transfer": true
}
CampoTipoObrigatórioDescrição
worker_idUUIDNãoMove para outro canal quando permitido.
user_idUUIDNãoAtendente de destino.
sector_idUUIDNãoSetor de destino.
chatbot_idUUIDNãoChatbot de destino.
annotationstring, até 5000NãoContexto interno da transferência.
keep_in_chatbooleanNãoMantém o executor no chat; padrão false.
send_message_on_transferbooleanNãoControla mensagem automática configurada.

O body aceita destinos opcionais porque o comportamento depende da modalidade de transferência. Envie apenas a combinação exibida por transfer-options.

8. Etiquetar e finalizar ​

PATCH /v1/chat/:chat_id/label

Associa os IDs de templates permitidos. Para remover uma etiqueta específica do contato, existe DELETE /v1/chat/contacts/:contact_id/labels/:label_template_id.

PATCH /v1/chat/:chat_id/status

json
{
  "status": "closed",
  "send_message_on_finish_attendance": true,
  "closure_comment": "Solicitação resolvida e confirmada pelo cliente."
}
CampoTipoObrigatórioDescrição
statusenumSimNova situação do chat.
send_message_on_finish_attendancebooleanNãoDispara mensagem de finalização configurada.
closure_commentstring, até 1000NãoObservação interna de encerramento.

Mapa completo do domínio ​

Conversas e preferências ​

MétodoCaminhoFinalidade
GET/chatListar chats.
GET/chat/kanbanVisão de chats para kanban.
GET/POST/DELETE/chat/pinned e /chat/pinned/:chat_idConsultar, fixar e desafixar.
POST/chat/start-with-contactIniciar conversa.
POST/chat/link-previewObter preview seguro de URL pública.
GET/PUT/chat/notification-settingsLer e alterar preferências do executor.
GET/chat/unread-summaryResumo de não lidas.
GET/chat/:chat_id/attendantsAtendentes relacionados ao chat.
PUT/chat/userAtualizar atribuição de usuário nos chats.

Operações do atendimento ​

MétodoCaminhoFinalidade
GET/POST/chat/:chat_idHistórico e envio de mensagem.
GET/chat/:chat_id/searchBuscar mensagens no chat.
PATCH/chat/:chat_id/statusAlterar situação/finalizar.
POST/chat/:chat_id/clear-summaryLimpar resumo gerado.
POST/chat/:chat_id/joinEntrar no atendimento.
POST/chat/:chat_id/leaveSair do atendimento.
POST/chat/:chat_id/transferTransferir.
POST/chat/bulk-actionExecutar ação em lote conforme schema.
PATCH/chat/:chat_id/labelAtualizar etiquetas.
PATCH/chat/:chat_id/forward-to-output-chatbotControlar encaminhamento ao chatbot de saída.
GET/PATCH/chat/:chat_id/attendance-inactivityLer e alterar inatividade.
POST/chat/:chat_id/ai-generateGerar sugestão com IA, mediante permissão específica.

Contexto oficial e destinos ​

MétodoCaminhoFinalidade
GET/chat/worker/:worker_id/configConfiguração pública necessária ao chat.
GET/chat/official-opening/contextContexto para abertura oficial.
GET/chat/:chat_id/official-conversation/contextJanela e contexto oficial do chat.
POST/chat/:chat_id/official-templateEnviar template oficial.
GET/chat/workersWorkers/canais permitidos.
GET/chat/usersUsuários permitidos.
GET/chat/sectorsSetores permitidos ao chat.
GET/chat/offline-channelsCanais offline.
GET/chat/channels-statusSituação dos canais.

Contatos e recursos auxiliares ​

MétodoCaminhoFinalidade
GET/chat/contact-channelsCanais disponíveis para contatos.
GET/chat/contacts/:contact_id/channelsCanais de um contato.
GET/chat/contacts/:contact_id/emailEmail protegido.
GET/chat/contacts/:contact_id/phoneTelefone protegido.
GET/chat/contacts/:contact_id/documentDocumento protegido.
DELETE/chat/contacts/:contact_id/photoRemover foto.
POST/chat/contacts/:contact_id/validateValidar dados do contato.
GET/chat/label-templatesEtiquetas disponíveis no contexto do chat.
GET/chat/quick-message-templatesMensagens rápidas permitidas.

Todos os caminhos desta seção recebem o prefixo /v1. Para bodies, queries, respostas e permissões operação por operação, use a referência interativa.

Segurança e efeitos externos ​

  • link-preview aceita apenas destinos públicos e limita redirects, tamanho e timeout; não use a rota para acessar redes privadas;
  • consultas de email, telefone e documento exigem conta e canal permitidos;
  • IA e transcrição exigem permissões adicionais e podem consumir serviços externos;
  • envio e edição de mensagem têm efeito no canal real; teste em um contato controlado;
  • IDs retornados pela conta devem ser tratados como opacos.

API pública para integrações seguras e rastreáveis.