Antonnia Docs
ConversationsApi reference

API de Ingest

Referência completa do endpoint unificado de ingestão de mensagens

Ingest

Endpoint unificado que, em uma única chamada, lida com:

  • Busca ou criação de conversa
  • Ciclo de vida da sessão (continuar, criar nova, fechar)
  • Envio de mensagem
  • Transferência de agente
  • Disparo automático de resposta da IA
POST /ingest

Corpo da requisição

CampoTipoObrigatórioDescrição
tostringSimID do canal (ex.: "wn_55119999")
fromstringSimID do usuário no canal (ex.: "+5511999999999")
channel_typestringNãoTipo do canal. Padrão: "whatsapp"
contactobjectNãoDados do contato (ver abaixo)
contentobjectNãoCorpo da mensagem (ver abaixo). Omita para operações sem mensagem
rolestringNão"user" (padrão) ou "assistant"
provider_message_idstringNãoID da mensagem no provedor externo
sessionstringNão"continue" (padrão), "new" ou "close"
agent_idstringNãoID do agente. Omita para manter o atual; envie null para desassociar
metadataobjectNãoRFC 7396 merge patch no metadata da sessão

Objeto contact

CampoTipoObrigatórioDescrição
namestringCondicionalNome do contato
phonestringCondicionalTelefone do contato

Ao menos um campo (name ou phone) deve ser fornecido se o objeto contact estiver presente. Omita contact inteiramente quando não houver informação adicional — o from já identifica o usuário.

Objeto content

O campo content aceita um dos seguintes tipos:

TipoCamposDescrição
texttype, textMensagem de texto
imagetype, urlImagem (URL)
audiotype, url, transcript?Áudio (URL + transcrição opcional)
videotype, urlVídeo (URL)
filetype, url, mime_type, nameArquivo genérico

Semântica do campo session

ValorComportamento
"continue"Reutiliza sessão aberta existente ou cria uma nova caso não exista
"new"Fecha a sessão aberta atual e cria uma nova
"close"Insere a mensagem (se houver) e então fecha a sessão

Semântica do campo metadata

O metadata usa RFC 7396 (JSON Merge Patch) recursivo:

  • Valores null dentro do objeto removem as chaves
  • Objetos aninhados são mesclados recursivamente (não substituição rasa)
  • Omitir o campo inteiramente não altera o metadata existente

Exemplo de requisição

curl -X POST https://services.antonnia.com/conversations/v2/api/v1/ingest \
  -H "Authorization: Bearer sk_live_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "wn_55119999",
    "from": "+5511999888777",
    "channel_type": "whatsapp",
    "contact": {
      "name": "Maria Silva",
      "phone": "+5511999888777"
    },
    "content": {
      "type": "text",
      "text": "Olá, preciso de ajuda com meu pedido"
    },
    "role": "user",
    "session": "continue",
    "agent_id": "agent_abc",
    "metadata": {
      "source": "whatsapp",
      "priority": "high"
    }
  }'
import httpx

BASE_URL = "https://services.antonnia.com/conversations/v2/api/v1"
HEADERS = {
    "Authorization": "Bearer sk_live_YOUR_TOKEN",
    "Content-Type": "application/json",
}

response = httpx.post(f"{BASE_URL}/ingest", headers=HEADERS, json={
    "to": "wn_55119999",
    "from": "+5511999888777",
    "channel_type": "whatsapp",
    "contact": {
        "name": "Maria Silva",
        "phone": "+5511999888777",
    },
    "content": {
        "type": "text",
        "text": "Olá, preciso de ajuda com meu pedido",
    },
    "role": "user",
    "session": "continue",
    "agent_id": "agent_abc",
    "metadata": {
        "source": "whatsapp",
        "priority": "high",
    },
})
result = response.json()

Response 200

{
  "conversation_id": "conv_abc123",
  "session_id": "sess_xyz789",
  "message_id": "msg_def456",
  "created_conversation": false,
  "created_session": true
}
CampoTipoDescrição
conversation_idstringID da conversa (criada ou reutilizada)
session_idstring | nullID da sessão (null se não houver contexto de sessão)
message_idstring | nullID da mensagem (null se content não foi enviado)
created_conversationbooleantrue se a conversa foi criada nesta chamada
created_sessionbooleantrue se a sessão foi criada nesta chamada

Erros

StatusDetalheCausa
401UnauthorizedToken inválido ou ausente
502Ingest RPC returned no dataO banco não retornou dados
502Ingest RPC returned unexpected shapeEstrutura de retorno inesperada
500Internal server errorErro interno não tratado

Comportamentos automáticos

  1. Criação de contato: Se o contato não existir, ele é criado automaticamente com os dados fornecidos
  2. Criação de conversa: Se não existir conversa para o par (canal + usuário), uma nova é criada
  3. Resposta da IA: Se a sessão tem um agente do tipo ai e uma mensagem foi criada, a resposta da IA é disparada automaticamente com debounce configurável
  4. Eventos: Cada transição de estado gera eventos internos (conversation.created, session.created, session.transferred, session.closed, message.created)

Operações sem mensagem

O endpoint aceita chamadas sem content para operações de controle:

{
  "to": "wn_55119999",
  "from": "+5511999888777",
  "agent_id": "agent_new"
}
{
  "to": "wn_55119999",
  "from": "+5511999888777",
  "session": "close"
}
{
  "to": "wn_55119999",
  "from": "+5511999888777",
  "metadata": { "priority": "urgent", "old_key": null }
}

Concorrência

O endpoint usa advisory locks no PostgreSQL para serializar operações concorrentes no mesmo par (canal + usuário), garantindo que mensagens simultâneas não criem sessões ou conversas duplicadas. Não é necessário implementar locking distribuído do lado do cliente.

On this page