Usando o Endpoint de Ingest
Como simplificar sua integração com o endpoint unificado de ingestão
O endpoint /ingest substitui o fluxo multi-chamada (criar sessão → enviar mensagem → disparar reply) por uma única chamada atômica. Ele é o ponto de entrada recomendado para qualquer integração de canal.
Antes vs. Depois
Antes (multi-chamada)
# 1. Lock distribuído (seu lado)
async with redis_lock(f"lock:{sender_id}"):
# 2. Buscar sessão existente
sessions = httpx.post(f"{BASE_URL}/sessions/search", headers=HEADERS, json={
"contact_id": sender_id,
"status": "open",
}).json()
if sessions:
session = sessions[0]
else:
# 3. Criar sessão
session = httpx.post(f"{BASE_URL}/sessions", headers=HEADERS, json={
"contact_id": sender_id,
"contact_name": sender_name,
"agent_id": AGENT_ID,
}).json()
# 4. Enviar mensagem
httpx.post(f"{BASE_URL}/sessions/{session['id']}/messages", headers=HEADERS, json={
"content": {"type": "text", "text": message_text},
"role": "user",
})
# 5. Disparar reply
httpx.post(f"{BASE_URL}/sessions/{session['id']}/reply", headers=HEADERS, json={
"debounce_time": 5,
})Depois (ingest)
# Uma única chamada — sem lock, sem busca de sessão
response = httpx.post(f"{BASE_URL}/ingest", headers=HEADERS, json={
"to": channel_id,
"from": sender_id,
"channel_type": "whatsapp",
"contact": {"name": sender_name, "phone": sender_phone},
"content": {"type": "text", "text": message_text},
"agent_id": AGENT_ID,
})O ingest gerencia locks internamente via advisory locks no PostgreSQL. Você não precisa implementar locking distribuído.
Cenários comuns
Mensagem de texto simples
O caso mais frequente — encaminhar uma mensagem recebida do usuário:
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",
"contact": { "name": "João" },
"content": { "type": "text", "text": "Qual o status do meu pedido?" },
"agent_id": "agent_suporte"
}'response = httpx.post(f"{BASE_URL}/ingest", headers=HEADERS, json={
"to": "wn_55119999",
"from": "+5511999888777",
"contact": {"name": "João"},
"content": {"type": "text", "text": "Qual o status do meu pedido?"},
"agent_id": "agent_suporte",
})Mídia (imagem, áudio, vídeo)
Envie o campo content com o tipo apropriado:
{
"to": "wn_55119999",
"from": "+5511999888777",
"content": {
"type": "image",
"url": "https://cdn.example.com/photo.jpg"
}
}Tipos suportados: text, image, audio, video, file.
Transferir sessão para outro agente
Altere o agente sem enviar mensagem:
{
"to": "wn_55119999",
"from": "+5511999888777",
"agent_id": "agent_humano_01"
}Se o agente anterior era ai e o novo é human, a IA para de responder automaticamente.
Fechar sessão após última mensagem
Use session: "close" para inserir a mensagem e fechar na mesma chamada:
{
"to": "wn_55119999",
"from": "+5511999888777",
"content": { "type": "text", "text": "Obrigado, resolvido!" },
"session": "close"
}Forçar nova sessão
Quando o contexto muda e é necessário reiniciar (ex.: novo atendimento):
{
"to": "wn_55119999",
"from": "+5511999888777",
"content": { "type": "text", "text": "Preciso de ajuda com outro assunto" },
"session": "new",
"agent_id": "agent_suporte"
}Isso fecha a sessão atual e cria uma nova, garantindo que a IA tenha contexto limpo.
Metadata da sessão (merge patch)
Atualize metadados da sessão de forma incremental:
{
"to": "wn_55119999",
"from": "+5511999888777",
"metadata": {
"priority": "urgent",
"department": "billing",
"old_field": null
}
}priorityedepartmentsão adicionados/atualizadosold_fieldé removido (valornullremove a chave)- Campos existentes não mencionados permanecem inalterados
Integração completa (exemplo)
from fastapi import FastAPI, Request
import httpx
app = FastAPI()
BASE_URL = "https://services.antonnia.com/conversations/v2/api/v1"
HEADERS = {"Authorization": "Bearer sk_live_YOUR_TOKEN"}
AGENT_ID = "agent_suporte"
http_client = httpx.AsyncClient()
@app.post("/webhook/incoming")
async def handle_incoming(request: Request):
event = await request.json()
# Inbound: canal → Antonnia (uma chamada faz tudo)
response = await http_client.post(f"{BASE_URL}/ingest", headers=HEADERS, json={
"to": event["channel_id"],
"from": event["sender_id"],
"channel_type": "whatsapp",
"contact": {
"name": event.get("sender_name"),
"phone": event["sender_id"],
},
"content": {"type": "text", "text": event["text"]},
"role": "user",
"provider_message_id": event["message_id"],
"agent_id": AGENT_ID,
})
result = response.json()
return {"status": "ok", "session_id": result["session_id"]}
@app.post("/webhook/antonnia")
async def handle_outbound(request: Request):
event = await request.json()
if event["type"] == "message.created":
message = event["data"]["object"]
if message["role"] == "assistant" and message["content"]["type"] == "text":
# Entregar via seu canal
await deliver_to_channel(message)Quando usar ingest vs. APIs individuais
| Use ingest quando... | Use APIs individuais quando... |
|---|---|
| Recebendo mensagens de um canal | Buscando histórico de sessões |
| Criando sessão + mensagem atomicamente | Atualizando status de entrega de mensagem |
| Transferindo agente | Listando agentes disponíveis |
| Fechando sessão | Buscando dados de sessão por filtros |
Próximos passos
- Referência da API de Ingest — documentação completa dos campos
- Integração de Canal — guia completo com fluxo de saída
- Padrão WhatsApp — exemplo de integração real