npm package: @pilot-status/sdk
Description: Official TypeScript SDK for the Pilot Status public API.
Latest version: 0.1.3

# @pilot-status/sdk

Official TypeScript SDK for the Pilot Status public API.

## Installation

```bash
npm i @pilot-status/sdk
```

## Quickstart (Node.js / TypeScript)

Create an API key in the dashboard and use it only on the backend.

```ts
import { PilotStatusClient } from "@pilot-status/sdk";

const client = new PilotStatusClient({
  apiKey: process.env.PILOT_STATUS_API_KEY!,
});

const accepted = await client.messages.send({
  templateId: "onboarding-test",
  destinationNumber: "+5511999999999",
  variables: { name: "John" },
});

const message = await client.messages.get(accepted.id);
console.log(message.status);
```

## Management (projects, API keys, numbers)

These endpoints create resources within the scope (project + environment) of the current `apiKey`.

### Projects

```ts
const project = await client.projects.create({
  name: "My Project",
  description: "Optional description",
});

const projects = await client.projects.list();
```

### API keys

```ts
const key = await client.apiKeys.create({
  name: "Backend Key",
  retentionDays: 30,
});

const keys = await client.apiKeys.list();
```

### Numbers (WhatsApp)

```ts
const created = await client.numbers.create({
  name: "My WhatsApp",
  number: "+5511999999999",
});

const status = await client.numbers.getStatus(created.instance.id);
```

## Opt-in check (destination authorization)

In LIVE, sending may require opt-in when using the Pilot Status WhatsApp number. You can check whether a destination is already authorized for your project:

```ts
const optIn = await client.messages.checkOptIn("+5511999999");

if (!optIn.authorized) {
  throw new Error(`Missing opt-in: ${optIn.reason}`);
}
```

## Analytics

```ts
const stats = await client.analytics.getDashboardStats({ tz: "America/Sao_Paulo" });
console.log(stats.totalSent, stats.failureRate);
```

## Webhooks (parse / validation)

```ts
import { parseCustomerWebhook } from "@pilot-status/sdk";

export async function handler(req: Request) {
  const payload = await req.json();
  const event = parseCustomerWebhook(payload);

  if (event.event === "message.failed") {
    console.log(event.data.errorMessage);
  }

  return new Response("ok");
}
```

Notes:
- Customer webhook payloads do not include: `projectSlug`, `lastMessageId`, `correlationId`.
- For outbound status events (`message.sent`, `message.delivered`, `message.read`, `message.failed`), `messageId` is the WhatsApp provider message id (key.id) and `internalMessageId` is the Pilot Status message id.
- `message.received` includes `fromMe` (boolean).
- `message.group` is delivered for inbound group messages (includes `groupName`).
- Supported events in the parser: `message.sent`, `message.delivered`, `message.read`, `message.failed`, `message.reply`, `message.received`, `message.group`, `optin.created`.

## Errors

For non-2xx responses, the SDK throws an HTTP error with `status` and, when available, `body`.

```ts
import { PilotStatusHttpError } from "@pilot-status/sdk";

try {
  await client.messages.send({
    templateId: "x",
    destinationNumber: "+5511999999999",
    variables: {},
  });
} catch (err) {
  if (err instanceof PilotStatusHttpError) {
    console.log(err.status, err.body);
  }
}
```