@postwave/sdk
v0.1.0
Published
Official TypeScript SDK for the Postwave email platform — campaigns, subscribers, sequences, voice, sandbox, budgets, approvals. Designed for software agents and developer-driven workflows.
Maintainers
Readme
@postwave/sdk
First-party TypeScript SDK for the Postwave API. MIT licensed as Layer 2 of the Postwave open-core architecture.
- Strict types end-to-end (no
any). - Dual ESM + CJS build.
- Works in Node 18+, modern browsers, and edge runtimes.
- Exponential-backoff retries on 429 / 5xx (with
Retry-Afterhonoring). - Constant-time HMAC-SHA256 webhook signature verification.
- Hand-written — no codegen toolchain — kept in lockstep with
packages/openapi.
Install
pnpm add @postwave/sdk
# or: npm i / yarn addQuickstart
import { PostwaveClient } from "@postwave/sdk";
const pw = new PostwaveClient({
apiKey: process.env.POSTWAVE_API_KEY!,
tenantId: "acme", // omit in prod when JWT carries tenant claim
});
// Generate a 3-email welcome series
const seq = await pw.sequences.generate({
template_id: "tpl_welcome_3",
name: "Welcome series",
variables: { product_name: "Acme", founder_name: "Alex" },
});
console.log(seq.emails[0].subject);Method index
| Resource | Methods |
|-------------------------|---------|
| pw.migrations | start, callback, discover, dryRun, commit, get, verification, rollback, rollbackStatus, listSources |
| pw.subscribers | list, get, create, update, delete, search, suppress |
| pw.sequences | list, get, generate, regenerate |
| pw.templates | list, get, create |
| pw.voiceProfile | get, build, listSources, addSource, ingestSource, removeSource |
| pw.forms | list, get, create, update, delete, listSubmissions, exportSubmissionsCSV |
| pw.inboxReality | getCampaignReport, predict, diagnose, render |
| pw.reputation | get |
| pw.authChecks | list |
| pw.sending | provision, getState, getWarmup |
| pw.automations | trigger, listExecutions, pause, resume |
| pw.webhooks | list, create, update, delete, verifySignature |
Error handling
Every method throws a typed subclass of PostwaveError:
import { PostwaveClient, NotFoundError, RateLimitError } from "@postwave/sdk";
try {
await pw.subscribers.get("does-not-exist");
} catch (e) {
if (e instanceof NotFoundError) console.warn(`gone: ${e.code}`);
else if (e instanceof RateLimitError) console.warn(`retry in ${e.retryAfterSeconds}s`);
else throw e;
}Every error carries status, code, message, and (when the gateway sets it)
a requestId you can include in support tickets.
Webhook signature verification
import { verifySignature } from "@postwave/sdk";
// Express, with body-parser raw middleware so req.body is a Buffer:
app.post("/postwave-webhook", async (req, res) => {
const ok = await verifySignature(
req.body,
req.headers["x-postwave-signature"] as string,
process.env.POSTWAVE_WEBHOOK_SECRET!,
);
if (!ok) return res.status(401).end();
const evt = JSON.parse(req.body.toString());
// ... handle evt
res.status(200).end();
});The verifier uses Web Crypto and works unchanged on Cloudflare Workers, Vercel Edge, Deno, Bun, and Node 18+.
Contributing
Open a PR against packages/sdk-ts/. Run:
pnpm -F @postwave/sdk test
pnpm -F @postwave/sdk typecheck
pnpm -F @postwave/sdk buildThe OpenAPI spec at packages/openapi/openapi.yaml is the source of truth;
keep src/types.ts in sync with any spec change in the same PR.
