Builder, not flat
kirim.phoneNumbers('id').messages.send(...) reads like the URL it
hits. No hand-built paths, no juggling phone IDs in every call.
@kirimdev/sdk is the official TypeScript client for the kirim.dev
Public API. Its builder shape mirrors the URL structure: organization
resources hang off the root client, per-phone-number resources hang off
kirim.phoneNumbers(id). Types are generated from the live OpenAPI
spec, retries and pagination are handled for you, and the runtime uses
only web-standard fetch so the same code runs in Node, Bun, Deno, and
edge.
Builder, not flat
kirim.phoneNumbers('id').messages.send(...) reads like the URL it
hits. No hand-built paths, no juggling phone IDs in every call.
Type-safe
Request and response types come from the live OpenAPI 3.1 spec at build time. Autocomplete and compile-time checks on every field.
Safe to retry
Auto-retries 429 / 5xx / network errors with exponential backoff and
honors Retry-After. POSTs carry an Idempotency-Key so the same
key is reused across retries.
Async pagination
Every list() is async-iterable. for await exhausts pages
transparently, or call .page() for manual cursor control.
Typed errors
KirimError hierarchy — branch with instanceof, drill into
code / param / requestId / retryAfter.
Runs anywhere
Web-standard fetch only. Node 18+, Bun, Deno, Cloudflare Workers,
Vercel Edge — no Node-specific dependencies.
bun add @kirimdev/sdknpm install @kirimdev/sdkpnpm add @kirimdev/sdkyarn add @kirimdev/sdkimport { Kirim } from 'npm:@kirimdev/sdk'Requirements: Node 18+, Bun 1.2+, or Deno 1.40+. ESM only. Types ship
with the package — no @types/... needed.
import { Kirim } from '@kirimdev/sdk'
const kirim = new Kirim({ apiKey: process.env.KIRIM_KEY! })
// Pick the phone number you want to send from.const phone = kirim.phoneNumbers('106540352242922')
const msg = await phone.messages.send({ messaging_product: 'whatsapp', to: '+628111222333', type: 'text', text: { body: 'Halo dari @kirimdev/sdk!' },})
console.log(msg.id, msg.status)That’s the entire contract: construct once, scope to a phone number
when needed, call resource methods. Every method returns a
Promise<T> where T is the unwrapped resource — the SDK strips the
{ data, request_id } envelope for you.
The SDK has two tiers, matching the API’s URL structure:
kirim ← root client (org / team scope)├── kirim.accounts ← all WhatsApp numbers in the org├── kirim.labels ← labels (org-wide)├── kirim.webhookSubscriptions ← webhook endpoints├── kirim.webhookDeliveries ← delivery history & replays├── kirim.me() ← who am I│└── kirim.phoneNumbers('id') ← scoped to one WhatsApp number ├── .messages ← send / retrieve / list / media ├── .contacts ← CRUD + labels ├── .conversations ← list / update / labels └── .templates ← list / retrieveawait kirim.accounts.list() // every connected numberawait kirim.labels.create({ name: 'VIP', color: 'green' })await kirim.labels.list()await kirim.webhookSubscriptions.create({ url, events })await kirim.webhookDeliveries.list({ status: 'failed' })await kirim.me() // current API key contextconst phone = kirim.phoneNumbers('106540352242922')
await phone.messages.send({ messaging_product: 'whatsapp', to: '+628111222333', type: 'text', text: { body: 'Hi' },})await phone.messages.retrieve(messageId)await phone.messages.media(messageId) // signed redirect URL info
await phone.contacts.create({ phone_number: '+628111222333' })await phone.contacts.addLabel(contactId, { label_id })await phone.contacts.bulkLabel({ contact_ids, label_id, operation: 'add' })
await phone.conversations.update(id, { status: 'resolved' })await phone.templates.list({ status: 'approved' })new Kirim({ apiKey: 'kdv_live_...', // required baseUrl: 'https://api.kirim.chat/v1', // optional, default production timeout: 30_000, // optional, ms (default 30s) maxRetries: 2, // optional, default 2 userAgentSuffix: 'myapp/1.2.3', // optional, appended to UA fetch: customFetch, // optional, default globalThis.fetch})KirimError hierarchy
and recipes for every subclass.for await vs.
manual .page(), cursor stability rules, common pitfalls.verify() from
@kirimdev/sdk/webhooks, framework adapters, secret rotation.