Aparência
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
- Localize o contato por lista, telefone ou ID.
- Crie o contato se ele ainda não existir.
- Inicie o chat escolhendo worker/canal e, opcionalmente, setor.
- Entre no atendimento quando a situação exigir.
- Consulte o histórico antes de responder.
- Envie texto, mídia, localização ou contato.
- Adicione etiquetas ou transfira para outro destino.
- 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 endpoint | Uso |
|---|---|
GET /v1/chat/contacts | Lista contatos com filtros e paginação. |
GET /v1/chat/contacts/:contact_id | Consulta um contato da conta. |
GET /v1/chat/contacts/by-phone | Localiza por telefone nos canais permitidos. |
POST /v1/chat/contacts/batch | Consulta vários contatos em uma chamada. |
POST /v1/chat/contacts | Cria um novo contato. |
PATCH /v1/chat/contacts/:contact_id | Atualiza 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"
}| Campo | Tipo | Obrigatório | Finalidade |
|---|---|---|---|
contact_id | UUID | Sim | Contato que receberá o atendimento. |
worker_id | UUID | Sim | Canal/worker usado para iniciar a conversa. |
sector_id | UUID | Não | Setor inicial do chat. |
official_template | object | Não | Template 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:
| Campo | Obrigatório | Uso |
|---|---|---|
message | Conforme tipo | Texto ou legenda. |
message_quoted_id | Não | ID da mensagem respondida. |
link_preview | Não | Preview previamente validado por /chat/link-preview. |
images, documents, videos, audios | Conforme tipo | Arquivos em multipart. |
location_latitude, location_longitude | Para localização | Coordenadas; nome e endereço são opcionais. |
contacts | Para contato(s) | ID ou lista conforme schema. |
quick_message_template_id | Não | Template de mensagem rápida. |
Veja uploads e mídia para exemplos multipart.
6. Reagir, editar, excluir ou encaminhar
| Método e endpoint | Ação |
|---|---|
POST /v1/chat/:chat_id/message/:message_id/react | Adiciona ou remove reação conforme body. |
POST /v1/chat/:chat_id/message/:message_id/edit | Edita mensagem quando o canal permite. |
POST /v1/chat/:chat_id/message/:message_id/delete | Solicita exclusão no canal. |
POST /v1/chat/:chat_id/message/:message_id/forward | Encaminha para destinos permitidos. |
POST /v1/chat/:chat_id/message/:message_id/transcribe | Transcreve á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
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
worker_id | UUID | Não | Move para outro canal quando permitido. |
user_id | UUID | Não | Atendente de destino. |
sector_id | UUID | Não | Setor de destino. |
chatbot_id | UUID | Não | Chatbot de destino. |
annotation | string, até 5000 | Não | Contexto interno da transferência. |
keep_in_chat | boolean | Não | Mantém o executor no chat; padrão false. |
send_message_on_transfer | boolean | Não | Controla 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."
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | enum | Sim | Nova situação do chat. |
send_message_on_finish_attendance | boolean | Não | Dispara mensagem de finalização configurada. |
closure_comment | string, até 1000 | Não | Observação interna de encerramento. |
Mapa completo do domínio
Conversas e preferências
| Método | Caminho | Finalidade |
|---|---|---|
| GET | /chat | Listar chats. |
| GET | /chat/kanban | Visão de chats para kanban. |
| GET/POST/DELETE | /chat/pinned e /chat/pinned/:chat_id | Consultar, fixar e desafixar. |
| POST | /chat/start-with-contact | Iniciar conversa. |
| POST | /chat/link-preview | Obter preview seguro de URL pública. |
| GET/PUT | /chat/notification-settings | Ler e alterar preferências do executor. |
| GET | /chat/unread-summary | Resumo de não lidas. |
| GET | /chat/:chat_id/attendants | Atendentes relacionados ao chat. |
| PUT | /chat/user | Atualizar atribuição de usuário nos chats. |
Operações do atendimento
| Método | Caminho | Finalidade |
|---|---|---|
| GET/POST | /chat/:chat_id | Histórico e envio de mensagem. |
| GET | /chat/:chat_id/search | Buscar mensagens no chat. |
| PATCH | /chat/:chat_id/status | Alterar situação/finalizar. |
| POST | /chat/:chat_id/clear-summary | Limpar resumo gerado. |
| POST | /chat/:chat_id/join | Entrar no atendimento. |
| POST | /chat/:chat_id/leave | Sair do atendimento. |
| POST | /chat/:chat_id/transfer | Transferir. |
| POST | /chat/bulk-action | Executar ação em lote conforme schema. |
| PATCH | /chat/:chat_id/label | Atualizar etiquetas. |
| PATCH | /chat/:chat_id/forward-to-output-chatbot | Controlar encaminhamento ao chatbot de saída. |
| GET/PATCH | /chat/:chat_id/attendance-inactivity | Ler e alterar inatividade. |
| POST | /chat/:chat_id/ai-generate | Gerar sugestão com IA, mediante permissão específica. |
Contexto oficial e destinos
| Método | Caminho | Finalidade |
|---|---|---|
| GET | /chat/worker/:worker_id/config | Configuração pública necessária ao chat. |
| GET | /chat/official-opening/context | Contexto para abertura oficial. |
| GET | /chat/:chat_id/official-conversation/context | Janela e contexto oficial do chat. |
| POST | /chat/:chat_id/official-template | Enviar template oficial. |
| GET | /chat/workers | Workers/canais permitidos. |
| GET | /chat/users | Usuários permitidos. |
| GET | /chat/sectors | Setores permitidos ao chat. |
| GET | /chat/offline-channels | Canais offline. |
| GET | /chat/channels-status | Situação dos canais. |
Contatos e recursos auxiliares
| Método | Caminho | Finalidade |
|---|---|---|
| GET | /chat/contact-channels | Canais disponíveis para contatos. |
| GET | /chat/contacts/:contact_id/channels | Canais de um contato. |
| GET | /chat/contacts/:contact_id/email | Email protegido. |
| GET | /chat/contacts/:contact_id/phone | Telefone protegido. |
| GET | /chat/contacts/:contact_id/document | Documento protegido. |
| DELETE | /chat/contacts/:contact_id/photo | Remover foto. |
| POST | /chat/contacts/:contact_id/validate | Validar dados do contato. |
| GET | /chat/label-templates | Etiquetas disponíveis no contexto do chat. |
| GET | /chat/quick-message-templates | Mensagens 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-previewaceita 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.