> ## Documentation Index
> Fetch the complete documentation index at: https://developer.wabox.me/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Wabox é uma API não-oficial de WhatsApp (aparelho vinculado). Tudo é snake_case; a base é https://api.wabox.me/instances/{instance_id}/token/{token}.
> Envios respondem { id, message_id, wabox_id, status: "queued" } na hora; o resultado real chega no webhook delivery. Envios não são idempotentes: confira GET /queue antes de repetir.
> Sempre verifique X-Wabox-Signature (HMAC-SHA256 de "<t>.<corpo cru>") nos webhooks e deduplique por event_id.
> Botões, listas, carrossel e catálogo são best effort e não renderizam no WhatsApp Web/Desktop. Não existem: chamadas, listas de transmissão, histórico de mensagens, instância mobile.
> Não invente endpoints ou campos: use o OpenAPI em https://api.wabox.me/openapi.json.

# Account API

> Crie, atualize e exclua instâncias da sua conta por API, até o número de slots do seu plano.

A **Account API** é para quem quer administrar instâncias **sem passar pelo painel**: um CRM, um omnichannel ou uma plataforma de atendimento que cria um número de WhatsApp para cada cliente, ou um time que provisiona canais por script.

Ela está disponível para **contas com plano**. Contas em trial criam a instância pelo painel; na Account API recebem `403 plan_required`.

## Slots: o que o plano compra

O plano do Wabox é cobrado por **slot** (canal), não por instância. Com um plano de 5 slots, a conta pode ter até 5 instâncias ao mesmo tempo e pode criar, atualizar e excluir à vontade dentro desse limite:

* Cada instância existente ocupa um slot, conectada ou não, criada pelo painel ou pela API.
* Com todos os slots em uso, `POST /account/instances` responde `409 instance_limit_reached`.
* Excluir uma instância **libera o slot na hora**; a próxima criação já passa.
* `GET /account/plan` mostra `instance_slots`, `instances_used` e `instances_available`.

```bash theme={"system"}
curl https://api.wabox.me/account/plan -H "Authorization: Bearer $WABOX_API_KEY"
```

```json theme={"system"}
{
  "subscription_status": "active",
  "due_at": "2026-10-15T12:00:00.000Z",
  "instance_slots": 5,
  "instances_used": 3,
  "instances_available": 2
}
```

