> ## Documentation Index
> Fetch the complete documentation index at: https://developers.perkstar.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> Use the official typed Perkstar client with automatic retries, pagination, and webhook verification.

The official SDK supports Node.js 18+ and ships ESM and CommonJS builds with no
runtime dependencies.

```bash theme={null}
npm install @perkstar/api-client
```

## Create a client

```ts theme={null}
import { PerkstarClient } from "@perkstar/api-client";

const perkstar = new PerkstarClient({
  apiKey: process.env.PERKSTAR_API_KEY!,
  userAgent: "MyOdooConnector/1.0",
});

const context = await perkstar.marketplace.ping();
console.log(context.data.organization.name);
```

You can pass an OAuth access token instead of an API key:

```ts theme={null}
const perkstar = new PerkstarClient({
  oauthAccessToken: accessToken,
});
```

Pass exactly one credential type.

## Post a POS transaction

```ts theme={null}
const result = await perkstar.marketplace.accrue(
  {
    identifier: { external_ref: "odoo:4:partner:981" },
    card_id: "card_123",
    transaction: {
      type: "STAMP",
      delta: 1,
      external_transaction_id: "odoo:4:pos_order:94721",
    },
  },
  {
    idempotencyKey: "odoo:4:pos_order:94721:loyalty",
  },
);

console.log(result.enrollment.balance);
```

The SDK generates an idempotency key for each new POST call and keeps it across
its automatic retries. Pass your own stable key when a job may restart in a new
process.

## Pagination

```ts theme={null}
for await (const customer of perkstar.customers.list({ limit: 100 })) {
  await syncCustomer(customer);
}
```

## Typed errors

```ts theme={null}
import {
  PerkstarRateLimitError,
  PerkstarValidationError,
} from "@perkstar/api-client";

try {
  await postLoyalty();
} catch (error) {
  if (error instanceof PerkstarValidationError) {
    console.error(error.code, error.requestId);
    return;
  }
  if (error instanceof PerkstarRateLimitError) {
    throw error; // let the durable job retry later
  }
  throw error;
}
```

By default the client retries network errors, `429`, and retryable `5xx`
responses up to three times, honours `Retry-After`, and times out each request
after 30 seconds.

## Verify webhooks

```ts theme={null}
import { verifyWebhookSignature } from "@perkstar/api-client/webhooks";

const event = verifyWebhookSignature({
  payload: rawBody,
  signature: signatureHeader,
  secret: process.env.PERKSTAR_WEBHOOK_SECRET!,
});
```

The helper uses constant-time HMAC comparison and rejects timestamps outside a
five-minute tolerance by default.

<Note>
  The REST API currently contains a few endpoints that are not yet wrapped by
  the SDK, including locations and direct wallet pushes. Use the generated API
  reference for those calls while keeping the same bearer and retry rules.
</Note>


## Related topics

- [Pagination](/fundamentals/pagination.md)
- [Perkstar developer platform](/index.md)
- [Quickstart](/quickstart.md)
- [Changelog](/changelog.md)
- [Python SDK](/sdks/python.md)
