Skip to content

Node.js / TypeScript

Use the official SDK @whatstig/sdk (ESM, Node 18.17+, typed from the OpenAPI contract). A complete runnable example lives in the repository at examples/node-typescript (src/reminder.ts shows invoice reminders with native follow-ups: a reminder sequence, anchorAt, dedupeKey, rescheduling and cancelling).

npm install @whatstig/sdk

Client

import { WhatsTig, WhatsTigError } from '@whatstig/sdk';

const wt = new WhatsTig({
  apiKey: process.env.WHATSTIG_API_KEY!,      // server-side only
  baseUrl: process.env.WHATSTIG_BASE_URL,      // default https://api.whatstig.com
  timeoutMs: 30_000,
  maxRetries: 2,                               // network errors, 429, 502-504 on safe requests only
});

Instances

const instance =
  (await wt.instances.findByExternalReference('tenant-101')) ??
  (await wt.instances.create({ name: 'School A WhatsApp', externalReference: 'tenant-101' }, { idempotencyKey: 'create-tenant-101' }));

await wt.instances.connect(instance.id, { method: 'qr' });
const pairing = await wt.instances.qr(instance.id);       // pairing.qrDataUrl → <img src=...>
const final = await wt.instances.waitForConnected(instance.id, 180_000);

Messages

const accepted = await wt.messages.send(
  { instanceId: instance.id, recipient: '923001234567', type: 'text', content: { text: 'Hello' }, clientReference: 'n-1' },
  { idempotencyKey: 'n-1' },
);

const msg = await wt.messages.get(accepted.id);          // status: QUEUED | PROCESSING | SENT | DELIVERED | READ | FAILED | UNKNOWN
for await (const m of wt.messages.listAll({ status: 'FAILED' })) console.log(m.id, m.failure?.code);

// Media
const media = await wt.media.upload(await readFile('report.pdf'), 'report.pdf', 'application/pdf');
await wt.messages.send({ instanceId: instance.id, recipient: '923001234567', type: 'document', content: { mediaId: media.id, fileName: 'Report.pdf' } });

Errors

try {
  await wt.messages.send(/* ... */);
} catch (err) {
  if (err instanceof WhatsTigError) {
    // err.status, err.code (e.g. INVALID_RECIPIENT), err.message, err.requestId, err.details, err.retryAfterSeconds
  }
  throw err;
}

Webhooks (Express)

import express from 'express';
import { verifyWebhook, WebhookVerificationError } from '@whatstig/sdk';

const app = express();
// Raw body is required for signature verification.
app.post('/whatstig/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = verifyWebhook(req.body, req.header('WhatsTIG-Signature'), process.env.WHATSTIG_WEBHOOK_SECRET!);
    void handleEvent(event); // dedupe on event.id, process asynchronously
    res.sendStatus(200);
  } catch (err) {
    res.sendStatus(err instanceof WebhookVerificationError ? 401 : 500);
  }
});

Without the SDK, any HTTP client works; see Generic REST and the verification snippet in Webhooks.