DocsNode.js SDK

Node.js SDK

The official Node.js SDK for the Squalto WhatsApp Business Platform — typed, zero-dependency, production-ready.

@squalto/sdk@0.1.0Node 18, 20, 22 · ESM + CJS · TypeScript types included

Introduction

@squalto/sdk is a typed client for the Squalto REST API. It replaces hand-rolled HTTP calls with a clean, Twilio-style interface that handles authentication, retries, idempotency, auto-pagination, typed errors, and webhook verification out of the box.

The SDK talks to Squalto — not to Meta directly. Squalto wraps the WhatsApp Cloud API server-side, so you never manage Meta access tokens or phone-number ids.

  • Zero runtime dependencies, tree-shakeable, and fully typed.
  • Automatic retries with exponential backoff on transient failures.
  • Idempotency keys on message and campaign sends to prevent duplicates.
  • Auto-paginating list methods you can iterate with for await.
  • First-class webhook signature verification and typed parsing.

Installation

Install the package from npm. The SDK ships both ESM and CommonJS builds along with TypeScript declarations, and supports Node 18 and above.

bash
npm install @squalto/sdk
# or: pnpm add @squalto/sdk
# or: yarn add @squalto/sdk

Authentication

Authenticate with an account SID (AC…) and an auth token (SK… secret) from your Squalto dashboard. Construct the client once and reuse it across your application.

client.ts
import { Squalto } from "@squalto/sdk";

export const squalto = new Squalto(
  process.env.SQUALTO_ACCOUNT_SID!,
  process.env.SQUALTO_AUTH_TOKEN!,
);
Never hard-code your auth token or expose it in client-side code. Load it from an environment variable or secret manager.

Quickstart

Send your first message in under a minute. Template messages can be delivered at any time; free-form text replies are only deliverable inside the 24-hour customer service window.

send.ts
import { squalto } from "./client";

// Send an approved template (deliverable any time)
const message = await squalto.whatsapp.messages.create({
  to: "+15551234567",
  templateName: "order_update",
  variables: { "1": "Alice", "2": "#1234" },
});

console.log(message.id, message.status); // e.g. "msg_…", "accepted"

// Send a free-form reply (inside the 24h service window)
await squalto.whatsapp.messages.sendText({
  to: "+15551234567",
  body: "Thanks for your order! 🎉",
});

Auto-pagination

Every list method returns an async iterable that transparently walks pages for you. Iterate the whole collection with for await, or fetch a single page manually.

typescript
// Iterate every matching contact across all pages
for await (const contact of squalto.whatsapp.contacts.list({ tag: "vip" })) {
  console.log(contact.phone);
}

// Or fetch a single 1-indexed page
const page = await squalto.whatsapp.contacts.list().page(1);
console.log(page.data, page.total);

// Or collect everything into an array
const all = await squalto.whatsapp.contacts.list().all();

Error handling

Failed requests throw a typed error subclass so you can branch on the failure mode. All API errors extend SqualtoApiError; transport failures throw SqualtoConnectionError.

typescript
import { ValidationError, RateLimitError } from "@squalto/sdk";

try {
  await squalto.whatsapp.messages.sendText({ to: "bad", body: "hi" });
} catch (err) {
  if (err instanceof ValidationError) {
    console.error(err.errors); // field-level detail
  } else if (err instanceof RateLimitError) {
    console.error(`Retry after ${err.retryAfter}s`);
  } else {
    throw err;
  }
}

Error classes

  • AuthenticationError — 401, missing or invalid API key.
  • ValidationError — 422, request failed validation (see .errors).
  • NotFoundError — 404, the resource does not exist.
  • ConflictError — 409, conflicts with current state.
  • RateLimitError — 429, includes .retryAfter (seconds).
  • ApiError — any other 4xx/5xx response.
  • SqualtoConnectionError — the request never reached the API.
Retries are automatic. The SDK retries 429 and 5xx responses (and transport errors) with exponential backoff and jitter, honoring the Retry-After header. Only after retries are exhausted does the error surface to your code.

Webhooks

Verify inbound webhooks with a constant-time HMAC-SHA256 check over the raw request body, then parse the payload into a typed, discriminated union. Capture the raw body before any JSON body parser runs.

webhook.ts
import express from "express";
import { Squalto } from "@squalto/sdk";

const squalto = new Squalto(sid, token, {
  webhookSigningSecret: process.env.SQUALTO_WEBHOOK_SECRET,
});
const app = express();

app.post(
  "/webhooks/squalto",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const valid = squalto.webhooks.validateSignature(
      req.body,
      req.get("X-Hub-Signature-256"),
    );
    if (!valid) return res.sendStatus(401);

    res.sendStatus(200); // ack immediately, then process

    const event = squalto.webhooks.parse(req.body);
    switch (event.type) {
      case "message":           /* inbound customer message */ break;
      case "status":            /* delivery receipt */          break;
      case "template_status":   /* Meta approval / rejection */ break;
      case "template_category": /* category change */           break;
    }
  },
);

Configuration

Pass an options object as the third constructor argument to tune the client. All fields are optional.

typescript
new Squalto(accountSid, authToken, {
  baseUrl: "https://api.squalto.com/api/v1", // or set SQUALTO_BASE_URL
  timeout: 30_000,          // per-request timeout in ms
  maxRetries: 3,            // retries on 429 / 5xx / transport errors
  fetch: globalThis.fetch,  // inject a custom fetch (tests, proxies)
  webhookSigningSecret: "…",
});

API reference

The WhatsApp service is exposed under client.whatsapp, with webhook helpers under client.webhooks. Full method signatures ship with the TypeScript declarations.

  • messages — sendText, create, list, get
  • templates — create, list, update
  • campaigns — create, list, get, listMessages, cancel
  • contacts — create, get, update, delete, list, bulkDelete, addToList, removeFromList, import, export
  • lists — create, list, update, delete
  • tags — list
  • audience — preview
  • media — upload
  • conversations — list, listMessages, markRead
  • webhooks — validateSignature, parse

Ready to build?

Grab your API keys from the dashboard and send your first message today.

Get Started Free