# 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](https://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.

Fonte: https://usecircles.app/pt-br/api-mcp-docs · Atualizado em 2026-10-31

## 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](https://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_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 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 `: 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/` e `GET /messages/` devolvem o que é permitido (`capabilities`, com motivos e observações) e `actions` completas.
- **Enviar:** `POST /chats//messages` (texto, ou um arquivo de até cerca de 3 MB com legenda opcional).
- **Responder:** `POST /messages//replies`, uma resposta com citação nativa do WhatsApp. Uma resposta que não pode ser citada é recusada.
- **Reagir:** `POST /messages//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/`.
- **Arquivos:** `POST /get_media` (pode pedir o arquivo ao celular), `GET /media//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 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_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.

## Continue lendo

- [Os guias, para pessoas](https://usecircles.app/pt-br/docs): Conectar o WhatsApp, escolher conversas, conectar um agente.
- [WhatsApp MCP, em resumo](https://usecircles.app/pt-br/whatsapp-mcp): O que é o Circles e a diferença para instalar por conta própria.
- [Segurança e controle](https://usecircles.app/pt-br/security): Níveis por conversa, aprovação, registro de atividade e os riscos reais.

---

14 dias de Pro grátis, sem cartão. Vincule seu número, escolha as conversas e conecte a IA que você já usa: Instinct com um toque, Claude, ChatGPT e Codex com um endereço. Comece aqui: https://usecircles.app/start?lang=pt-BR
