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

# JavaScript SDK

> Manage your entire woku account from your backend with @wokuapp/sdk: trackers, VoC tools (NPS, CSAT, CES), wokus, tickets, action plans and sends over the v1 API

<Info>
  **Available on every plan, including the free one.** The v1 API and the official SDKs are enabled for every woku account. [See the plans](https://woku.app/pricing).
</Info>

The **`@wokuapp/sdk`** SDK is the official **server-side** client for the woku
management API. With a single typed client you manage external trackers, VoC
tools (**NPS**, **CSAT**, **CES**), wokus, forms, flows, action plans, support
tickets, survey sends and delivery tracking, all over the public **v1** API.

<Warning>
  This is a **server-side** SDK. The company secret key grants full management
  access, so it must live only on your backend. Never ship it in a browser
  bundle, a mobile app or any client you do not control. To capture feedback from
  a mobile app use the [React Native SDK](/docs/en/development/sdk-react-native), which
  uses a public capture key.
</Warning>

## Installation

```bash theme={null}
npm install @wokuapp/sdk
```

Requires Node.js 18 or later (uses the global `fetch`). It has zero runtime
dependencies.

## Initialization

Create a `Woku` instance once and reuse it.

```ts theme={null}
import { Woku } from '@wokuapp/sdk';

const woku = new Woku({ apiKey: process.env.WOKU_API_KEY });
```

If you omit `apiKey`, the SDK reads the `WOKU_API_KEY` environment variable. You
can also pass the key directly: `new Woku('sk_...')`.

| Option       | Required | Description                                                 |
| ------------ | -------- | ----------------------------------------------------------- |
| `apiKey`     | yes      | Company secret key. Defaults to `process.env.WOKU_API_KEY`. |
| `baseURL`    | no       | API base URL. Defaults to `https://clientapi.woku.app`.     |
| `timeout`    | no       | Per-request timeout in ms. Defaults to `60000`.             |
| `maxRetries` | no       | Automatic retries for transient failures. Defaults to `2`.  |

## Authentication

The SDK authenticates with the **Company Key**, the same secret key the
[API](/docs/en/development/api) uses. The company owner gets it from the company
**Information** section in the admin app:
[admin.woku.app](https://admin.woku.app).

```
Authorization: Bearer <Company-Key>
```

The SDK adds that header for you on every call.

### Rotate or revoke the key

Since the secret key grants full access, you can rotate or revoke it from the
SDK itself. Rotating generates a new key and **immediately invalidates the
previous one**; store the returned key before continuing.

```ts theme={null}
const { secretKey } = await woku.company.rotateKey();
// store secretKey securely; the previous key stops working

await woku.company.revokeKey(); // leaves the account without an active key
```

## Quickstart

An end-to-end flow: create a tracker, create an NPS tool, tag it with the
tracker, send it and read the response rate.

```ts theme={null}
import { Woku } from '@wokuapp/sdk';

const woku = new Woku({ apiKey: process.env.WOKU_API_KEY });

// 1. Create a tracker definition (idempotent).
const tracker = await woku.trackers.create({
  name: 'Store #1',
  system: 'retail',
});

// 2. Create an NPS tool.
const tool = await woku.npsTools.create({
  name: 'Post-purchase',
  npsMessage: 'How likely are you to recommend us?',
});

// 3. Assign a tracker value to the NPS tool, so every response is tagged with
//    the store and reporting groups by it.
await woku.trackers.assignToEntity('nps', tool._id, {
  name: tracker.name,
  value: 'TX-42',
});

// 4. Send it by email or WhatsApp.
await woku.nps.sendInvitations({
  channel: 'email',
  npsToolId: tool._id,
  recipients: ['ana@example.com'],
});

// 5. Read delivery and response rate.
const stats = await woku.dispatches.stats({ channel: 'email' });
console.log(stats.responseRate);
```

## Main flows

### VoC tools

Create and manage NPS, CSAT and CES tools, and capture their responses.

```ts theme={null}
const csat = await woku.csatTools.create({
  name: 'Support',
  question: 'How satisfied were you with the support?',
});

// Send, then read responses.
await woku.csat.sendInvitations({
  channel: 'email',
  csatToolId: csat._id,
  recipients: ['ana@example.com'],
});
for await (const response of await woku.csat.listResponses()) {
  console.log(response);
}
```

### Support tickets

Tickets are generated by woku's AI. You can list, filter and curate them.

```ts theme={null}
for await (const ticket of await woku.tickets.list({ severity: 'high' })) {
  console.log(ticket.title);
}

const stats = await woku.tickets.stats();
```

### Action plans

Approve and manage action plans inside woku: change their status and manage
their tasks.

```ts theme={null}
await woku.actionPlans.approve('plan_123');

// Read the plan detail and its timeline.
const plan = await woku.actionPlans.get('plan_123');
const events = await woku.actionPlans.events('plan_123');

// Complete or reopen the plan.
await woku.actionPlans.complete('plan_123');
```

## Pagination

List methods return a `Page`. Iterate every item across pages, or walk page by
page:

```ts theme={null}
for await (const ticket of await woku.tickets.list({ severity: 'high' })) {
  console.log(ticket.title);
}

const first = await woku.dispatches.list({ channel: 'whatsapp' });
if (first.hasNextPage()) {
  const second = await first.getNextPage();
}
```

## Idempotency

Creates carry an automatic `Idempotency-Key`, so a retry after a transient
failure never creates twice. Actions (send, test, reply) are **not** retried on
their own so an effect is never repeated. You can pass your own key per call:

```ts theme={null}
await woku.npsTools.create(body, { idempotencyKey: 'my-key' });
```

## Error handling

Every failure is a `WokuError`. HTTP errors are typed subclasses carrying the
server `status`, body and `requestId`:

```ts theme={null}
import { NotFoundError, RateLimitError } from '@wokuapp/sdk';

try {
  await woku.tickets.get('nonexistent');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.error(err.status, err.requestId); // 404, "req_..."
  } else if (err instanceof RateLimitError) {
    console.error('retry after', err.retryAfterSeconds);
  }
}
```

Transport failures (DNS, TLS, timeout) are `WokuConnectionError` and
`WokuTimeoutError`. The SDK retries GETs and idempotent writes automatically
with backoff, honoring the `Retry-After` header.

## Per-call configuration

Every method accepts overrides in its last argument:

```ts theme={null}
await woku.tickets.list(
  { severity: 'high' },
  { timeout: 10_000, maxRetries: 0 },
);
```

## Reference

Complete reference of namespaces and methods. For the exact request and response shapes, see the [API reference](https://woku.app/docs/api-reference).

### actionPlans

Reads and drives action plans, including the managed kanban (tasks, AI conversation, and status transitions).

| Method                                | Returns                     | Description                                                                                                         |
| ------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `list(params?, opts?)`                | `Promise<Page<WokuRecord>>` | Lists action plans, optionally filtered by group, status, source, priority, search, or date range, with pagination. |
| `get(id, opts?)`                      | `Promise<WokuRecord>`       | Fetches a single action plan by id.                                                                                 |
| `events(id, opts?)`                   | `Promise<WokuRecord[]>`     | Returns the plan timeline as a list of events, oldest first.                                                        |
| `getConversation(id, opts?)`          | `Promise<WokuRecord>`       | Returns the plan's AI conversation (read-only).                                                                     |
| `reply(id, text, opts?)`              | `Promise<WokuRecord>`       | Sends a reply to the plan AI agent (a paid, asynchronously composed turn with confirm sent automatically).          |
| `createTask(id, body, opts?)`         | `Promise<WokuRecord>`       | Creates a task on the given action plan (idempotent).                                                               |
| `updateTask(id, taskId, body, opts?)` | `Promise<WokuRecord>`       | Updates a specific task on the given action plan.                                                                   |
| `reorderTasks(id, body, opts?)`       | `Promise<WokuRecord>`       | Reorders the tasks of the given action plan.                                                                        |
| `deleteTask(id, taskId, opts?)`       | `Promise<WokuRecord>`       | Deletes a specific task from the given action plan.                                                                 |
| `approve(id, opts?)`                  | `Promise<WokuRecord>`       | Approves the action plan (status transition).                                                                       |
| `reopen(id, opts?)`                   | `Promise<WokuRecord>`       | Reopens the action plan (status transition).                                                                        |
| `cancel(id, opts?)`                   | `Promise<WokuRecord>`       | Cancels the action plan (status transition).                                                                        |
| `complete(id, opts?)`                 | `Promise<WokuRecord>`       | Marks the action plan complete (status transition).                                                                 |
| `resume(id, opts?)`                   | `Promise<WokuRecord>`       | Resumes the action plan (status transition).                                                                        |

### actionPlanGroups

Manages action-plan groups (list, fetch with stats, create, update, enable/disable, and delete).

| Method                           | Returns                 | Description                                                      |
| -------------------------------- | ----------------------- | ---------------------------------------------------------------- |
| `list(params?, opts?)`           | `Promise<WokuRecord[]>` | Lists action-plan groups, optionally filtered by a search query. |
| `get(id, opts?)`                 | `Promise<WokuRecord>`   | Fetches one group along with its embedded stats.                 |
| `create(body, opts?)`            | `Promise<WokuRecord>`   | Creates a new action-plan group (idempotent).                    |
| `update(id, body, opts?)`        | `Promise<WokuRecord>`   | Updates an existing action-plan group.                           |
| `setEnabled(id, enabled, opts?)` | `Promise<WokuRecord>`   | Enables or disables the action-plan group.                       |
| `delete(id, opts?)`              | `Promise<WokuRecord>`   | Deletes the action-plan group.                                   |

### company

Manages the caller company and its API key at /v1/companies/me.

| Method             | Returns                 | Description                                                              |
| ------------------ | ----------------------- | ------------------------------------------------------------------------ |
| `me(opts?)`        | `Promise<WokuRecord>`   | Gets the caller company.                                                 |
| `rotateKey(opts?)` | `Promise<ApiKeyResult>` | Rotates the secret key, replacing the current one with the returned key. |
| `revokeKey(opts?)` | `Promise<WokuRecord>`   | Revokes the secret key so all subsequent requests become unauthorized.   |

### dispatches

Delivery tracking over invitation dispatches (/v1/dispatches).

| Method                  | Returns                   | Description                                                                |
| ----------------------- | ------------------------- | -------------------------------------------------------------------------- |
| `list(params?, opts?)`  | `Promise<Page<Dispatch>>` | Lists the invitation dispatches with delivery status and no recipient PII. |
| `stats(params?, opts?)` | `Promise<DispatchStats>`  | Returns response-rate metrics computed over the dispatches.                |

### flows

Read-only access to data flows (/v1/flows): list them and fetch one by id.

| Method                 | Returns                     | Description                                                                                             |
| ---------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------- |
| `list(params?, opts?)` | `Promise<Page<WokuRecord>>` | List data flows with optional page/limit pagination params, returning a paginated page of flow records. |
| `get(id, opts?)`       | `Promise<WokuRecord>`       | Fetch a single data flow by its id.                                                                     |

### forms

Reads forms and their responses, and sends form invitations over /v1/forms.

| Method                              | Returns                      | Description                                     |
| ----------------------------------- | ---------------------------- | ----------------------------------------------- |
| `list(params?, opts?)`              | `Promise<Page<WokuRecord>>`  | Lists forms with pagination.                    |
| `get(id, opts?)`                    | `Promise<WokuRecord>`        | Fetches a single form by id.                    |
| `listResponses(id, params?, opts?)` | `Promise<Page<WokuRecord>>`  | Lists the responses of a form (paginated).      |
| `sendInvitations(id, body, opts?)`  | `Promise<InvitationsResult>` | Sends a form by email or WhatsApp (idempotent). |

### quarantines

Checks whether a respondent contact is quarantined via the /v1/quarantines endpoint.

| Method                 | Returns               | Description                                                  |
| ---------------------- | --------------------- | ------------------------------------------------------------ |
| `check(params, opts?)` | `Promise<WokuRecord>` | Checks whether a contact (by email or phone) is quarantined. |

### reports

Reads NPS reports at /v1/reports (company-level and per NPS tool).

| Method                               | Returns               | Description                                   |
| ------------------------------------ | --------------------- | --------------------------------------------- |
| `companyNps(params?, opts?)`         | `Promise<WokuRecord>` | Fetches the company-level NPS report.         |
| `npsTool(npsToolId, params?, opts?)` | `Promise<WokuRecord>` | Fetches the NPS report for a single NPS tool. |

### nps

Sends the NPS survey and reads its responses (/v1/nps).

| Method                          | Returns                      | Description                                             |
| ------------------------------- | ---------------------------- | ------------------------------------------------------- |
| `sendInvitations(body, opts?)`  | `Promise<InvitationsResult>` | Sends the NPS survey by email or WhatsApp (idempotent). |
| `listResponses(params?, opts?)` | `Page<WokuRecord>`           | Lists NPS responses with pagination.                    |
| `getResponse(id, opts?)`        | `Promise<WokuRecord>`        | Gets one NPS response by id.                            |

### csat

Sends the CSAT survey and reads its responses (/v1/csat).

| Method                          | Returns                      | Description                                     |
| ------------------------------- | ---------------------------- | ----------------------------------------------- |
| `sendInvitations(body, opts?)`  | `Promise<InvitationsResult>` | Sends the CSAT survey invitations (idempotent). |
| `listResponses(params?, opts?)` | `Page<WokuRecord>`           | Lists CSAT responses with pagination.           |
| `getResponse(id, opts?)`        | `Promise<WokuRecord>`        | Gets one CSAT response by id.                   |

### ces

Sends the CES survey and reads its responses (/v1/ces).

| Method                          | Returns                      | Description                                    |
| ------------------------------- | ---------------------------- | ---------------------------------------------- |
| `sendInvitations(body, opts?)`  | `Promise<InvitationsResult>` | Sends the CES survey invitations (idempotent). |
| `listResponses(params?, opts?)` | `Page<WokuRecord>`           | Lists CES responses with pagination.           |
| `getResponse(id, opts?)`        | `Promise<WokuRecord>`        | Gets one CES response by id.                   |

### tickets

Reads and curates AI-generated support tickets under /v1/tickets.

| Method                    | Returns                 | Description                                                                                                   |
| ------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------- |
| `list(params?, opts?)`    | `Promise<Page<Ticket>>` | Lists support tickets with optional filters (tool, severity, search, destinationId, date range, page, limit). |
| `stats(params?, opts?)`   | `Promise<TicketStats>`  | Returns aggregate ticket counts by tool and by SAC destination.                                               |
| `get(id, opts?)`          | `Promise<Ticket>`       | Fetches a single ticket by id.                                                                                |
| `update(id, body, opts?)` | `Promise<Ticket>`       | Patches a ticket with the given update body.                                                                  |

### ticketDestinations

Manages SAC ticket destinations under /v1/ticket-destinations.

| Method                    | Returns                         | Description                                                                              |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------- |
| `list(opts?)`             | `Promise<WokuRecord[]>`         | Lists all configured ticket destinations.                                                |
| `get(id, opts?)`          | `Promise<WokuRecord>`           | Fetches a single ticket destination by id.                                               |
| `create(body, opts?)`     | `Promise<WokuRecord>`           | Creates a new ticket destination (sent idempotently).                                    |
| `update(id, body, opts?)` | `Promise<WokuRecord>`           | Patches an existing ticket destination.                                                  |
| `delete(id, opts?)`       | `Promise<WokuRecord>`           | Deletes a ticket destination by id.                                                      |
| `test(id, opts?)`         | `Promise<TestConnectionResult>` | Sends a real connectivity test to a saved destination (confirm:true sent automatically). |

### trackers

Manages external tracker definitions and assigns/removes tracker values on wokus and VoC entities (/v1/external-trackers).

| Method                                                 | Returns                       | Description                                                                   |
| ------------------------------------------------------ | ----------------------------- | ----------------------------------------------------------------------------- |
| `list(params?, opts?)`                                 | `Promise<Page<Tracker>>`      | List the company tracker definitions, paginated.                              |
| `create(body, opts?)`                                  | `Promise<Tracker>`            | Create a tracker definition (idempotent).                                     |
| `get(id, opts?)`                                       | `Promise<Tracker>`            | Get one tracker definition by id.                                             |
| `update(id, body, opts?)`                              | `Promise<Tracker>`            | Update a tracker definition.                                                  |
| `activate(id, opts?)`                                  | `Promise<Tracker>`            | Activate a tracker definition.                                                |
| `deactivate(id, opts?)`                                | `Promise<Tracker>`            | Deactivate a tracker definition.                                              |
| `searchEntities(body, opts?)`                          | `Promise<EntitiesByTrackers>` | Search VoC entities whose trackers match every provided filter (AND).         |
| `listWokuValues(wokuId, opts?)`                        | `Promise<WokuRecord[]>`       | List the tracker values assigned to a woku.                                   |
| `assignToWoku(wokuId, body, opts?)`                    | `Promise<WokuRecord>`         | Assign (upsert) a tracker value to a woku by tracker name (idempotent).       |
| `removeFromWoku(wokuId, trackerName, opts?)`           | `Promise<WokuRecord>`         | Remove a tracker value from a woku by tracker name.                           |
| `searchWokus(params, opts?)`                           | `Promise<Page<WokuRecord>>`   | Search wokus by an exact (tracker name, value) pair, paginated.               |
| `listEntityValues(entityType, id, opts?)`              | `Promise<WokuRecord[]>`       | List the tracker values assigned to a VoC entity (nps/csat/ces/form/flow).    |
| `assignToEntity(entityType, id, body, opts?)`          | `Promise<WokuRecord>`         | Assign (upsert) a tracker value to a VoC entity by tracker name (idempotent). |
| `removeFromEntity(entityType, id, trackerName, opts?)` | `Promise<WokuRecord>`         | Remove a tracker value from a VoC entity by tracker name.                     |

### npsTools

Manage NPS tool (survey) definitions under /v1/nps-tools.

| Method                    | Returns                  | Description                                                                                |
| ------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
| `list(params?, opts?)`    | `Promise<Page<NpsTool>>` | List NPS tool definitions with page/limit pagination; the returned page is async-iterable. |
| `create(body, opts?)`     | `Promise<NpsTool>`       | Create a new NPS tool definition (idempotent POST).                                        |
| `get(id, opts?)`          | `Promise<NpsTool>`       | Retrieve a single NPS tool by id via the singular /v1/nps-tool/{id} route.                 |
| `update(id, body, opts?)` | `Promise<NpsTool>`       | Partially update an existing NPS tool definition (PATCH).                                  |
| `delete(id, opts?)`       | `Promise<DeletedResult>` | Delete an NPS tool definition by id.                                                       |

### csatTools

Manage CSAT tool (survey) definitions under /v1/csat-tools.

| Method                    | Returns                   | Description                                                                                 |
| ------------------------- | ------------------------- | ------------------------------------------------------------------------------------------- |
| `list(params?, opts?)`    | `Promise<Page<CsatTool>>` | List CSAT tool definitions with page/limit pagination; the returned page is async-iterable. |
| `create(body, opts?)`     | `Promise<CsatTool>`       | Create a new CSAT tool definition (idempotent POST).                                        |
| `get(id, opts?)`          | `Promise<CsatTool>`       | Retrieve a single CSAT tool by id via the singular /v1/csat-tool/{id} route.                |
| `update(id, body, opts?)` | `Promise<CsatTool>`       | Partially update an existing CSAT tool definition (PATCH).                                  |
| `delete(id, opts?)`       | `Promise<DeletedResult>`  | Delete a CSAT tool definition by id.                                                        |

### cesTools

Manage CES tool (survey) definitions under /v1/ces-tools.

| Method                    | Returns                  | Description                                                                                |
| ------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
| `list(params?, opts?)`    | `Promise<Page<CesTool>>` | List CES tool definitions with page/limit pagination; the returned page is async-iterable. |
| `create(body, opts?)`     | `Promise<CesTool>`       | Create a new CES tool definition (idempotent POST).                                        |
| `get(id, opts?)`          | `Promise<CesTool>`       | Retrieve a single CES tool by id via the singular /v1/ces-tool/{id} route.                 |
| `update(id, body, opts?)` | `Promise<CesTool>`       | Partially update an existing CES tool definition (PATCH).                                  |
| `delete(id, opts?)`       | `Promise<DeletedResult>` | Delete a CES tool definition by id.                                                        |

### wokus

Manages wokus (feedback collection tools) under /v1/wokus, including reviews, settings, folder moves, invitations, and sharing.

| Method                             | Returns                       | Description                                                                       |
| ---------------------------------- | ----------------------------- | --------------------------------------------------------------------------------- |
| `list(params?, opts?)`             | `Promise<Page<WokuResource>>` | Lists the company's wokus with page/limit pagination.                             |
| `create(body, opts?)`              | `Promise<WokuResource>`       | Creates a new woku (idempotent POST).                                             |
| `get(id, opts?)`                   | `Promise<WokuResource>`       | Gets one woku with its aggregated review stats.                                   |
| `update(id, body, opts?)`          | `Promise<WokuResource>`       | Partially updates a woku's fields.                                                |
| `delete(id, opts?)`                | `Promise<DeletedResult>`      | Deletes a woku.                                                                   |
| `updateSettings(id, body, opts?)`  | `Promise<WokuResource>`       | Applies the woku's boolean settings idempotently (closed, reviewsDisabled, etc.). |
| `move(id, body, opts?)`            | `Promise<WokuResource>`       | Moves the woku into a folder, or to the root with folderId null.                  |
| `listReviews(id, params?, opts?)`  | `Promise<Page<WokuRecord>>`   | Lists a woku's reviews with page/limit pagination.                                |
| `sendInvitations(id, body, opts?)` | `Promise<InvitationsResult>`  | Sends a woku review invitation by email or WhatsApp (idempotent).                 |
| `share(id, body, opts?)`           | `Promise<WokuRecord>`         | Shares a woku review link by email.                                               |

## Resources

`trackers`, `npsTools` / `csatTools` / `cesTools`, `nps` / `csat` / `ces`,
`wokus`, `forms`, `flows`, `actionPlans`, `actionPlanGroups`, `tickets`,
`ticketDestinations`, `dispatches`, `reports`, `company`, `quarantines`.

## Versioning

The SDK follows **semantic versioning** (`MAJOR.MINOR.PATCH`). The current
published version is **`0.1.0`**. We recommend pinning a compatible range (for
example `^0.1.0`) and reviewing the changelog before a MAJOR bump. Versions and
their notes are on the
[npm package](https://www.npmjs.com/package/@wokuapp/sdk) and the
[GitHub releases](https://github.com/wokuApp/sdks/releases).

## Resources

* **npm package:** [@wokuapp/sdk](https://www.npmjs.com/package/@wokuapp/sdk)
* **Code and examples:** [github.com/wokuApp/sdks](https://github.com/wokuApp/sdks)
* **Equivalent Python SDK:** [Python SDK](/docs/en/development/sdk-python)
* **API reference:** [API Integration Guide](/docs/en/development/api)
