> ## 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.

# SDK TypeScript

> Cliente tipado gerado do OpenAPI, verificação de webhooks e tipos de todos os payloads: @wabox/sdk para Node, Bun, Deno e edge.

`@wabox/sdk` é o pacote oficial para TypeScript e JavaScript. Ele é **gerado a partir do OpenAPI** da API, então cada rota, body, parâmetro e resposta desta referência tem o tipo correspondente no editor. Toda página de endpoint mostra o equivalente em SDK na aba **TypeScript**.

```bash theme={"system"}
npm install @wabox/sdk
```

Requer Node ≥ 20 (ou Bun, Deno, Cloudflare Workers, Vercel Edge). Sem dependências além do [openapi-fetch](https://openapi-ts.dev/openapi-fetch/), \~6 kB.

## Enviar e consultar

```ts theme={"system"}
import { createWabox } from "@wabox/sdk";

const wabox = createWabox({
  instanceId: process.env.WABOX_INSTANCE_ID!,
  token: process.env.WABOX_TOKEN!,
  // clientToken: process.env.WABOX_CLIENT_TOKEN, // se o workspace exigir Client-Token
});

const { data, error } = await wabox.POST("/send-text", {
  body: { phone: "5511988887777", message: "Olá! Seu pedido *#1234* foi confirmado." },
});
if (error) throw new Error(`${error.error.code}: ${error.error.message}`);
console.log(data.message_id); // id definitivo no WhatsApp; o resultado chega no webhook delivery
```

O caminho é relativo à instância (`/send-text`, `/chats/{phone}`, `/groups`): o SDK monta `https://api.wabox.me/instances/{instance_id}/token/{token}` por você. Parâmetros de rota e query vão em `params`:

```ts theme={"system"}
const { data } = await wabox.GET("/contacts/{phone}", {
  params: { path: { phone: "5511988887777" } },
});

const { data: page } = await wabox.GET("/chats", {
  params: { query: { page: 1, page_size: 50, archived: false } },
});
```

Cada chamada resolve com `{ data, error, response }`: `data` tipado quando a resposta é 2xx, `error` tipado como `{ error: { code, message } }` nos demais casos, e `response` é o `Response` cru (status, headers como `Retry-After`).

### Preferir exceções

`unwrap()` devolve só o `data` e lança `WaboxError` (`code`, `status`, `details`) quando a API responde erro:

```ts theme={"system"}
import { createWabox, unwrap, WaboxError } from "@wabox/sdk";

try {
  const status = await unwrap(wabox.GET("/status"));
  if (!status.connected) console.log("instância desconectada:", status.status);
} catch (e) {
  if (e instanceof WaboxError && e.code === "rate_limited") {
    // respeite e.response.headers.get("Retry-After")
  }
  throw e;
}
```

## Receber webhooks

`constructWebhookEvent` verifica o [`X-Wabox-Signature`](/security/webhook-signature) (HMAC-SHA256 sobre o corpo cru, com janela de 5 minutos contra replay) e devolve o evento **tipado**, discriminado por `type`:

<CodeGroup>
  ```ts Express theme={"system"}
  import express from "express";
  import { constructWebhookEvent, WaboxWebhookError } from "@wabox/sdk/webhooks";

  const app = express();

  // express.raw: a assinatura é calculada sobre os bytes originais, antes do parser JSON.
  app.post("/wabox", express.raw({ type: "application/json" }), async (req, res) => {
    let event;
    try {
      event = await constructWebhookEvent({
        body: req.body, // Buffer
        headers: req.headers,
        secret: process.env.WABOX_WEBHOOK_SECRET!,
      });
    } catch (e) {
      if (e instanceof WaboxWebhookError) return res.status(401).end();
      throw e;
    }
    res.status(200).end(); // responda antes de processar

    switch (event.type) {
      case "received":
        if (event.text) console.log(`${event.phone}: ${event.text.message}`);
        break;
      case "delivery":
        console.log(event.wabox_id, event.status, event.error_code);
        break;
    }
  });
  ```

  ```ts Hono / Workers / Next.js theme={"system"}
  import { constructWebhookEvent, WaboxWebhookError } from "@wabox/sdk/webhooks";

  export async function POST(request: Request) {
    try {
      const event = await constructWebhookEvent({
        body: await request.text(),
        headers: request.headers,
        secret: process.env.WABOX_WEBHOOK_SECRET!,
      });
      queueMicrotask(() => handle(event));
      return new Response(null, { status: 200 });
    } catch (e) {
      if (e instanceof WaboxWebhookError) return new Response(null, { status: 401 });
      throw e;
    }
  }
  ```
</CodeGroup>

`WaboxWebhookError.reason` diz o motivo: `invalid_signature` (assinatura errada, ausente ou `t` fora da janela), `invalid_json` ou `unknown_event`. Se você só quer a verificação, use `verifyWebhookSignature(secret, header, rawBody)`; para processar sem verificar (não recomendado), `parseWebhookEvent(rawBody)`.

O `secret` (`whsec_…`) é por instância: `GET /webhooks` ou o painel em **Webhooks e configurações gerais**.

## Partner API

Integradores criam e administram instâncias com o header `Partner-Token` (veja [Partner API](/partner/api)):

```ts theme={"system"}
import { createWabox, createWaboxPartner, unwrap } from "@wabox/sdk";

const partner = createWaboxPartner({ partnerToken: process.env.WABOX_PARTNER_TOKEN! });

const inst = await unwrap(partner.POST("/partner/instances", { body: { name: "Loja Centro" } }));
// guarde inst.id, inst.token e inst.webhooks.secret por cliente

const wabox = createWabox({ instanceId: inst.id, token: inst.token });
const { data: qr } = await wabox.GET("/qr-code");
```

## Tipos

Todos os schemas nomeados da referência são exportados como tipos: `Instance`, `Chat`, `Contact`, `Group`, `SendResponse`, `QueueItem`, `WebhookReceived`, `WebhookDelivery`… e `WebhookEvent` (a união de todos os eventos). Para tipar o resto, use `InstancePaths`/`PartnerPaths` (todas as rotas) e `Schemas`:

```ts theme={"system"}
import type { Chat, Schemas, WebhookEvent, InstancePaths } from "@wabox/sdk";

type SendTextBody =
  InstancePaths["/send-text"]["post"]["requestBody"]["content"]["application/json"];

function onEvent(event: WebhookEvent) {
  if (event.type === "message_status") console.log(event.status, event.ids);
}
```

## Opções

| Opção          | Onde                                              | Para quê                                                 |
| -------------- | ------------------------------------------------- | -------------------------------------------------------- |
| `baseUrl`      | `createWabox`, `createWaboxPartner`               | Outro host (padrão `https://api.wabox.me`)               |
| `clientToken`  | `createWabox`                                     | Header `Client-Token` do workspace                       |
| `headers`      | ambos                                             | Headers extras em toda chamada                           |
| `fetch`        | ambos                                             | `fetch` customizado (proxy, retry, testes)               |
| `toleranceSec` | `verifyWebhookSignature`, `constructWebhookEvent` | Janela anti-replay em segundos (padrão 300; `0` desliga) |

<Note>
  O SDK não faz retry nem fila: trate `429` (`Retry-After`), `409 instance_not_connected` e `402` como descrito em [Rate limits e erros](/guides/rate-limits-and-errors). Envios não são idempotentes — confira `GET /queue` antes de repetir uma chamada que falhou por rede.
</Note>
