Como funciona
Esta página mostra a Orkesio de ponta a ponta: as peças, o caminho de uma mensagem enviada e de uma recebida, e o que chega em cada momento. Os detalhes de cada parte estão nas páginas seguintes.
As peças
- Inbox: um número conectado a um canal. Cada inbox tem um
token, que vai no header de toda chamada. A inbox da Orkesio é a mesma da uazapi: o mesmo token serve para as rotas antigas e para as novas. - Canal: por onde a inbox fala. Hoje, o WhatsApp pelo Web (
whatsapp_web, o número conectado por QR code), a API oficial do WhatsApp (whatsapp_cloud, pela Meta), o Instagram (instagram, uma conta profissional), o Messenger (messenger, uma Página do Facebook) ou o Telegram (telegram, um bot e, com o Telegram Business, a sua conta ligada a ele). O canal da inbox aparece em todo evento, eminbox.channel. - Mensagem: um objeto só, a
OrkesioMessage. É o mesmo na resposta do envio, na busca e nos eventos. - Três portas:
| Para | Use | Página |
|---|---|---|
| Enviar | POST /messages | Enviar mensagens |
| Ler o que já aconteceu | GET /messages | Buscar mensagens |
| Saber na hora | GET /events (tempo real) ou webhook (/webhooks) | Eventos |
Uma mensagem enviada, passo a passo
Exemplo: você envia um texto para um contato pelo WhatsApp Web.
| Passo | O que acontece | O que você vê |
|---|---|---|
| 1. Pedido | POST /messages com to, type: "text" e text. A api confere o pedido antes de qualquer coisa. | Erro no pedido (campo faltando, to inválido): 400 na hora, nada é enviado. Tipo que o canal não tem: 501. |
| 2. Fila | O pedido entra na fila da inbox, que envia uma mensagem por vez e na ordem de chegada. | A resposta volta na hora, com a mensagem e status: "queued". O id já é o definitivo. |
| 3. Saída | Na vez dela, a api manda a mensagem ao WhatsApp. | Evento message.sent, com a mensagem completa (placeholders trocados, arquivo processado). |
| 4. Entrega | O aparelho do contato recebe. | Evento message.status com delivered. |
| 5. Leitura | O contato abre a conversa (ou ouve o áudio). | message.status com read (ou played). |
| Se falhar | O WhatsApp recusa, ou a fila passa do prazo sem conseguir enviar. | message.status com failed e o motivo em error (error.error: "expired" quando passou do prazo). Quem só quer as falhas assina message.failed, que traz a mensagem inteira. |
Em qualquer momento, GET /messages?message_id=<id> devolve a mensagem com o status mais recente.
Quer esperar o envio sair na própria resposta? Mande options.async: false: a resposta só volta depois do passo
3, com status: "pending" (já saiu, sem confirmação de entrega ainda) ou com o erro.
Na API oficial o padrão é enviar na hora: o passo 2 não existe, e a resposta volta depois do passo 3, com
status: "pending" e o wamid como id (ou o erro). Lá não há fila: options.async: true é ignorado.
Em grupo, a entrega e a leitura chegam por participante, em group.receipts (um lote a
cada 60 segundos). O message.status do grupo traz só a falha.
Uma mensagem recebida, passo a passo
| Passo | O que acontece | O que você vê |
|---|---|---|
| 1. Chegada | O contato escreve. | Evento message.received: data.message (com quem escreveu, em author, e a conversa, em chat_id), data.chat (a conversa) e, em conversa direta, data.lead. |
| 2. Depois | O contato reage, edita ou apaga. | message.reaction ou message.updated (com change: "edited" ou "deleted" e a mensagem já com a mudança). |
| Mídia | Foto, vídeo, áudio ou documento. | O evento já traz o tipo, o tamanho e a miniatura (o arquivo ainda não). Quando a api baixa o arquivo (na chegada, se a inbox baixa as mídias, ou quando você pede o download), chega message.updated com change: "media_ready" e o url. |
O que você mesmo responde pelo celular ou pelo WhatsApp Web chega como message.sent, com sent_by: "phone" ou
"web". Assim dá para ver a conversa inteira, não só o que passou pela API.
Identificadores
id: o identificador da mensagem no próprio canal (o id do WhatsApp; na API oficial, owamid). É único dentro da inbox: se dois números seus estão no mesmo grupo, a mesma mensagem chega nas duas inboxes com o mesmoid. Guarde pela inbox (inbox.iddo evento) e peloid. Busca e ações valem para o número atual da inbox.chat_id(na mensagem;chat.idna conversa): a conversa. Num contato, o número no formato do WhatsApp (5511999999999@s.whatsapp.net); num grupo, o id do grupo (...@g.us). O LID, quando existe, vem emchat.lid.chat.lead_id: o lead do contato da conversa (veja abaixo). Guarde como veio, sem montar a partir de outro campo.
Conversa e lead
São duas coisas, com rotas próprias:
- Conversa (
/chats): o que o WhatsApp mostra, como nome, foto, não lidas, arquivada, etiquetas do WhatsApp Business e última mensagem. O atendimento também fica aqui: o responsável (assigned_to), o atendimento aberto (ticket_open), a pausa da automação e a memória da IA (PATCH /chats), porque valem para aquela conversa. - Lead (
/leads): quem é o cliente no CRM, com etapa do funil, tags do CRM, campos personalizados e notas. Só conversas diretas têm lead; grupo, canal e status não.
Três dados existem nos dois lados, com donos diferentes. Nenhum copia o outro:
| Dado | Na conversa (WhatsApp) | No lead (CRM da Orkesio) |
|---|---|---|
| Nome | chat.name: o da agenda do celular ou o que o contato usa | lead.name e lead.full_name: o que você ou a IA gravaram |
| Notas | notes em GET /chats/{chat_id}: as notas do WhatsApp Business, as mesmas do celular | lead.notes: só na Orkesio |
| Etiquetas | chat.labels: as do WhatsApp Business | lead.tags: as do CRM (colunas do kanban) |
O lado do WhatsApp é de cada número: cada um tem as suas notas e etiquetas, como no celular. O lado do CRM é do lead.
Como montar a tela:
- Lista de conversas com o CRM:
GET /chats. Cada conversa direta trazlead_ide olead. - Funil ou kanban:
GET /leads, filtrando por etapa ou tag. Por responsável:GET /chatscomassigned_to. - Alterar o CRM:
PATCH /leads, com ochat.lead_id. - No webhook e no
/events: o evento de mensagem de conversa direta já traz olead(data.lead), ao lado da mensagem e da conversa. A mudança sem mensagem chega emlead.updated.
Guarde o lead_id como opaco, como veio, e atualize-o pelo lead.updated.
Erros
Toda resposta de erro tem o mesmo formato:
{ "error": "invalid_request", "message": "text é obrigatório." }
error | Status HTTP | Quando |
|---|---|---|
invalid_request | 400 | Pedido errado: campo faltando, valor inválido, campo desconhecido no corpo. |
unsupported_for_channel | 501 | O canal da inbox não tem esse recurso: um tipo de mensagem (ex.: enquete na API oficial) ou uma rota inteira (as rotas da uazapi nos canais oficiais). |
outside_window | 400 | Canais oficiais: fora da janela de 24 horas. No WhatsApp, mande um modelo; no Instagram e no Messenger, espere o contato ou use options.human_agent. |
human_agent_not_allowed | 400 | Instagram e Messenger: human_agent sem a permissão Human Agent no app. |
recipient_unavailable | 400 | O contato bloqueou a conta ou não pode receber agora. No Telegram, também quando ele nunca falou com o bot. |
unauthorized | 401 | Token inválido. |
conversation_taken | 409 | Instagram e Messenger: a conversa está com outro app ou com a caixa de entrada da Meta. |
inbox_uses_whatsapp_web | 409 | Ligar uma API oficial numa inbox que já foi conectada pelo QR code. Crie uma inbox nova. |
rate_limited | 429 | Muitas requisições, da Orkesio ou do canal. |
disconnected | 503 | A inbox não está conectada (no WhatsApp Web) ou o token do canal oficial venceu: conecte de novo. |
send_failed | 500 | O canal recusou o envio. message traz o motivo. |
telegram_error | 502 | Telegram: o Telegram não respondeu ao ligar a inbox. Tente de novo. |
internal_error | 500 | Falha da nossa parte. Tente de novo. |
O error é estável: trate pelo código, não pelo texto de message, que pode mudar.
Regras que valem para tudo
- Nomes em
snake_casee datas em ISO 8601, em UTC, com milissegundos (2026-10-17T12:00:00.000Z), terminando em_at. - Listas paginadas por cursor:
limitecursorna URL; a resposta traznext_cursorenquanto houver mais. Veja Paginação. - Valores que podem crescer: listas como
type,status,sent_byechannelganham valores novos com novos canais e recursos. Trate valor desconhecido sem quebrar. - Campo ausente é campo vazio: campos sem valor não vêm no JSON (em vez de
nullou""). - Uma mudança no WhatsApp por pedido: nas rotas que alteram algo no WhatsApp, mande um campo de cada vez. Veja o motivo.
Paginação
As listas longas da Orkesio paginam do mesmo jeito, por cursor:
-
Peça a primeira página com
limit(de 1 a 200; padrão 50):GET /chats?limit=50. -
A resposta traz a lista e, se houver mais, o
next_cursor:{ "chats": [ ... ], "next_cursor": "MTc5MjIzODQwMDAwMHwzRUIwQTE" } -
Para a próxima página, repita o mesmo pedido (mesmos filtros) com
cursor=<next_cursor>:GET /chats?limit=50&cursor=MTc5MjIzODQwMDAwMHwzRUIwQTE. -
Quando a resposta vier sem
next_cursor, a lista acabou.
O cursor marca onde a página parou, e não uma posição: se chegar item novo enquanto você pagina, nada se repete nem fica de fora. Guarde o cursor como veio, sem montar nem alterar: o formato pode mudar.
- Não há número de página. Para percorrer tudo, siga o
next_cursoraté ele não vir. O total só vem quando você pede (total=trueemGET /chats,GET /leadseGET /contacts/list). - Listas que vêm do WhatsApp (catálogo e newsletters) seguem o mesmo
cursorenext_cursor, mas o tamanho da página pode ser menor: quem decide é o WhatsApp. - Listas curtas vêm inteiras, sem
limitnemnext_cursor: os webhooks (até 5) e as inboxes do servidor (GET /inbox/all). - Rotas no formato da uazapi (marcadas na página da rota) seguem paginando como na uazapi.
Uma mudança no WhatsApp por pedido
As rotas que alteram um grupo, uma newsletter ou o perfil comercial aceitam um campo por pedido. Para mudar o nome e a descrição de um grupo, faça dois pedidos:
PATCH /groups {"group_id": "120363028782550019@g.us", "name": "Clientes VIP"}
PATCH /groups {"group_id": "120363028782550019@g.us", "description": "Atendimento prioritário"}
Mais de um campo responde 400 com error: "one_change_per_request", e nada muda.
Por quê: cada campo é uma operação separada no WhatsApp. Com vários num pedido só, se o WhatsApp recusar o segundo (sem permissão, foto inválida, instabilidade), o primeiro já mudou e o grupo fica pela metade: você recebe um erro, mas parte do pedido valeu. Com um por pedido, a resposta diz exatamente o que aconteceu: ou mudou, ou não mudou nada.
Vale para:
| Rota | Um destes por pedido |
|---|---|
PATCH /groups | name, description, picture, announce, locked, join_approval, member_add_mode, ephemeral_seconds |
PATCH /newsletters | name, description, picture, reaction_mode, muted |
PATCH /business-profiles/me | description, address, email |
O que só muda na Orkesio (o lead, a conversa, a inbox) aceita vários campos juntos: lá não há etapa que possa falhar pela metade.