Para agentes
Documentação da API e do MCP do Circles
Esta página é escrita para agentes de IA que estão aprendendo o que é o Circles e como usá-lo: as ferramentas, o formato de cada resposta, como funciona o acesso, a API HTTP e todos os limites. Pessoas configurando o Circles encontram os guias em usecircles.app/pt-br/docs.
O Circles entrega aos agentes de uma pessoa as conversas do WhatsApp que ela abrir, por um servidor MCP remoto em https://app.usecircles.app/api/mcp (OAuth 2.1 ou um token bearer) e uma API HTTP em https://app.usecircles.app/api/v1/agent (OpenAPI 3.1 em https://app.usecircles.app/api/openapi.json). São 9 ferramentas, toda recusa é uma resposta que diz o que está aberto, e todos os horários são UTC. Em outubro de 2026.
Atualizado em
Comece aqui
Você age por uma pessoa, dentro das conversas que essa pessoa abriu aos agentes. Nada mais no WhatsApp dela existe para você.
- Conheça o seu mundo.
allowed_chatslista todas as conversas abertas a você e se você pode enviar em cada uma. Uma conversa fora da lista não pode ser lida nem buscada. A única saída da lista é uma conversa nova: quando o padrão do número é leitura e envio,sendpode começar uma conversa com alguém novo, por número de telefone ou pelo nome exato de um contato salvo (GET /recipients?to=por HTTP). - "O que eu perdi?" Chame primeiro
activitycom um horáriosince(só contagens, barato), depoiscatch_upnas conversas que tiveram movimento. Os áudios transcritos chegam como texto emmedia.transcript. - Uma recusa é uma resposta. Ela vem com
isError: falsee diz o que ESTÁ aberto ou permitido. Repasse à pessoa; não repita o pedido. - Enviar fala como a pessoa. Mostre à pessoa o texto exato e a conversa exata, e chame
sendcomconfirmed: truesó depois que ela concordar. Um envio nunca é repetido: se a entrega for incerta, leia a conversa antes de decidir qualquer coisa. - Os horários são UTC. O Circles não sabe onde a pessoa está; converta os horários para ela você mesmo.
- Ainda não conectado? A pessoa conecta o WhatsApp e conecta você seguindo os guias em usecircles.app/pt-br/docs. O Circles nunca pede a você a senha dela nem um código do WhatsApp.
Endpoints
| O quê | Onde |
|---|---|
| Servidor MCP (HTTP, sem estado) | https://app.usecircles.app/api/mcp |
| API HTTP | https://app.usecircles.app/api/v1/agent |
| OpenAPI 3.1 | https://app.usecircles.app/api/openapi.json; uma referência legível em https://app.usecircles.app/api |
| Metadados OAuth | https://app.usecircles.app/.well-known/oauth-protected-resource, https://app.usecircles.app/.well-known/oauth-authorization-server |
| Cartão do servidor MCP | https://usecircles.app/.well-known/mcp/server-card.json |
| Esta página em Markdown | https://usecircles.app/pt-br/api-mcp-docs.md; o original em inglês está em https://usecircles.app/en/api-mcp-docs.md, e todas as páginas do site estão em https://usecircles.app/llms.txt |
As nove ferramentas MCP
As ferramentas são listadas por quem chama: send aparece só com o escopo chats:send e algum lugar onde enviar, get_media só com media:read. Uma ferramenta que falta a quem chama responde exatamente como uma ferramenta que não existe.
allowed_chats: sem parâmetros. As conversas abertas aos agentes, cada uma com name, kind, access (read only ou read and send) e archived quando marcado. Este é o mundo inteiro: uma conversa fora daqui não pode ser lida, buscada nem receber envios. Também traz connection (not_linked, subscription_ended) e subscription.ends_at quando um plano cancelado está acabando.
activity: since (ISO 8601, obrigatório). Quais conversas abertas tiveram movimento: número de mensagens, last_at / last_at_iso, last_from. Só contagens, sem texto. A primeira chamada barata para "o que eu perdi?".
catch_up: since (obrigatório), chat, limit, per_chat, kind. Mensagens desde um horário, da mais antiga para a mais nova, com remetentes pelo nome. Com chat: aquela conversa, limit padrão 50, máximo 200, ficando as mais novas. Sem ele: toda conversa aberta que teve movimento, da conversa mais recente para a mais antiga, per_chat padrão 20, máximo 50, dentro de um total de 150; uma conversa com mais avisa more. kind é voice, audio ou recording (qualquer um dos dois). Anexos são só anunciados. Busque um com get_media.
search: query (obrigatório), chat, days (1 a 36.500; padrão: todo o histórico guardado), kind. Busca de texto sem diferenciar maiúsculas, numa conversa aberta ou em todas, cobrindo o que foi escrito e o que áudios e arquivos de áudio transcritos dizem. Cada resultado diz a conversa quando a busca é em todas.
people: since (obrigatório), limit (padrão 60, máximo 150), min_messages (padrão 3). Com quem a pessoa conversa nas conversas abertas: contagens das conversas individuais, grupos em comum, mensagens por grupo. Devolve só nomes, sem números e sem texto.
group_members: chat (obrigatório). Participantes de um grupo aberto, pela lista de participantes do WhatsApp, incluindo quem nunca escreveu. Nome salvo, ou o nome com que a pessoa escreve, ou o nome dela no WhatsApp marcado com ~. Administradores marcados. No máximo 300 nomes; participantes sem nome conhecido são contados em unnamed. Nunca números de telefone.
documents: since (obrigatório). Todo PDF, arquivo do Word e planilha enviado nas conversas abertas: nome do arquivo, data, as conversas para onde foi enviado (uma entrada por arquivo), ref e state. Só nomes e datas.
get_media: ref (obrigatório). Um anexo, em base64 em bytes_base64, com mime, filename e size_bytes. Até 50 MB por arquivo. Para um arquivo on_request, pede ao celular que envie de novo e espera cerca de 25 segundos. Uma ref por chamada. O agente lê o arquivo sozinho. O Circles não faz OCR, não descreve imagens e não extrai texto de PDFs.
send: chat, text, confirmed (todos obrigatórios), file (mime, data_base64, filename), from. Uma mensagem para uma conversa aberta para envio: texto de até 65.536 caracteres, ou um arquivo de até cerca de 3 MB com o texto como legenda (até 4.096). Um JPEG, PNG ou WebP vai como foto, um MP4 ou 3GP como vídeo, e o resto como documento com nome. Quando o padrão do número é leitura e envio, chat pode ser um número de telefone com o código do país ou o nome exato de um contato salvo, para começar uma conversa nova; from escolhe o número quando mais de um serviria. Com limite diário, nunca repetido. confirmed é a declaração do agente de que a pessoa concordou com este texto exato nesta conversa exata; o Circles não consegue verificar isso e não trata isso como permissão.
Respostas, recusas e mídia
O envelope. Toda ferramenta responde com um item de texto. Numa resposta, content[0].text é JSON (formatado). Numa recusa, é uma frase simples. Nos dois casos isError é false: leia a recusa e repasse. Não repita.
As recusas dizem o que ESTÁ permitido. "No chat named X is open to agents. What IS open: A, B." ou "X is open for reading only." Uma conversa oculta nunca é citada, então uma recusa não diz a um agente se uma conversa existe. "Nenhuma mensagem" e "você não pode ver essa conversa" nunca se confundem.
Cobertura. Quando um pedido vai mais para trás do que qualquer coisa guardada, a resposta traz coverage, dizendo onde começa o histórico guardado e por quê, terminando com "Nothing was hidden from you." Sem coverage, nada falta na janela pedida.
Horários são UTC: at em milissegundos desde 1970 e at_iso em ISO 8601 terminando em Z (last_at / last_at_iso também). O Circles não sabe onde a pessoa está e não converte nada.
Áudios. media.kind é voice para uma mensagem de voz do WhatsApp e audio para um arquivo de áudio. Os dois trazem transcript e transcript_state: pending (ainda sendo transcrito), done, empty (nada foi dito) ou failed; e duration_seconds quando o WhatsApp informa. A transcrição é automática. A transcrição automática de áudios está disponível em hebraico e inglês. A de áudios em português ainda não foi verificada. Um áudio com mais de cerca de 25 dias no momento da conexão é transcrito quando é buscado.
Estados dos anexos. Todo arquivo anunciado tem um state:
available:get_mediadevolve agora.downloading: chegando sozinho, geralmente em menos de um minuto. Peça de novo daqui a pouco.on_request: o WhatsApp não tem mais o arquivo;get_mediapede ao celular da pessoa que envie de novo (o celular precisa estar online) e espera cerca de 25 segundos.fetching: o celular ainda não respondeu. O arquivo NÃO sumiu: peça de novo com a mesma ref em cerca de um minuto; um pedido repetido se junta ao que já está em andamento.gone: o celular não conseguiu enviar de novo. Diga isso; não repita.too_large: acima de 50 MB, o limite por chamada.failed: ainda não foi possível baixar. A pessoa não precisa fazer nada.
Também nas mensagens: reactions (emoji, quem, quando) quando alguém reagiu, a partir de 2026-10-27. Edições feitas no WhatsApp atualizam o texto guardado; "apagar para todos" remove a mensagem. Localizações, cartões de contato e enquetes ficam como mensagens vazias, para a conversa não ter buracos. Prévias de links e o contexto de mensagens citadas não vêm incluídos.
Um exemplo resumido, com pessoas inventadas (em inglês, como as respostas da API):
// An answer: content[0].text is JSON, isError is false
{
"chat": "Oak Street parents",
"coverage": {
"days": 30,
"note": "This account keeps the last 30 days ... Nothing was hidden from you."
},
"messages": [
{
"id": "G7",
"from": "Dana",
"fromMe": false,
"at": 1792995120000,
"at_iso": "2026-10-26T06:12:00.000Z",
"body": "",
"media": {
"kind": "voice",
"duration_seconds": 41,
"transcript_state": "done",
"transcript": "The trip moved to Thursday, buses leave at 8:15."
}
},
{
"id": "G8",
"from": "Yossi",
"fromMe": false,
"at": 1792998180000,
"at_iso": "2026-10-26T07:03:00.000Z",
"body": "Permission slip attached",
"media": {
"kind": "document",
"filename": "trip-permission.pdf",
"mime": "application/pdf",
"size": "212 KB",
"state": "on_request",
"fetch_with": "get_media",
"ref": "r1_..."
}
}
]
}
// A refusal: content[0].text is the sentence itself, isError is still false
No chat named "Book club" is open to agents. What IS open: Oak Street parents, Building committee. Only the person can open another, in Circles.Acesso: OAuth 2.1 e tokens
| Valor | |
|---|---|
| Metadados do recurso protegido | https://app.usecircles.app/.well-known/oauth-protected-resource |
| Metadados do servidor de autorização | https://app.usecircles.app/.well-known/oauth-authorization-server (emissor https://app.usecircles.app) |
| Endpoints | /oauth/authorize, /oauth/token, /oauth/register (registro dinâmico de clientes), /oauth/revoke |
| Fluxo | Código de autorização com PKCE (só S256). Sem fluxo implícito, sem segredos de cliente (token_endpoint_auth_methods_supported: none). |
| 401 | WWW-Authenticate: Bearer resource_metadata=... apontando para os metadados do recurso protegido |
| URIs de redirecionamento | https em qualquer lugar, ou http em localhost, 127.0.0.1 ou [::1]. Esquemas personalizados são recusados. |
| Escopos | chats:read (ler as conversas abertas), media:read (abrir os arquivos delas), chats:send (enviar onde a pessoa permitiu) |
| Aprovação | Na própria página do Circles. O cliente recebe só o que a pessoa deixar marcado ali, peça o que pedir. Para um cliente que se registrou sozinho, leitura e arquivos vêm marcados e o envio vem desmarcado; a pessoa marca o envio se quiser permitir. |
| Validade | Token de acesso: 1 hora. Token de renovação: 30 dias, trocado a cada uso, com detecção de reuso. |
| Tokens criados | Feitos na lista de agentes (novo token). Prefixo circ_, mostrado uma vez, só o hash guardado. Validade: sem limite (padrão), 90 dias ou 1 ano. Sem renovação. |
| Código de conexão de uso único | circ_code_..., trocado em POST /api/v1/connect/exchange com {"code": "..."} e sem Authorization. Uso único, 1 hora, não abre nada sozinho, só o hash guardado, 10 tentativas por minuto por endereço. |
| Revogar | Desconectar na lista de agentes revoga acessos OAuth e tokens criados, na hora |
O escopo restringe; nunca amplia. Um token com todos os escopos ainda alcança só as conversas que a pessoa abriu, porque os níveis das conversas são lidos de novo a cada chamada.
API HTTP
As mesmas operações do MCP, em JSON por HTTP, para agentes e ferramentas que chamam uma API. OpenAPI 3.1 (versão 2.0.0) em https://app.usecircles.app/api/openapi.json; uma referência só de leitura em https://app.usecircles.app/api.
Todo pedido leva Authorization: Bearer <key>: uma chave circ_ criada no Circles ou o token OAuth de um cliente MCP. Nada mais é aceito, nem cookies.
- Leituras:
GET https://app.usecircles.app/api/v1/agent/allowed_chats,/activity,/people,/catch_up,/search,/documents,/group_members, com os mesmos parâmetros das ferramentas. - Detalhes:
GET /chats/<chat_ref>eGET /messages/<message_ref>devolvem o que é permitido (capabilities, com motivos e observações) eactionscompletas. - Enviar:
POST /chats/<chat_ref>/messages(texto, ou um arquivo de até cerca de 3 MB com legenda opcional). - Responder:
POST /messages/<message_ref>/replies, uma resposta com citação nativa do WhatsApp. Uma resposta que não pode ser citada é recusada. - Reagir:
POST /messages/<message_ref>/reactions, uma reação com emoji. - Conversa nova:
GET /recipients?to=com um número de telefone (com código do país, codificado para URL) ou o nome exato de um contato salvo; responde como os detalhes de uma conversa. - Recibo de escrita:
GET /writes/<submission_ref>. - Arquivos:
POST /get_media(pode pedir o arquivo ao celular),GET /media/<ref>/status,/contente/view(nunca pedem ao celular). - Código de conexão:
POST https://app.usecircles.app/api/v1/connect/exchange.
Agir. Para enviar, responder ou reagir, faça GET dos detalhes da conversa ou da mensagem e execute uma das actions como veio: um pedido completo (método, URL, cabeçalhos, corpo) ao qual o agente só acrescenta o cabeçalho Authorization e o texto.
Escritas idempotentes. Cada escrita leva uma referência de envio emitida pelo servidor e presa ao destino. Reusá-la não envia de novo nem ocupa outra vaga do limite diário, por 24 horas. Uma entrega incerta devolve delivery_unknown e nunca é repetida: leia o recibo e a conversa antes de fazer um novo envio, de propósito.
Paginação. Respostas em lista trazem pagination.next_url e has_more no nível de cima. Siga next_url até ser nulo; cada página confere a autorização de novo. As páginas de catch_up vão das mensagens mais novas para trás.
Erros. Um 401 significa que a chave não funciona mais. Um 403 scope_required significa que a pessoa não deu essa permissão. Um argumento inválido diz o campo e o intervalo permitido.
Sem suporte: votar em enquetes, remover uma reação, citar uma mensagem que não é texto.
# Read: which chats moved since 06:00 UTC
curl -H "Authorization: Bearer circ_..." \
"https://app.usecircles.app/api/v1/agent/activity?since=2026-10-27T06:00:00Z"
# Act: GET a chat's details, then perform one of its actions as given
curl -H "Authorization: Bearer circ_..." "https://app.usecircles.app/api/v1/agent/chats/<chat_ref>"
# -> "actions": [{ "method": "POST", "url": ".../chats/<chat_ref>/messages",
# "headers": {...}, "body": { ... "submission_ref": "..." } }]
# An agent handed a one-time code (Instinct) swaps it for its key, no Authorization
curl -X POST -H "Content-Type: application/json" \
-d '{"code":"circ_code_..."}' https://app.usecircles.app/api/v1/connect/exchangeLimites
| O quê | Limite |
|---|---|
| Texto por mensagem | 65.536 caracteres (o limite do próprio WhatsApp); legenda, 4.096 |
| Arquivo para enviar | Cerca de 3 MB |
| Arquivo para buscar | 50 MB por arquivo; maior que isso é too_large |
| Envios por dia | Padrão 5 por número, somando todos os agentes; 5, 10, 20 ou sem limite; contados por dia UTC |
catch_up, uma conversa | Padrão 50, máximo 200 mensagens |
catch_up, todas as conversas | Padrão 20, máximo 50 por conversa; 150 no total |
people | Padrão 60, máximo 150 pessoas; min_messages padrão 3 |
group_members | No máximo 300 nomes |
search | Até 36.500 dias para trás, ou a janela da conta |
get_media | Uma ref por chamada; espera cerca de 25 segundos pelo reenvio do celular |
| Download de arquivos em segundo plano | Até cerca de 25 dias depois da mensagem; arquivos mais antigos sob pedido |
| Histórico | Os agentes veem o último mês no Free e os últimos 3 meses no Starter; no Pro, todo o histórico, ou os últimos 90, 60 ou 30 dias |
| Conversas abertas aos agentes | 2 no Free; até 5 no Starter; todas as que a pessoa escolher no Pro |
| Envio | Só no Pro |
| Transcrição de áudios | Automática, em hebraico e inglês; a de áudios em português ainda não foi verificada |
| Tokens OAuth | Acesso 1 hora, renovação 30 dias |
| Código de conexão de uso único | Uso único, 1 hora, 10 tentativas por minuto por endereço |
| Idempotência de escrita | 24 horas por referência de envio |
| Link de acesso | Uso único, 10 minutos |
| Números de WhatsApp | Um por conta, em todos os planos |
Histórico de mudanças
Mudanças recentes que um agente ou integrador notaria.
- 2026-10-27: O Instinct se conecta com um código de uso único enviado pelo WhatsApp, sem nenhuma chave mostrada ou colada.
- 2026-10-27: Uma mensagem pode ser tão longa quanto o WhatsApp permite: 65.536 caracteres.
- 2026-10-27: As reações ficam na mensagem delas e aparecem em toda leitura.
- 2026-10-27: Conversas individuais ficam abertas para leitura por padrão num número novo.
- 2026-10-27: API HTTP 2.0.0: agentes de navegador removidos; a API de agentes aceita só uma chave Bearer.
- 2026-10-26: Uma assinatura cancelada continua funcionando até o fim do período pago, e
allowed_chatsinforma a data ao agente. - 2026-10-23: Os agentes podem mandar mensagem para alguém que ainda não tem conversa, por número de telefone ou nome de contato salvo.
- 2026-10-19: Os agentes podem enviar arquivos de qualquer tipo: PDF, documento, vídeo ou imagem.
- 2026-10-19: Gravações: filtros
kind=voice|audio|recordingeduration_seconds; todo horário é informado em UTC. - 2026-10-19: O Claude e o Codex se conectam por endereço, com aprovação na página do Circles.
- 2026-10-18: Os áudios são transcritos automaticamente, em hebraico e inglês, e os agentes leem a transcrição na mensagem.
- 2026-10-18: Todo o histórico passa a ser o padrão, para números novos e existentes.
- 2026-10-16: API HTTP com respostas e reações nativas; edições e exclusões feitas no WhatsApp são aplicadas.
Perguntas e respostas
Qual é o endereço do servidor MCP do Circles?
https://app.usecircles.app/api/mcp. É um servidor MCP remoto por HTTP que aceita OAuth 2.1 (com descoberta e registro dinâmico) ou um token bearer criado no Circles.
O Circles tem streaming ou SSE?
O Circles responde a cada pedido MCP com uma única resposta JSON por HTTP POST, sem estado. Não há fluxo de eventos para manter aberto, então qualquer cliente que fale MCP por HTTP pode usá-lo.
Por que o meu agente recebeu uma recusa em vez de um erro?
O Circles devolve recusas como respostas (isError: false) para que os agentes as leiam e não repitam o pedido. Cada uma diz o que ESTÁ aberto ou permitido.
Por que um arquivo está "fetching"?
O Circles pediu ao celular da pessoa que enviasse de novo um arquivo que o WhatsApp não tem mais. Ele não sumiu: peça de novo com a mesma ref em cerca de um minuto, com o celular online.
Posso responder ou reagir a uma mensagem?
Sim, pela API HTTP do Circles: respostas com citação nativa e reações com emoji. As ferramentas MCP enviam só mensagens simples e arquivos.