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

# Node.js SDK

> The official @kua/node client for TypeScript and JavaScript.

<Card title="View on GitHub" icon="github" href="https://github.com/TRSNg/kua-developer/tree/main/node" horizontal>
  Source, releases, and issues.
</Card>

## Install

```bash theme={null}
npm install @kua/node
```

Requires Node.js 18+ (uses the built-in `fetch`). Fully typed — no `@types`
package needed.

## Initialize

```ts theme={null}
import { Kua } from "@kua/node";

const kua = new Kua({ apiKey: process.env.KUA_API_KEY! });
```

Get your key from **Settings → API keys** in the
[dashboard](https://dashboard.kuahr.com/settings/api-keys). Use a `kua_test_…`
key to work against [sandbox data](/concepts/data-model#test-mode).

## Examples

```ts theme={null}
// List payroll runs
const runs = await kua.payrollRuns.list();

// Add an employee (retry-safe with an idempotency key)
const employee = await kua.employees.create(
  {
    firstName: "Jane",
    lastName: "Doe",
    email: "jane@acme.com",
    employmentTypeId: "3f9a0b1c-…",
    employedAt: "2026-07-01",
  },
  { idempotencyKey: "employee-jane-2026-07" },
);

// Create a draft payroll run
const run = await kua.payrollRuns.create({ year: 2026, month: 7 });

// Poll events incrementally
const events = await kua.events.list({ since: "2026-07-25T10:30:00Z", limit: 100 });
```

## Errors

Non-2xx responses throw a `KuaError` with a stable `code` and the HTTP `status`:

```ts theme={null}
import { KuaError } from "@kua/node";

try {
  await kua.payrollRuns.create({ year: 2026, month: 7 });
} catch (err) {
  if (err instanceof KuaError && err.code === "INSUFFICIENT_SCOPE") {
    // the key is missing the payroll:write scope
  }
}
```

## Webhooks

Register endpoints and verify deliveries against the **raw** request body:

```ts theme={null}
import express from "express";
import { Kua, verifySignature } from "@kua/node";

const kua = new Kua({ apiKey: process.env.KUA_API_KEY! });
const app = express();

app.post("/kua/webhooks", express.raw({ type: "application/json" }), (req, res) => {
  const ok = verifySignature(req.body, req.header("X-Kua-Signature"), process.env.KUA_WEBHOOK_SECRET!);
  if (!ok) return res.status(400).end();

  const event = JSON.parse(req.body.toString());
  // …handle event (dedupe on event.id)…
  res.status(200).end();
});
```

`verifySignature` rejects deliveries older than 5 minutes by default (replay
protection); tune with `{ toleranceSeconds }`. See
[verifying signatures](/webhooks/verifying-signatures).
