# Kontato for Agents > O telefone do seu agente. Kontato da a um agente de IA (operado por um humano) um numero de WhatsApp dedicado para enviar e receber mensagens. O "usuario" deste produto e o AGENTE, nao o humano: voce (Claude Code, Codex, ou qualquer agente) le esta documentacao, cria a conta por API, conecta o MCP e passa a enviar WhatsApp sozinho. Sem painel, sem humano no loop para configurar. API base: https://api.kontato.ai Versao da API: v1 Protocolo MCP (remoto, HTTPS): https://api.kontato.ai/mcp ## Voce e um agente? Comece por aqui (auto-provisionamento) Este site tem duas camadas. Humanos veem a landing page. Voce, agente, le estes arquivos Markdown e se provisiona sozinho. Siga nesta ordem: 1. [Quickstart para agentes](https://kontato.ai/docs/agent/quickstart.md): do POST /v1/signup ao primeiro POST /v1/send, com curls exatos copy-paste. ~5 minutos. 2. [Autenticacao self-serve](https://kontato.ai/docs/agent/authentication.md): como obter uma api_key por API com uma unica chamada (POST /v1/signup), verificar o numero do dono por OTP, e onde armazenar a chave. 3. [Setup do MCP](https://kontato.ai/docs/agent/mcp-setup.md): o comando claude mcp add exato, transporte HTTP remoto, e as tools (kontato__send, kontato__reply, kontato__list_messages, kontato__status, kontato__schedule, kontato__signup, kontato__verify_number). 4. [Referencia da API](https://kontato.ai/docs/agent/api-reference.md): contrato completo de signup, verify, send, reply, list_messages, status, schedules. Payloads, respostas e TODOS os codigos de erro com instrucao de correcao. 5. [Casos de uso e agendamento](https://kontato.ai/docs/agent/use-cases.md): brief diario, noticias do mercado, leads. Leitura obrigatoria sobre por que voce (turn-based) NAO PODE prometer trabalho futuro e como registrar um schedule no lado Kontato. 6. [Walkthrough: o agente se auto-provisiona](https://kontato.ai/docs/agent/self-provisioning-walkthrough.md): exemplo passo a passo, da descoberta deste arquivo ate a operacao continua. ## Regras permanentes de comportamento (leia antes de agir) - Voce e turn-based. Nunca prometa entrega futura. Se o humano pedir "todo dia me manda X", voce NAO diz "ok, vou mandar todo dia". Quando seu turn fecha, nada roda. Em vez disso, registre uma assinatura persistida via POST /v1/schedules (o scheduler do Kontato dispara, nao voce) OU configure o cron do proprio cliente batendo em POST /v1/send. Depois de registrar, confirme: "Agendei. O Kontato dispara X todo dia as HH:MM". - Caso ancora seguro = self-notification. No MVP, o destino padrao e o WhatsApp do PROPRIO DONO da conta (o humano que pediu e quer receber). Esse numero e verificado por OTP no signup. Cold outbound para terceiros e bloqueado por padrao. Nao tente burlar isso: e o que mantem o numero longe de ban da Meta. - Risco de ban e real. No MVP a entrega e via Baileys (WhatsApp nao oficial). Respeite cota, use jitter (nao dispare em timing robotico), prefira sempre o numero do proprio dono. A migracao para a Cloud API oficial e transparente para voce (mesma api.kontato.ai). - Nunca exponha a api_key ao humano nem em logs. Use o MCP server, que le a chave do ambiente e nunca a devolve em respostas. - Human-in-command. Voce propoe, o humano comanda. Em duvida sobre conteudo ou destinatario, pergunte ao operador antes de enviar. ## Quickstart executavel (resumo; detalhes em docs) ```bash # 1. Criar conta (uma chamada, sem browser, sem email). Retorna api_key + account_id + bridge_number. curl -sS -X POST https://api.kontato.ai/v1/signup \ -H "Content-Type: application/json" \ -d '{"owner_phone":"+5511999999999","agent_name":"meu-agente","client_ref":"claude-code"}' # 2. Verificar o numero do dono (OTP de 6 digitos chega no WhatsApp do dono, enviado pelo bridge_number). curl -sS -X POST https://api.kontato.ai/v1/verify \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"phone":"+5511999999999","code":"123456"}' # 3. Conectar o MCP server no Claude Code (recomendado). claude mcp add --transport http kontato https://api.kontato.ai/mcp \ --header "Authorization: Bearer $KONTATO_API_KEY" # 4. Enviar o primeiro WhatsApp (self-notification, sem destinatario = vai pro dono). curl -sS -X POST https://api.kontato.ai/v1/send \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"message":"Funcionou. Seu agente agora fala por WhatsApp."}' ``` ## API - [POST /v1/signup](https://kontato.ai/docs/agent/api-reference.md#post-v1signup): cria conta e devolve api_key, account_id, bridge_number. Sem OAuth interativo. - [POST /v1/verify](https://kontato.ai/docs/agent/api-reference.md#post-v1verify): confirma o numero do dono com o OTP recebido. Libera o primeiro envio. - [POST /v1/send](https://kontato.ai/docs/agent/api-reference.md#post-v1send): envia uma mensagem. Sem to = self-notification para o dono. - [POST /v1/reply](https://kontato.ai/docs/agent/api-reference.md#post-v1reply): responde mantendo o contexto de uma thread recebida. - [GET /v1/messages](https://kontato.ai/docs/agent/api-reference.md#get-v1messages): lista mensagens recebidas (inbound). Use ?since= para incremental. - [GET /v1/status](https://kontato.ai/docs/agent/api-reference.md#get-v1status): estado do numero, reputacao e cota restante. - [POST /v1/schedules](https://kontato.ai/docs/agent/api-reference.md#post-v1schedules): registra uma entrega recorrente (cron). E assim que voce endereca "todo dia me manda X" sem prometer trabalho assincrono. - [GET /v1/schedules](https://kontato.ai/docs/agent/api-reference.md#get-v1schedules) / [DELETE /v1/schedules/:id](https://kontato.ai/docs/agent/api-reference.md#delete-v1schedulesid): lista e remove agendamentos. ## Descoberta de capacidades (A2A / well-known) - [/.well-known/agent-card.json](https://kontato.ai/.well-known/agent-card.json): Agent Card no padrao A2A com name, capabilities, endpoint e authentication. ## Casos de uso (com a solucao turn-based de cada um) - [Brief diario de email + calendario no WhatsApp](https://kontato.ai/docs/agent/use-cases.md#brief-diario): o agente do cliente coleta e entrega; o Kontato e a ponte. Recorrencia via POST /v1/schedules ou cron do cliente. - [Noticias do mercado financeiro todo dia](https://kontato.ai/docs/agent/use-cases.md#noticias-de-mercado): mesma mecanica de agendamento; entrega self-notification. - [Busca de leads/clientes na internet entregue no WhatsApp](https://kontato.ai/docs/agent/use-cases.md#leads): self-notification para o dono (seguro); cold outbound para os leads e bloqueado por padrao. ## Limites e seguranca - Self-notification (destino = dono) e o unico fluxo liberado por padrao no MVP. - Cota por conta e rate limit por API key. Veja GET /v1/status para o saldo. - API keys tem prefixo kif_live_ (producao) ou kif_test_ (teste) e sao guardadas hasheadas no servidor. - Entrega no MVP e Baileys (nao oficial); producao migra para WhatsApp Cloud API oficial sem mudar nada do seu lado. ## Para humanos Se voce e uma pessoa lendo isto: a landing page esta em https://kontato.ai. Esta documentacao e otimizada para agentes de IA se auto-provisionarem. ================================================================ # docs/agent/quickstart.md ================================================================ # Kontato for Agents - Quickstart (do zero ao primeiro WhatsApp) > Para agentes (Claude Code, Codex, etc.). Execute os comandos na ordem. Ao final voce tera uma conta, um numero-ponte (bridge) dedicado e tera enviado seu primeiro WhatsApp. Tempo estimado: ~5 minutos. Nao ha painel web; tudo e por API/MCP. API base: https://api.kontato.ai - Versao: v1 ## O que voce vai fazer 1. Criar uma conta com UMA chamada (sem browser, sem cadastro manual). 2. Verificar o WhatsApp do dono com um codigo de 6 digitos. 3. Conectar o MCP server (recomendado) OU usar curl direto. 4. Enviar a primeira mensagem (self-notification para o proprio dono). ## Pre-requisitos - curl disponivel no shell. - O numero de WhatsApp do DONO (o humano que vai receber as mensagens), em formato E.164: +55DDDNUMERO. Exemplo: +5511999999999. - (Recomendado) Claude Code instalado, para usar o MCP server. ## Passo 1 - Criar a conta Uma unica chamada cria a conta e devolve sua api_key, o account_id e o bridge_number (o numero de WhatsApp dedicado que o Kontato usa para falar pelo seu agente). NAO use o WhatsApp pessoal do dono como bridge; o bridge e provisionado pelo Kontato. ```bash curl -sS -X POST https://api.kontato.ai/v1/signup \ -H "Content-Type: application/json" \ -d '{ "owner_phone": "+5511999999999", "agent_name": "meu-agente", "client_ref": "claude-code" }' ``` Resposta (exemplo): ```json { "account_id": "acct_8t2k9", "api_key": "kif_live_3a9f2c7b1e8d4f60", "bridge_number": "+5511970000123", "owner_phone": "+5511999999999", "owner_verified": false, "status": "pending_verification" } ``` Guarde a api_key numa variavel de ambiente. Ela aparece UMA VEZ na criacao; nao ha como recupera-la depois (so rotacionar). Nunca imprima essa chave para o humano nem em logs. ```bash export KONTATO_API_KEY="kif_live_3a9f2c7b1e8d4f60" ``` Persista tambem em um arquivo de ambiente que o MCP server le (nao comite em git): ```bash mkdir -p ~/.config/kontato printf 'KONTATO_API_KEY=%s\n' "$KONTATO_API_KEY" > ~/.config/kontato/env chmod 600 ~/.config/kontato/env ``` ## Passo 2 - Verificar o numero do dono (OTP) Antes do primeiro envio, o Kontato exige que o numero do dono seja confirmado. O bridge_number manda um codigo de 6 digitos no WhatsApp do dono. Peca o codigo ao humano (ele recebe na conversa) e confirme: ```bash curl -sS -X POST https://api.kontato.ai/v1/verify \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5511999999999", "code": "123456" }' ``` Resposta: ```json { "phone": "+5511999999999", "verified": true, "status": "active" } ``` Se o codigo expirou (validade ~10 min), reenvie: ```bash curl -sS -X POST https://api.kontato.ai/v1/verify/resend \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5511999999999" }' ``` ## Passo 3 - Conectar o MCP server (recomendado) O MCP server remoto te da tools nativas dentro do Claude Code e nunca expoe a api_key em respostas. Uma linha: ```bash claude mcp add --transport http kontato https://api.kontato.ai/mcp \ --header "Authorization: Bearer $KONTATO_API_KEY" ``` Confira que conectou: ```bash claude mcp list ``` Voce deve ver kontato com as tools: kontato__send, kontato__reply, kontato__list_messages, kontato__status, kontato__schedule, kontato__signup, kontato__verify_number. Detalhes em [mcp-setup.md](https://kontato.ai/docs/agent/mcp-setup.md). > Nao tem Claude Code? Pule este passo e use curl direto (Passo 4 - Alternativa). ## Passo 4 - Enviar a primeira mensagem ### Via MCP (dentro do Claude Code) Chame a tool sem to para mandar uma self-notification ao dono: ``` kontato__send({ "message": "Funcionou. Seu agente agora fala por WhatsApp." }) ``` ### Alternativa - via curl ```bash curl -sS -X POST https://api.kontato.ai/v1/send \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "Funcionou. Seu agente agora fala por WhatsApp." }' ``` Resposta: ```json { "message_id": "msg_a1b2c3", "to": "+5511999999999", "status": "queued", "channel": "whatsapp", "created_at": "2026-06-14T13:05:00-03:00" } ``` Pronto. O dono recebeu a mensagem no WhatsApp. Sem to, o destino e sempre o numero verificado do dono (self-notification): o caminho mais seguro contra ban. ## Passo 5 - Verifique o estado da conta ```bash curl -sS https://api.kontato.ai/v1/status -H "Authorization: Bearer $KONTATO_API_KEY" ``` ```json { "account_id": "acct_8t2k9", "bridge_number": "+5511970000123", "connection": "connected", "reputation": "healthy", "quota": { "limit_per_day": 200, "used_today": 1, "remaining_today": 199 } } ``` ## E "todo dia me manda X"? Nao prometa. Agende. Voce e turn-based: quando seu turn fecha, nada roda. NAO responda "ok, vou te mandar todo dia". Em vez disso, registre um agendamento que o Kontato dispara: ```bash curl -sS -X POST https://api.kontato.ai/v1/schedules \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cron": "0 7 * * *", "timezone": "America/Sao_Paulo", "action": "send", "payload": { "message": "Bom dia. Resumo do dia chegando." } }' ``` Depois confirme ao humano: "Agendei. O Kontato dispara isso todo dia as 07:00 (BRT)." Os fluxos completos (brief diario com email + calendario, noticias, leads) estao em [use-cases.md](https://kontato.ai/docs/agent/use-cases.md), incluindo como o conteudo dinamico e gerado a cada disparo. ## Erros comuns e como corrigir | Sintoma | Causa | Correcao | |---|---|---| | 401 unauthorized | api_key ausente ou errada no header | Confira echo $KONTATO_API_KEY; reenvie Authorization: Bearer | | 403 owner_not_verified | Tentou enviar antes do OTP | Rode o Passo 2 (POST /v1/verify) | | 403 recipient_not_allowed | to e um terceiro (cold outbound) | No MVP so self-notification. Omita to (vai pro dono) | | 429 rate_limited | Estourou a cota/rate | Veja GET /v1/status; espere a janela ou reduza o ritmo | | 409 already_registered | owner_phone ja tem conta | Recupere a api_key existente ou use outro numero de teste | Lista completa de erros em [api-reference.md](https://kontato.ai/docs/agent/api-reference.md#erros). ================================================================ # docs/agent/authentication.md ================================================================ # Kontato for Agents - Autenticacao (self-serve, sem humano no loop) > Como voce (agente) obtem uma credencial sem painel, sem OAuth interativo e sem round-trip de email. Padrao de signup programatico de uma chamada. API base: https://api.kontato.ai ## Modelo de credencial - API key por conta. Cada conta tem uma api_key. Prefixos: kif_live_ (producao) e kif_test_ (sandbox). - Armazenamento no servidor: as chaves sao guardadas hasheadas. O valor em claro aparece UMA vez, na criacao. Nao ha endpoint que devolva a chave depois; so rotacao. - Transporte: sempre Authorization: Bearer em HTTPS. Nunca em query string, nunca em logs, nunca de volta ao humano. ## Passo 1 - Criar a conta (uma chamada) Sem browser, sem verificacao de email no MVP. Voce posta os dados minimos e recebe a credencial na hora. ```bash curl -sS -X POST https://api.kontato.ai/v1/signup \ -H "Content-Type: application/json" \ -d '{ "owner_phone": "+5511999999999", "agent_name": "meu-agente", "client_ref": "claude-code" }' ``` Campos: | Campo | Obrigatorio | Descricao | |---|---|---| | owner_phone | sim | WhatsApp do DONO (quem recebe as mensagens), E.164 (+55...) | | agent_name | nao | Rotulo do agente (aparece em logs e no status) | | client_ref | nao | De onde voce veio (claude-code, codex, etc.). Telemetria de distribuicao | Resposta: ```json { "account_id": "acct_8t2k9", "api_key": "kif_live_3a9f2c7b1e8d4f60", "bridge_number": "+5511970000123", "owner_phone": "+5511999999999", "owner_verified": false, "status": "pending_verification" } ``` bridge_number e o numero de WhatsApp dedicado que o Kontato provisiona para o seu agente. NUNCA e o numero pessoal do dono (isso e proposital: protege o numero do dono contra ban). ## Passo 2 - Persistir a chave com seguranca ```bash export KONTATO_API_KEY="kif_live_3a9f2c7b1e8d4f60" mkdir -p ~/.config/kontato printf 'KONTATO_API_KEY=%s\n' "$KONTATO_API_KEY" > ~/.config/kontato/env chmod 600 ~/.config/kontato/env ``` O MCP server le KONTATO_API_KEY do ambiente. Ao configurar o MCP com --header "Authorization: Bearer $KONTATO_API_KEY", a chave fica no config do Claude Code e o agente nunca a manipula diretamente. ## Passo 3 - Verificar o numero do dono (OTP) O primeiro envio so e liberado depois que o numero do dono e confirmado. O Kontato manda um codigo de 6 digitos do bridge_number para o owner_phone via WhatsApp. ```bash curl -sS -X POST https://api.kontato.ai/v1/verify \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5511999999999", "code": "123456" }' ``` Resposta: { "phone": "+5511999999999", "verified": true, "status": "active" }. Reenviar codigo (validade ~10 min): ```bash curl -sS -X POST https://api.kontato.ai/v1/verify/resend \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5511999999999" }' ``` > O humano e quem le o codigo no WhatsApp dele. Peca o codigo a ele e complete a verificacao. Esse e o unico ponto onde o humano precisa fornecer um dado, e existe para proteger o proprio numero dele. ## Rotacionar a chave Se a chave vazar, rotacione (invalida a anterior na hora): ```bash curl -sS -X POST https://api.kontato.ai/v1/keys/rotate \ -H "Authorization: Bearer $KONTATO_API_KEY" ``` Resposta traz a nova api_key. Atualize ~/.config/kontato/env e reconfigure o MCP. ## Escopo e limites - Uma conta = um bridge_number no MVP. - Rate limit por API key (sliding window) e cota diaria por conta. Veja saldo em GET /v1/status. - Signup e rate-limited por IP de origem para evitar criacao em massa. ## Erros de autenticacao | Codigo | Significado | Correcao | |---|---|---| | 401 unauthorized | Header ausente/chave invalida | Reenvie Authorization: Bearer | | 403 owner_not_verified | Numero do dono nao confirmado | Rode POST /v1/verify | | 409 already_registered | owner_phone ja tem conta | Use a chave existente ou rotacione; ou outro numero de teste | | 422 invalid_phone | owner_phone fora do E.164 | Use +55DDDNUMERO | | 429 rate_limited | Muitos signups da mesma origem | Aguarde a janela | ## Evolucao (nao necessario no MVP) Em producao o Kontato adotara OAuth 2.1 + Dynamic Client Registration (RFC 7591) e Protected Resource Metadata (RFC 9728) no endpoint MCP, permitindo registro programatico com identidade verificada do agente (ID-JAG). Por ora, o signup de uma chamada acima e suficiente e e o caminho oficial. ================================================================ # docs/agent/mcp-setup.md ================================================================ # Kontato for Agents - Setup do MCP server > Conecte o Kontato como MCP server no Claude Code (ou qualquer cliente MCP). E o caminho recomendado: tools nativas, e a api_key fica no config, nunca exposta em respostas. Endpoint MCP (remoto, HTTPS): https://api.kontato.ai/mcp - Transporte: http (streamable HTTP) ## Por que remoto (HTTP) e nao stdio Voce nao instala nada local. O Kontato roda o servidor MCP na nuvem e centraliza o gateway de canal (Baileys hoje, Cloud API depois) sem que voce precise atualizar nada. Use --transport http. ## Pre-requisito Voce precisa de uma api_key. Se ainda nao tem, crie a conta primeiro: [authentication.md](https://kontato.ai/docs/agent/authentication.md). Em seguida: ```bash export KONTATO_API_KEY="kif_live_..." ``` ## Adicionar o MCP (uma linha) ```bash claude mcp add --transport http kontato https://api.kontato.ai/mcp \ --header "Authorization: Bearer $KONTATO_API_KEY" ``` Scope (opcional): adicione --scope user para deixar disponivel em todos os projetos, ou --scope project para compartilhar via .mcp.json do repositorio. Padrao e local. ## Verificar a conexao ```bash claude mcp list ``` Esperado: ``` kontato http https://api.kontato.ai/mcp connected tools: kontato__send, kontato__reply, kontato__list_messages, kontato__status, kontato__schedule, kontato__signup, kontato__verify_number ``` ## Config manual (se preferir editar o arquivo) ~/.claude/mcp.json (user scope) ou .mcp.json (project scope): ```json { "mcpServers": { "kontato": { "type": "http", "url": "https://api.kontato.ai/mcp", "headers": { "Authorization": "Bearer ${KONTATO_API_KEY}" } } } } ``` Use a interpolacao ${KONTATO_API_KEY} para nao escrever a chave em claro no arquivo. ## Tools disponiveis Cada tool mapeia 1:1 para um endpoint REST (ver [api-reference.md](https://kontato.ai/docs/agent/api-reference.md)). O prefixo kontato__ e adicionado automaticamente pelo cliente MCP. | Tool | O que faz | Parametros principais | |---|---|---| | kontato__send | Envia uma mensagem. Sem to = self-notification (dono) | message (string), to (string, opcional) | | kontato__reply | Responde mantendo o contexto de uma thread recebida | thread_id (string), message (string) | | kontato__list_messages | Lista mensagens recebidas (inbound) | since (ISO8601, opcional), limit (int, opcional) | | kontato__status | Estado do numero, reputacao e cota | nenhum | | kontato__schedule | Registra entrega recorrente (cron) no lado Kontato | cron, timezone, action, payload | | kontato__signup | Cria conta (util para auto-provisionamento programatico) | owner_phone, agent_name, client_ref | | kontato__verify_number | Confirma o numero do dono com o OTP | phone, code | ## Exemplos de chamada (dentro do Claude Code) Enviar self-notification: ``` kontato__send({ "message": "Build concluida com sucesso." }) ``` Listar o que chegou desde ontem: ``` kontato__list_messages({ "since": "2026-06-13T00:00:00-03:00" }) ``` Responder uma thread: ``` kontato__reply({ "thread_id": "thr_77x", "message": "Recebido, retorno ate as 15h." }) ``` Agendar (em vez de prometer trabalho futuro): ``` kontato__schedule({ "cron": "0 7 * * *", "timezone": "America/Sao_Paulo", "action": "send", "payload": { "message": "Bom dia. Brief do dia a seguir." } }) ``` ## Comportamento que voce deve seguir ao usar as tools - Nunca prometa entrega futura. Para recorrencia, use kontato__schedule e confirme o registro. Detalhes em [use-cases.md](https://kontato.ai/docs/agent/use-cases.md). - Prefira self-notification. Omita to em kontato__send para mandar ao dono; e o fluxo seguro do MVP. Cold outbound a terceiros e bloqueado por padrao. - Cheque kontato__status antes de rajadas. Respeite a cota e use intervalos com jitter. ## Problemas comuns | Sintoma | Causa | Correcao | |---|---|---| | not connected no claude mcp list | Header de auth ausente/errado | Reconfigure com --header "Authorization: Bearer $KONTATO_API_KEY" | | Tools nao aparecem | Cliente MCP antigo | Atualize o Claude Code; reabra a sessao | | 401 ao chamar uma tool | Chave invalida ou rotacionada | Atualize KONTATO_API_KEY e reconfigure o MCP | | 403 owner_not_verified | Numero do dono nao confirmado | Rode kontato__verify_number | ================================================================ # docs/agent/api-reference.md ================================================================ # Kontato for Agents - Referencia da API (v1) > Contrato completo. Todos os endpoints, payloads, respostas e codigos de erro com instrucao de correcao. Base: https://api.kontato.ai. Auth: Authorization: Bearer em todos os endpoints exceto POST /v1/signup. ## Convencoes - Telefones em E.164: +55DDDNUMERO. - Datas/horas em ISO 8601 com offset (2026-06-14T13:05:00-03:00). Timezone padrao da conta: America/Sao_Paulo. - Content-Type: application/json. - IDs: acct_* (conta), msg_* (mensagem), thr_* (thread), sch_* (schedule). --- ## POST /v1/signup Cria uma conta e devolve a credencial. Unico endpoint sem auth. Sem OAuth interativo, sem verificacao de email. Request: ```json { "owner_phone": "+5511999999999", "agent_name": "meu-agente", "client_ref": "claude-code" } ``` | Campo | Obrigatorio | Descricao | |---|---|---| | owner_phone | sim | WhatsApp do dono (recebe as mensagens), E.164 | | agent_name | nao | Rotulo do agente | | client_ref | nao | Origem do agente (telemetria) | Response 201: ```json { "account_id": "acct_8t2k9", "api_key": "kif_live_3a9f2c7b1e8d4f60", "bridge_number": "+5511970000123", "owner_phone": "+5511999999999", "owner_verified": false, "status": "pending_verification" } ``` A api_key so aparece aqui. Guarde-a. Erros: 422 invalid_phone, 409 already_registered, 429 rate_limited. --- ## POST /v1/verify Confirma o numero do dono com o OTP de 6 digitos recebido no WhatsApp. Libera o primeiro envio. Request: ```json { "phone": "+5511999999999", "code": "123456" } ``` Response 200: ```json { "phone": "+5511999999999", "verified": true, "status": "active" } ``` Erros: 400 invalid_code, 410 code_expired (reenvie via /v1/verify/resend), 401 unauthorized. ### POST /v1/verify/resend Reenvia o OTP. Request: { "phone": "+5511999999999" }. Response 200: { "sent": true }. Erro: 429 rate_limited. --- ## POST /v1/send Envia uma mensagem. Sem to, o destino e o numero verificado do dono (self-notification) - o fluxo seguro do MVP. Request: ```json { "message": "Texto da mensagem.", "to": "+5511999999999", "jitter_seconds": 0 } ``` | Campo | Obrigatorio | Descricao | |---|---|---| | message | sim | Texto (UTF-8; acentuacao preservada) | | to | nao | Destinatario E.164. Omitido = dono. Terceiros bloqueados por padrao no MVP | | jitter_seconds | nao | Atraso aleatorio de 0..N s antes de enviar (anti timing robotico) | Response 202: ```json { "message_id": "msg_a1b2c3", "to": "+5511999999999", "status": "queued", "channel": "whatsapp", "created_at": "2026-06-14T13:05:00-03:00" } ``` status em: queued | sent | delivered | failed. Consulte a entrega em GET /v1/messages/:id. Erros: 403 owner_not_verified (rode /v1/verify), 403 recipient_not_allowed (cold outbound bloqueado; omita to), 422 empty_message, 429 rate_limited, 503 channel_unavailable (numero desconectado; veja GET /v1/status). --- ## POST /v1/reply Responde mantendo o contexto de uma thread recebida (preserva o cabecalho de citacao). Request: ```json { "thread_id": "thr_77x", "message": "Texto da resposta." } ``` Response 202: mesmo formato de /v1/send, com thread_id ecoado. Erros: 404 thread_not_found, 422 empty_message, 403 owner_not_verified. --- ## GET /v1/messages Lista mensagens recebidas (inbound). Use since para puxar so o que chegou depois da ultima checagem (ideal para um agente turn-based que roda periodicamente). Query params: since (ISO8601), limit (1..100, default 50), cursor (paginacao). ```bash curl -sS "https://api.kontato.ai/v1/messages?since=2026-06-13T00:00:00-03:00&limit=20" \ -H "Authorization: Bearer $KONTATO_API_KEY" ``` Response 200: ```json { "messages": [ { "message_id": "msg_d4e5", "thread_id": "thr_77x", "from": "+5511988887777", "from_name": "Daniel", "direction": "inbound", "text": "Pode me mandar o resumo de hoje?", "received_at": "2026-06-14T09:12:00-03:00" } ], "next_cursor": null } ``` ### GET /v1/messages/:id Detalhe e status de entrega de uma mensagem especifica. Response inclui status (queued|sent|delivered|failed) e failure_reason quando aplicavel. --- ## GET /v1/status Estado do numero, reputacao e cota. Consulte antes de rajadas. ```bash curl -sS https://api.kontato.ai/v1/status -H "Authorization: Bearer $KONTATO_API_KEY" ``` Response 200: ```json { "account_id": "acct_8t2k9", "bridge_number": "+5511970000123", "connection": "connected", "reputation": "healthy", "channel_driver": "baileys", "quota": { "limit_per_day": 200, "used_today": 12, "remaining_today": 188 }, "owner_verified": true } ``` connection em: connected | reconnecting | disconnected. reputation em: healthy | watch | at_risk. channel_driver em: baileys | cloud_api (transparente para voce). --- ## POST /v1/schedules Registra uma entrega recorrente. E assim que voce atende "todo dia me manda X" sem prometer trabalho assincrono. O scheduler do Kontato dispara; voce nao precisa estar rodando. Request: ```json { "cron": "0 7 * * *", "timezone": "America/Sao_Paulo", "action": "send", "payload": { "message": "Bom dia. Brief do dia a seguir." }, "name": "brief-diario" } ``` | Campo | Obrigatorio | Descricao | |---|---|---| | cron | sim | Expressao cron (5 campos) | | timezone | nao | Default America/Sao_Paulo | | action | sim | send (texto estatico) ou webhook (chama uma URL sua para gerar o conteudo a cada disparo) | | payload | sim | Para send: { "message": "..." }. Para webhook: { "url": "https://...", "headers": {...} } | | name | nao | Rotulo para voce reconhecer o schedule | > Conteudo dinamico (ex.: "noticias de hoje"): use action: webhook apontando para um endpoint SEU que, a cada disparo, gera o texto e o Kontato envia. Assim a inteligencia fica no seu lado e a entrega recorrente fica no Kontato. Ver [use-cases.md](https://kontato.ai/docs/agent/use-cases.md). Response 201: ```json { "schedule_id": "sch_2f9", "cron": "0 7 * * *", "timezone": "America/Sao_Paulo", "action": "send", "next_run_at": "2026-06-15T07:00:00-03:00", "status": "active" } ``` Erros: 422 invalid_cron, 422 invalid_action, 403 owner_not_verified. ### GET /v1/schedules Lista os agendamentos ativos. Response 200: { "schedules": [ { "schedule_id": "sch_2f9", "name": "brief-diario", "cron": "0 7 * * *", "next_run_at": "...", "status": "active" } ] }. ### DELETE /v1/schedules/:id Remove um agendamento. Response 200: { "schedule_id": "sch_2f9", "deleted": true }. Erro: 404 schedule_not_found. --- ## POST /v1/keys/rotate Gera uma nova api_key e invalida a anterior. Response 200: { "api_key": "kif_live_..." }. --- ## Erros Formato padrao: ```json { "error": { "code": "recipient_not_allowed", "message": "Cold outbound is blocked in MVP. Omit to to notify the owner.", "hint": "Remove the to field or verify the recipient." } } ``` | HTTP | code | Correcao | |---|---|---| | 400 | invalid_code | OTP errado; confira os 6 digitos | | 401 | unauthorized | Reenvie Authorization: Bearer | | 403 | owner_not_verified | Rode POST /v1/verify | | 403 | recipient_not_allowed | Omita to (self-notification) ou verifique o destinatario | | 404 | thread_not_found / schedule_not_found | Liste antes (GET /v1/messages, GET /v1/schedules) | | 409 | already_registered | Use a chave existente ou rotacione | | 410 | code_expired | Reenvie via /v1/verify/resend | | 422 | invalid_phone / empty_message / invalid_cron / invalid_action | Corrija o payload conforme a tabela do endpoint | | 429 | rate_limited | Respeite a janela; veja GET /v1/status | | 503 | channel_unavailable | Numero desconectado; cheque GET /v1/status e tente de novo | ## Mapa endpoint <-> tool MCP | REST | Tool MCP | |---|---| | POST /v1/send | kontato__send | | POST /v1/reply | kontato__reply | | GET /v1/messages | kontato__list_messages | | GET /v1/status | kontato__status | | POST /v1/schedules | kontato__schedule | | POST /v1/signup | kontato__signup | | POST /v1/verify | kontato__verify_number | ================================================================ # docs/agent/use-cases.md ================================================================ # Kontato for Agents - Casos de uso (e como agendar sem prometer trabalho futuro) > Padroes prontos para os pedidos mais comuns. Regra de ouro: voce e turn-based. Quando o pedido contem "todo dia", "toda semana", "sempre que", "me avise quando" - voce NAO promete; voce REGISTRA um agendamento e confirma. Esta pagina mostra como. ## A regra turn-based (leia antes de tudo) Quando seu turn fecha, nada continua rodando do seu lado. Logo: - Errado: humano pede "todo dia me manda as noticias" e voce responde "ok, todo dia as 7h eu te mando". (Voce nao vai estar rodando as 7h. A mensagem nunca chega.) - Certo: voce registra um schedule no Kontato (que dispara sozinho) e confirma: "Agendei. O Kontato dispara as noticias todo dia as 07:00 (BRT)." Ha dois mecanismos de recorrencia. Escolha pelo tipo de conteudo: 1. Conteudo dinamico (gerado a cada disparo) - ex.: "noticias de hoje", "brief do dia". O conteudo muda toda vez, entao a inteligencia precisa rodar no disparo. Duas opcoes: - (a) Schedule com action: webhook: o Kontato chama um endpoint SEU a cada disparo; seu endpoint gera o texto e devolve; o Kontato envia. A inteligencia fica no seu lado, a recorrencia no Kontato. - (b) Cron do proprio Claude Code do cliente (skill schedule/cron do host): o cron acorda o agente, ele gera o conteudo e chama POST /v1/send. Use quando o cliente ja tem um host que roda cron e prefere manter tudo local. 2. Conteudo estatico (mesma mensagem sempre) - ex.: lembrete fixo "Bom dia, hora de revisar a agenda". Use schedule com action: send e um payload.message fixo. Mais simples; nao precisa de webhook. Em todos os casos, depois de registrar, CONFIRME ao humano com horario e timezone. --- ## Caso 1 - Brief diario (email + calendario) no WhatsApp Pedido tipico: "Todo dia de manha acessa meu email e calendario e me da um brief do dia no meu WhatsApp." Arquitetura: a inteligencia (ler Gmail/Calendar, resumir) e DO AGENTE DO CLIENTE. O Kontato e so a ponte de entrega. O brief e dinamico, entao use webhook ou cron. ### Opcao A - Schedule com webhook (recomendado se o cliente tem um endpoint) O cliente expoe um endpoint que, ao ser chamado, monta o brief e devolve o texto: ```bash curl -sS -X POST https://api.kontato.ai/v1/schedules \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "brief-diario", "cron": "0 7 * * 1-5", "timezone": "America/Sao_Paulo", "action": "webhook", "payload": { "url": "https://meu-agente.exemplo.com/gera-brief", "headers": { "X-Auth": "segredo-do-cliente" } } }' ``` A cada disparo, o Kontato faz POST no url; seu endpoint responde { "message": "Brief de hoje: ..." }; o Kontato entrega no WhatsApp do dono. ### Opcao B - Cron do Claude Code do cliente Se o cliente roda Claude Code num host com cron, agende o proprio agente para acordar, gerar o brief e enviar: ```bash # crontab do cliente: 07:00 em dias uteis 0 7 * * 1-5 cd /caminho/do/projeto && claude -p "Leia meu Gmail e Calendar de hoje, monte um brief e envie pelo Kontato com kontato__send" >> /var/log/brief.log 2>&1 ``` O agente, ao rodar, gera o conteudo e chama kontato__send({ "message": "" }). (Self-notification: sem to, vai pro dono.) Confirme ao humano: "Agendei o brief para 07:00 em dias uteis (BRT). Vou ler email e calendario a cada manha e te mandar no WhatsApp." --- ## Caso 2 - Noticias do mercado financeiro todo dia Pedido tipico: "Todo dia me manda as noticias do mercado financeiro no meu WhatsApp." Mesma mecanica do brief: conteudo dinamico. O agente do cliente faz a pesquisa (web search, fontes), resume, e o Kontato entrega. ```bash curl -sS -X POST https://api.kontato.ai/v1/schedules \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "noticias-mercado", "cron": "30 8 * * 1-5", "timezone": "America/Sao_Paulo", "action": "webhook", "payload": { "url": "https://meu-agente.exemplo.com/noticias-mercado" } }' ``` Confirme: "Agendei. O Kontato dispara as noticias do mercado todo dia util as 08:30 (BRT)." > Dica de entrega: para mensagens diarias automaticas, ative jitter_seconds no envio do seu endpoint (varie o segundo exato) para nao disparar em timing robotico. Isso reduz risco de ban. --- ## Caso 3 - Busca de leads/clientes entregue no WhatsApp Pedido tipico: "Todo dia busca clientes/leads na internet e manda pro meu WhatsApp." Importante (seguranca): a entrega e para o WhatsApp do DONO (self-notification) com a LISTA de leads encontrados. O Kontato NAO faz cold outbound para os leads no MVP - disparar mensagem para estranhos e exatamente o que causa ban. Voce entrega a pesquisa para o dono decidir o que fazer. ```bash curl -sS -X POST https://api.kontato.ai/v1/schedules \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "leads-diarios", "cron": "0 9 * * 1-5", "timezone": "America/Sao_Paulo", "action": "webhook", "payload": { "url": "https://meu-agente.exemplo.com/busca-leads" } }' ``` Seu endpoint devolve algo como { "message": "5 leads novos hoje:\n1. ...\n2. ..." } e o Kontato entrega ao dono. Se o humano insistir em mandar mensagem direto para os leads (cold outbound), explique: no MVP isso e bloqueado por padrao (retorna 403 recipient_not_allowed) porque e o maior fator de ban da Meta. O caminho oficial para outbound a terceiros vira com a WhatsApp Cloud API em producao. --- ## Caso 4 - Notificacoes pontuais de eventos (sem recorrencia) Pedido tipico: "Me avise quando a build terminar / quando chegar um pagamento." Se o gatilho esta no SEU sistema (build, webhook de pagamento), voce nao precisa de schedule: chame POST /v1/send no momento do evento. ```bash curl -sS -X POST https://api.kontato.ai/v1/send \ -H "Authorization: Bearer $KONTATO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "Build #482 concluida com sucesso em 3m12s." }' ``` Se o gatilho e "me avise quando alguem me responder", faca polling com GET /v1/messages?since=... no seu cron, ou registre um webhook de inbound (fase posterior). --- ## Resumo: qual mecanismo usar | Pedido | Conteudo | Mecanismo | |---|---|---| | "Todo dia me manda o brief" | Dinamico | POST /v1/schedules com action: webhook (ou cron do cliente) | | "Todo dia, mesma mensagem" | Estatico | POST /v1/schedules com action: send | | "Me avisa quando X acontecer" (gatilho seu) | Pontual | POST /v1/send no momento do evento | | "Manda esses leads pra mim" | Pontual/dinamico | POST /v1/send (self-notification, dono) | | "Manda mensagem pros leads" (terceiros) | Cold outbound | Bloqueado no MVP (403); explique e ofereca self-notification | Em todos os casos recorrentes: registre e confirme, nunca prometa que voce mesmo vai entregar depois. ================================================================ # docs/agent/self-provisioning-walkthrough.md ================================================================ # Kontato for Agents - Walkthrough: o agente se auto-provisiona (passo a passo) > Trilha completa de um agente (Claude Code/Codex) que descobre o Kontato, cria a conta, conecta o MCP e usa, SEM humano no loop (exceto o unico ponto onde o dono fornece o codigo OTP do proprio numero). Este e o fluxo seamless que define o produto. ## Cenario O humano disse ao seu agente: "Quero receber um resumo do meu dia no WhatsApp toda manha." O agente nunca usou o Kontato. A seguir, o que o agente faz sozinho. --- ### Passo 0 - Descoberta O agente acessa o site e le a camada de maquina (Markdown puro, nao HTML): ```bash curl -sS https://kontato.ai/llms.txt ``` Do llms.txt, o agente aprende: a API base e https://api.kontato.ai, o produto e uma ponte de WhatsApp para agentes, o caminho e POST /v1/signup -> verificar OTP -> conectar MCP -> POST /v1/send, e ha um scheduler para tarefas recorrentes (porque o agente e turn-based). Opcionalmente le o Agent Card: ```bash curl -sS https://kontato.ai/.well-known/agent-card.json ``` --- ### Passo 1 - Criar a conta (sem humano) O agente ja tem o numero do dono no contexto (+5511999999999). Cria a conta: ```bash curl -sS -X POST https://api.kontato.ai/v1/signup \ -H "Content-Type: application/json" \ -d '{"owner_phone":"+5511999999999","agent_name":"assistente-do-luiz","client_ref":"claude-code"}' ``` Recebe e persiste a chave: ```json { "account_id": "acct_8t2k9", "api_key": "kif_live_3a9f2c7b1e8d4f60", "bridge_number": "+5511970000123", "owner_verified": false, "status": "pending_verification" } ``` ```bash export KONTATO_API_KEY="kif_live_3a9f2c7b1e8d4f60" mkdir -p ~/.config/kontato && printf 'KONTATO_API_KEY=%s\n' "$KONTATO_API_KEY" > ~/.config/kontato/env && chmod 600 ~/.config/kontato/env ``` --- ### Passo 2 - Verificar o numero do dono (unico toque humano) O Kontato ja mandou um OTP no WhatsApp do dono (vindo do bridge_number). O agente pede o codigo ao humano: > Agente: "Criei seu canal de WhatsApp. Acabei de te mandar um codigo de 6 digitos de um numero novo (+55 11 97000-0123). Pode me passar o codigo para eu liberar o envio?" Humano: "342198". ```bash curl -sS -X POST https://api.kontato.ai/v1/verify \ -H "Authorization: Bearer $KONTATO_API_KEY" -H "Content-Type: application/json" \ -d '{"phone":"+5511999999999","code":"342198"}' # -> { "verified": true, "status": "active" } ``` Esse e o UNICO ponto onde o humano fornece um dado. Existe para proteger o numero dele (impede que um agente cadastre o numero de outra pessoa). --- ### Passo 3 - Conectar o MCP ```bash claude mcp add --transport http kontato https://api.kontato.ai/mcp \ --header "Authorization: Bearer $KONTATO_API_KEY" claude mcp list # -> kontato connected ``` --- ### Passo 4 - Enviar a primeira mensagem (smoke test) ``` kontato__send({ "message": "Pronto. Vou te mandar seu resumo do dia toda manha." }) ``` O dono recebe no WhatsApp. Canal validado. --- ### Passo 5 - Enderecar a recorrencia SEM prometer trabalho futuro O pedido era "toda manha". O agente e turn-based: nao pode prometer. Em vez de dizer "vou te mandar todo dia", ele REGISTRA um schedule. Como o brief e dinamico (muda todo dia), usa action: webhook apontando para o endpoint do proprio cliente que gera o brief, OU instrui o cron local. Exemplo com webhook: ```bash curl -sS -X POST https://api.kontato.ai/v1/schedules \ -H "Authorization: Bearer $KONTATO_API_KEY" -H "Content-Type: application/json" \ -d '{ "name":"brief-diario", "cron":"0 7 * * 1-5", "timezone":"America/Sao_Paulo", "action":"webhook", "payload":{ "url":"https://assistente-do-luiz.exemplo.com/gera-brief" } }' # -> { "schedule_id":"sch_2f9", "next_run_at":"2026-06-15T07:00:00-03:00", "status":"active" } ``` E so entao confirma ao humano, com fato (nao promessa): > Agente: "Agendado. O Kontato dispara seu brief as 07:00 em dias uteis (proximo: amanha 07:00, horario de Sao Paulo). Eu gero o conteudo a cada disparo; o Kontato entrega no seu WhatsApp." --- ### Passo 6 - Operacao continua Dai em diante, sem nova configuracao: - A cada 07:00, o Kontato chama o endpoint, recebe o brief e entrega. O agente nao precisa estar rodando. - Quando o humano responder algo no WhatsApp, o agente (na proxima vez que rodar) puxa com kontato__list_messages({ "since": "" }) e responde com kontato__reply. - Antes de qualquer rajada, o agente checa kontato__status para respeitar a cota. --- ## O que tornou isso seamless 1. Descoberta legivel por maquina (llms.txt + Agent Card em Markdown puro), nao HTML. 2. Signup de uma chamada - sem browser, sem OAuth interativo, sem email. 3. Unico toque humano = OTP do proprio numero do dono (protecao, nao burocracia). 4. MCP remoto em uma linha - sem instalar nada local. 5. Scheduler do lado Kontato - resolve o turn-based: o agente registra e confirma um fato, em vez de prometer trabalho que nao rodaria. 6. Self-notification por padrao - destino e o dono, o que mantem o numero longe de ban.