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_chats lista 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, send pode 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 activity com um horário since (só contagens, barato), depois catch_up nas conversas que tiveram movimento. Os áudios transcritos chegam como texto em media.transcript.
  • Uma recusa é uma resposta. Ela vem com isError: false e 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 send com confirmed: true só 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 HTTPhttps://app.usecircles.app/api/v1/agent
OpenAPI 3.1https://app.usecircles.app/api/openapi.json; uma referência legível em https://app.usecircles.app/api
Metadados OAuthhttps://app.usecircles.app/.well-known/oauth-protected-resource, https://app.usecircles.app/.well-known/oauth-authorization-server
Cartão do servidor MCPhttps://usecircles.app/.well-known/mcp/server-card.json
Esta página em Markdownhttps://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_media devolve 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_media pede 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 protegidohttps://app.usecircles.app/.well-known/oauth-protected-resource
Metadados do servidor de autorizaçãohttps://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
FluxoCódigo de autorização com PKCE (só S256). Sem fluxo implícito, sem segredos de cliente (token_endpoint_auth_methods_supported: none).
401WWW-Authenticate: Bearer resource_metadata=... apontando para os metadados do recurso protegido
URIs de redirecionamentohttps em qualquer lugar, ou http em localhost, 127.0.0.1 ou [::1]. Esquemas personalizados são recusados.
Escoposchats:read (ler as conversas abertas), media:read (abrir os arquivos delas), chats:send (enviar onde a pessoa permitiu)
AprovaçãoNa 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.
ValidadeToken de acesso: 1 hora. Token de renovação: 30 dias, trocado a cada uso, com detecção de reuso.
Tokens criadosFeitos 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 únicocirc_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.
RevogarDesconectar 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> e GET /messages/<message_ref> devolvem o que é permitido (capabilities, com motivos e observações) e actions completas.
  • 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, /content e /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/exchange

Limites

O quêLimite
Texto por mensagem65.536 caracteres (o limite do próprio WhatsApp); legenda, 4.096
Arquivo para enviarCerca de 3 MB
Arquivo para buscar50 MB por arquivo; maior que isso é too_large
Envios por diaPadrão 5 por número, somando todos os agentes; 5, 10, 20 ou sem limite; contados por dia UTC
catch_up, uma conversaPadrão 50, máximo 200 mensagens
catch_up, todas as conversasPadrão 20, máximo 50 por conversa; 150 no total
peoplePadrão 60, máximo 150 pessoas; min_messages padrão 3
group_membersNo máximo 300 nomes
searchAté 36.500 dias para trás, ou a janela da conta
get_mediaUma ref por chamada; espera cerca de 25 segundos pelo reenvio do celular
Download de arquivos em segundo planoAté cerca de 25 dias depois da mensagem; arquivos mais antigos sob pedido
HistóricoOs 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 agentes2 no Free; até 5 no Starter; todas as que a pessoa escolher no Pro
EnvioSó no Pro
Transcrição de áudiosAutomática, em hebraico e inglês; a de áudios em português ainda não foi verificada
Tokens OAuthAcesso 1 hora, renovação 30 dias
Código de conexão de uso únicoUso único, 1 hora, 10 tentativas por minuto por endereço
Idempotência de escrita24 horas por referência de envio
Link de acessoUso único, 10 minutos
Números de WhatsAppUm 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_chats informa 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|recording e duration_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.