<Note>
  Contas **Partner** (integradores com contrato próprio, como o Kinbox) usam a mesma API, sem limite de slots e sem cobrança no Wabox: `instance_slots` vem `null`. Fale com a gente em [wabox.me/partners](https://wabox.me/partners).
</Note>

## Autenticação

Todas as rotas ficam sob `https://api.wabox.me/account` e autenticam por uma [API key](/security/api-keys) do workspace em `Authorization: Bearer`. As keys são criadas em **Segurança › API keys** no painel (owner ou admin), cada uma com um nome e as permissões que você marcar:

```bash theme={"system"}
curl https://api.wabox.me/account/instances \
  -H "Authorization: Bearer wbx_key_3f9a1c7e5b2d4f6a8c0e1b3d5f7a9c2e4b6d8f0a1c3ec2e1"
```

* A key é mostrada **uma única vez** ao ser criada (só o hash fica guardado). Perdeu? Crie outra e revogue a antiga; revogar uma key não afeta as demais.
* Só `Authorization: Bearer` é aceito aqui. O alias `Client-Token` vale apenas nas rotas de instância.
* A [allowlist de IPs](/security/ip-allowlist) do workspace vale também aqui.
* Rate limit por conta, com os mesmos headers e `429` da [API pública](/guides/rate-limits-and-errors).
* Erros no mesmo formato: `{ "error": { "code": "api_key_required" | "insufficient_scope" | "plan_required" | "subscription_required" | "instance_limit_reached" | "ip_not_allowed" | "instance_not_found" | ... } }`.

### Permissões por rota

| Scope             | Rotas                                                                                                                                   |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `instances:read`  | `GET /account/instances`, `GET /account/instances/{id}`, `GET /account/plan` (as respostas incluem o `token` das instâncias)            |
| `instances:write` | `POST /account/instances`, `PUT /account/instances/{id}`, `POST /account/instances/{id}/rotate-token`, `DELETE /account/instances/{id}` |
| `webhooks:read`   | `GET /account/webhooks` (inclui o `secret`)                                                                                             |
| `webhooks:write`  | `PUT /account/webhooks`, `POST /account/webhooks/secret`                                                                                |

Um provisionador típico usa uma key com `instances:read` + `instances:write`. A permissão `instances:operate` não abre nenhuma rota `/account/*`: ela só serve para as rotas de instância quando o workspace [exige API key](/security/api-keys) nelas — nesse caso, inclua-a na mesma key se o seu backend também opera os números.

### Erros

| Status | `code`                   | Quando                                                                     |
| ------ | ------------------------ | -------------------------------------------------------------------------- |
| `401`  | `api_key_required`       | Header `Authorization` ausente ou key inválida (revogada, inexistente)     |
| `403`  | `insufficient_scope`     | A key não tem a permissão da rota; `details.required_scope` diz qual falta |
| `403`  | `plan_required`          | Conta em trial                                                             |
| `402`  | `subscription_required`  | Plano vencido ou cancelado                                                 |
| `409`  | `instance_limit_reached` | Todos os slots em uso (`details.instance_slots`, `details.instances_used`) |

```json theme={"system"}
{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key lacks the \"instances:write\" permission",
    "details": { "required_scope": "instances:write" }
  }
}
```

<Note>
  O header `Account-Token` (`act_…`) foi substituído pelas API keys e não é mais aceito. Crie uma key com as permissões necessárias e troque o header por `Authorization: Bearer`.
</Note>

## Fluxo típico: um canal por cliente

<Steps>
  <Step title="Crie a instância quando o cliente pedir um número">
    ```bash theme={"system"}
    curl -X POST https://api.wabox.me/account/instances \
      -H "Authorization: Bearer $WABOX_API_KEY" -H "Content-Type: application/json" \
      -d '{
        "name": "Loja Centro (cliente 4821)",
        "webhooks": {
          "received_url": "https://seu-app.com/wabox/received",
          "delivery_url": "https://seu-app.com/wabox/delivery",
          "message_status_url": "https://seu-app.com/wabox/status",
          "instance_status_url": "https://seu-app.com/wabox/instance-status",
          "notify_sent_by_me": true
        },
        "settings": { "call_reject_auto": true }
      }'
    ```

    A resposta é a instância completa, com `id`, `token`, `api_url` e `webhooks` (inclusive o `secret` para verificar a [assinatura](/security/webhook-signature)). **Guarde `id`, `token` e `secret`** junto do cliente no seu banco. Se vier `409 instance_limit_reached`, aumente o plano ou exclua uma instância que não é mais usada.
  </Step>

  <Step title="Mostre o QR code ao cliente">
    Use a API pública normal com as credenciais devolvidas: `GET {api_url}/qr-code` (data URL) ou `/qr-code/image` (PNG), ou `GET {api_url}/phone-code/{phone}` para pareamento por código. O webhook [`instance_status`](/webhooks/instance-status) acompanha o ciclo inteiro (`qr` → `connecting` → `connected`): avisa quando o número entrou e quando voltar a mostrar o QR.
  </Step>

  <Step title="Opere o número como qualquer instância">
    `POST {api_url}/send-text`, webhooks `received`/`delivery`/`message_status`, grupos, contatos… tudo igual à [documentação da API](/quickstart). Recomendação: `notify_sent_by_me: true` para espelhar no seu produto o que o cliente digitou no celular.
  </Step>

  <Step title="Quando o cliente cancelar, exclua a instância">
    `DELETE /account/instances/{id}` desconecta o aparelho no celular do cliente, para a sessão, remove a instância (a fila é descartada) e devolve o slot.
  </Step>
</Steps>

## Rotas

| Método e rota                                     | Scope                              | O que faz                                                                                                                                            |
| ------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /account/plan`                               | `instances:read`                   | Status do plano e slots: `instance_slots`, `instances_used`, `instances_available`                                                                   |
| `POST /account/instances`                         | `instances:write`                  | Cria (ocupa um slot) e já inicia a sessão. Body: `name` (obrigatório), `webhooks?`, `settings?` (mesmos campos de `PUT /webhooks` e `PUT /settings`) |
| `GET /account/instances?status&q&page&page_size`  | `instances:read`                   | Lista com `token` e webhooks; `status` = `connected` \| `disconnected`, `q` busca por nome, id ou número                                             |
| `GET /account/instances/{id}`                     | `instances:read`                   | Detalhes                                                                                                                                             |
| `PUT /account/instances/{id}`                     | `instances:write`                  | Atualização parcial de `name`, `webhooks`, `settings`                                                                                                |
| `POST /account/instances/{id}/rotate-token`       | `instances:write`                  | Novo `token` da instância (o antigo para de valer)                                                                                                   |
| `DELETE /account/instances/{id}`                  | `instances:write`                  | Desconecta, para e remove (apaga também o histórico recente e a mídia guardados da instância) e libera o slot                                        |
| `GET /account/webhooks` · `PUT /account/webhooks` | `webhooks:read` · `webhooks:write` | Webhooks do workspace: URLs, filtros e `secret` herdados por toda instância criada sem `webhooks` próprios (`use_workspace_webhooks: true`)          |
| `POST /account/webhooks/secret`                   | `webhooks:write`                   | Novo `secret` do workspace                                                                                                                           |

### Webhooks do workspace

Se todas as instâncias apontam para o mesmo backend, configure uma vez em `PUT /account/webhooks` (mesmos campos de `PUT /webhooks`; `single_url_enabled` + `single_url` mandam todos os eventos para uma URL só — é o modo padrão de um workspace novo, então basta enviar `single_url`) e crie as instâncias sem `webhooks`. Elas herdam URLs, filtros **e o `secret` do workspace** — um só para verificar `X-Wabox-Signature`, em vez de um por instância. O `secret` nasce no primeiro `PUT`. Uma instância que precise de outro destino recebe `webhooks` próprios no `POST`/`PUT /account/instances` (isso desliga a herança só nela e ela volta a usar o próprio `secret`).

A referência completa, com exemplos de request e response, está em **API Reference › Conta**.

## Boas práticas para integradores

* **Um webhook por evento, com a assinatura verificada.** O `secret` é por instância; guarde-o ao criar e leia `X-Wabox-Instance-Id` para saber de qual cliente veio a entrega antes de escolher o segredo.
* **Idempotência do seu lado.** Se a criação falhar por rede sem resposta, liste com `q=<seu nome único>` antes de criar de novo, para não gastar um slot com uma instância órfã.
* **Exclua o que não usa.** Instância parada também ocupa slot; ao encerrar um cliente, faça o `DELETE`.
* **Não exponha a API key no front-end** nem em ferramentas no-code. Com `instances:write` ela cria e apaga instâncias no seu nome; com `instances:read` ela lê o `token` de todas.
* **Uma key por sistema, com o mínimo de permissões.** Para trocar sem downtime, crie a nova, publique e só então revogue a antiga ([Rotação](/security/credential-rotation)).
* **Trate `instance_status` com `status: logged_out`** (ou `qr`) mostrando o QR de novo ao cliente; `banned` não volta e precisa de um número novo.
* **Limites** por instância continuam valendo: fila de 1.000 mensagens, intervalo anti-ban, 60 req/s. Com muitos clientes, o gargalo é sempre o número, nunca a Account API.
