@omnistreams/sdk
v0.1.0
Published
Official TypeScript SDK for the OmniStream omnichannel CRM API — typed client with auth, pagination, retries, idempotency and webhook signature verification.
Readme
@omnistreams/sdk
Official TypeScript SDK for the OmniStream omnichannel CRM API. Types are generated from the published OpenAPI spec; the runtime adds auth, retries, pagination, idempotency and webhook verification.
Install
npm install @omnistreams/sdkRequires Node.js ≥ 18 (uses the global fetch and Web Crypto).
Quick start
import { OmnistreamClient } from "@omnistreams/sdk";
const client = new OmnistreamClient({
apiKey: process.env.OMNISTREAM_API_KEY!, // create in Developer → API Keys
baseUrl: "https://your-omnistream-host", // default http://localhost:3000
});
// Typed resource helpers
const open = await client.conversations.list({ status: "open" });
const message = await client.conversations.sendMessage(open[0].id, {
type: "text",
content: { text: "Hi! How can I help?" },
});Features
Auth
Every request sends your key as X-API-Key. Lock the key down with an IP
allow list (Developer → API Keys) for server-to-server use.
Retries & rate limits
Failed requests are retried automatically with exponential backoff and full
jitter. 429 responses honour the Retry-After header. Safe methods (GET)
retry on network/5xx errors; unsafe methods only retry on 429 — unless you
pass an idempotency key (see below).
const client = new OmnistreamClient({ apiKey, maxRetries: 3, timeoutMs: 15000 });Idempotency
Pass an idempotency key so a POST can be safely retried on transient failures:
import { generateIdempotencyKey } from "@omnistreams/sdk";
await client.conversations.sendMessage(
id,
{ type: "text", content: { text: "hi" } },
{ idempotencyKey: generateIdempotencyKey() },
);Pagination
paginate() returns an async iterator that walks page-numbered list endpoints
lazily:
import type { Contact } from "@omnistreams/sdk";
for await (const contact of client.paginate<Contact>("/api/contacts", { search: "acme" })) {
console.log(contact.name);
}Typed errors
import { OmnistreamApiError, OmnistreamNetworkError } from "@omnistreams/sdk";
try {
await client.conversations.get("does-not-exist");
} catch (err) {
if (err instanceof OmnistreamApiError && err.isNotFound) {
// 404
} else if (err instanceof OmnistreamNetworkError && err.timedOut) {
// request timed out
}
}OmnistreamApiError exposes status, code, body, and helpers:
isAuthError (401), isForbidden (403), isNotFound (404),
isValidationError (422), isRateLimited (429), isServerError (5xx).
Webhook verification
Verify inbound webhooks signed by the gateway (X-Omnistream-Signature,
HMAC-SHA256 hex). Works in Node, browsers and edge runtimes.
import { verifyWebhookSignature, verifyWebhookSignatureWithRotation } from "@omnistreams/sdk";
// rawBody must be the exact bytes received — verify BEFORE JSON.parse.
const ok = await verifyWebhookSignature(rawBody, req.headers["x-omnistream-signature"], secret);
// During a secret rotation, accept the current OR previous signature:
const okRotating = await verifyWebhookSignatureWithRotation(rawBody, secret, {
current: req.headers["x-omnistream-signature"],
previous: req.headers["x-omnistream-signature-previous"],
});Low-level access
Every endpoint is reachable through the generic verbs, and the full generated OpenAPI types are exported:
import type { components } from "@omnistreams/sdk";
type Campaign = components["schemas"]["Campaign"];
const campaigns = await client.get<Campaign[]>("/api/campaigns", { page: 1 });
await client.request("DELETE", `/api/api-keys/${keyId}`);Development
npm install
npm run generate # regenerate src/generated/openapi.ts from ../../docs/openapi.yaml
npm run build
npm testRegenerate the types whenever docs/openapi.yaml changes.
