@wokuapp/sdk
v0.2.2
Published
Official server-side SDK for the Woku management API (trackers, VoC tools, action plans, tickets, delivery and capture over /v1).
Maintainers
Readme
@wokuapp/sdk
Official server-side SDK for the Woku management API.
Why
Manage your entire Woku account from your backend with one typed client:
trackers, VoC tools (NPS/CSAT/CES), wokus, forms, flows, action plans,
support tickets, delivery tracking and survey sends over the public /v1 API.
- Typed request bodies (generated from the OpenAPI spec) and response models.
- Automatic retries with full-jitter backoff and
Retry-Aftersupport. - Idempotent creates: creates carry an auto-generated
Idempotency-Key, so a retry after a blip never creates twice. Action calls (send,test,reply) are never silently replayed. - Auto-paginated lists:
for await (const item of await woku.tickets.list()). - Typed errors with the server
request_idfor support. - Zero runtime dependencies.
Server-only. The secret key grants full management access, so the SDK refuses to run in a browser. Never ship it to a client bundle.
Install
npm install @wokuapp/sdk
# or: pnpm add @wokuapp/sdk / yarn add @wokuapp/sdkRequires Node.js 18+ (uses the global fetch).
Quickstart
import { Woku } from '@wokuapp/sdk';
const woku = new Woku({ apiKey: process.env.WOKU_API_KEY });
// Create a tracker definition (idempotent).
const tracker = await woku.trackers.create({
name: 'Store #1',
system: 'retail',
});
// Create an NPS tool.
const tool = await woku.npsTools.create({
name: 'Post-purchase',
npsMessage: 'How likely are you to recommend us?',
});
// Tag the NPS tool with the tracker, so every response is grouped by store.
await woku.trackers.assignToEntity('nps', tool._id, {
name: tracker.name,
value: 'TX-42',
});
// Send it, then read delivery + response rate.
await woku.nps.sendInvitations({
channel: 'email',
npsToolId: tool._id,
recipients: ['[email protected]'],
});
const stats = await woku.dispatches.stats({ channel: 'email' });
console.log(stats.responseRate);The key is read from WOKU_API_KEY when you omit apiKey. You can also pass
it directly: new Woku('sk_live_...').
Pagination
List methods return a Page. Iterate every item across pages, or walk pages:
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();
}Errors
Every failure is a WokuError. HTTP errors are typed subclasses carrying the
status, parsed body and requestId:
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/abort) are WokuConnectionError /
WokuTimeoutError.
Configuration
new Woku({
apiKey: process.env.WOKU_API_KEY,
baseURL: 'https://clientapi.woku.app', // default
timeout: 60_000, // ms, default
maxRetries: 2, // default
});Per-call overrides go in the last argument of any method:
await woku.tickets.list(
{ severity: 'high' },
{ timeout: 10_000, maxRetries: 0 },
);
await woku.npsTools.create(body, { idempotencyKey: 'my-key' });Resources
trackers, npsTools / csatTools / cesTools, nps / csat / ces,
wokus, forms, flows, actionPlans, actionPlanGroups, tickets,
ticketDestinations, dispatches, reports, company, quarantines.
License
MIT
