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, em inbox.channel.
  • Mensagem: um objeto só, a OrkesioMessage. É o mesmo na resposta do envio, na busca e nos eventos.
  • Três portas:
ParaUsePágina
EnviarPOST /messagesEnviar mensagens
Ler o que já aconteceuGET /messagesBuscar mensagens
Saber na horaGET /events (tempo real) ou webhook (/webhooks)Eventos

Uma mensagem enviada, passo a passo

Exemplo: você envia um texto para um contato pelo WhatsApp Web.

PassoO que aconteceO que você vê
1. PedidoPOST /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. FilaO 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ídaNa vez dela, a api manda a mensagem ao WhatsApp.Evento message.sent, com a mensagem completa (placeholders trocados, arquivo processado).
4. EntregaO aparelho do contato recebe.Evento message.status com delivered.
5. LeituraO contato abre a conversa (ou ouve o áudio).message.status com read (ou played).
Se falharO 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

PassoO que aconteceO que você vê
1. ChegadaO 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. DepoisO contato reage, edita ou apaga.message.reaction ou message.updated (com change: "edited" ou "deleted" e a mensagem já com a mudança).
MídiaFoto, 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, o wamid). É único dentro da inbox: se dois números seus estão no mesmo grupo, a mesma mensagem chega nas duas inboxes com o mesmo id. Guarde pela inbox (inbox.id do evento) e pelo id. Busca e ações valem para o número atual da inbox.
  • chat_id (na mensagem; chat.id na 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 em chat.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:

DadoNa conversa (WhatsApp)No lead (CRM da Orkesio)
Nomechat.name: o da agenda do celular ou o que o contato usalead.name e lead.full_name: o que você ou a IA gravaram
Notasnotes em GET /chats/{chat_id}: as notas do WhatsApp Business, as mesmas do celularlead.notes: só na Orkesio
Etiquetaschat.labels: as do WhatsApp Businesslead.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 traz lead_id e o lead.
  • Funil ou kanban: GET /leads, filtrando por etapa ou tag. Por responsável: GET /chats com assigned_to.
  • Alterar o CRM: PATCH /leads, com o chat.lead_id.
  • No webhook e no /events: o evento de mensagem de conversa direta já traz o lead (data.lead), ao lado da mensagem e da conversa. A mudança sem mensagem chega em lead.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." }
errorStatus HTTPQuando
invalid_request400Pedido errado: campo faltando, valor inválido, campo desconhecido no corpo.
unsupported_for_channel501O 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_window400Canais 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_allowed400Instagram e Messenger: human_agent sem a permissão Human Agent no app.
recipient_unavailable400O contato bloqueou a conta ou não pode receber agora. No Telegram, também quando ele nunca falou com o bot.
unauthorized401Token inválido.
conversation_taken409Instagram e Messenger: a conversa está com outro app ou com a caixa de entrada da Meta.
inbox_uses_whatsapp_web409Ligar uma API oficial numa inbox que já foi conectada pelo QR code. Crie uma inbox nova.
rate_limited429Muitas requisições, da Orkesio ou do canal.
disconnected503A inbox não está conectada (no WhatsApp Web) ou o token do canal oficial venceu: conecte de novo.
send_failed500O canal recusou o envio. message traz o motivo.
telegram_error502Telegram: o Telegram não respondeu ao ligar a inbox. Tente de novo.
internal_error500Falha 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_case e datas em ISO 8601, em UTC, com milissegundos (2026-10-17T12:00:00.000Z), terminando em _at.
  • Listas paginadas por cursor: limit e cursor na URL; a resposta traz next_cursor enquanto houver mais. Veja Paginação.
  • Valores que podem crescer: listas como type, status, sent_by e channel ganham 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 null ou "").
  • 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:

  1. Peça a primeira página com limit (de 1 a 200; padrão 50): GET /chats?limit=50.

  2. A resposta traz a lista e, se houver mais, o next_cursor:

    { "chats": [ ... ], "next_cursor": "MTc5MjIzODQwMDAwMHwzRUIwQTE" }
    
  3. Para a próxima página, repita o mesmo pedido (mesmos filtros) com cursor=<next_cursor>: GET /chats?limit=50&cursor=MTc5MjIzODQwMDAwMHwzRUIwQTE.

  4. 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_cursor até ele não vir. O total só vem quando você pede (total=true em GET /chats, GET /leads e GET /contacts/list).
  • Listas que vêm do WhatsApp (catálogo e newsletters) seguem o mesmo cursor e next_cursor, mas o tamanho da página pode ser menor: quem decide é o WhatsApp.
  • Listas curtas vêm inteiras, sem limit nem next_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:

RotaUm destes por pedido
PATCH /groupsname, description, picture, announce, locked, join_approval, member_add_mode, ephemeral_seconds
PATCH /newslettersname, description, picture, reaction_mode, muted
PATCH /business-profiles/medescription, 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.