TypeScript SDK
The official TypeScript and JavaScript client library for the RevKeen API
Build and bill on RevKeen from any Node.js, Bun, Deno, or TypeScript runtime. Typed end-to-end from the OpenAPI spec, with auto-pagination, automatic retries, webhook verification, and first-class OAuth support.
Repo: github.com/RevKeen/sdk-typescript · Releases · Issues · npm
Generated from packages/openapi/openapi.json. See the versioning page for the compatibility matrix.
Install
npm install @revkeen/sdkpnpm add @revkeen/sdkyarn add @revkeen/sdkbun add @revkeen/sdkRequires Node.js 18+ (or any modern runtime with fetch). Ships with full TypeScript definitions — no @types package needed.
Quick start
import { RevKeen } from "@revkeen/sdk";
const client = new RevKeen({
apiKey: process.env.REVKEEN_API_KEY!,
});
const customer = await client.customers.create({
email: "ops@acme.example",
name: "Acme Inc.",
});
console.log(customer.id);That's it. Every endpoint in the API reference is available as a typed method on client.
What's inside
- Fully typed request and response shapes — autocomplete + compile-time validation for every field
- Automatic pagination —
for await (const customer of client.customers.list()) - Automatic retries — idempotent requests retry on 5xx and network errors with exponential backoff
- Idempotency keys — attached automatically on safe-to-retry mutations; override per-call
- Webhook verification —
client.webhooks.verify(rawBody, signature, secret)in a single line - OAuth 2.1 + API-key auth — drop in either, mix per-request if needed
- Runtime-agnostic — Node.js, Bun, Deno, Cloudflare Workers, Vercel Edge
Authentication
import { RevKeen } from "@revkeen/sdk";
// Use `rk_sandbox_*` for sandbox, `rk_live_*` for production.
const client = new RevKeen({
apiKey: process.env.REVKEEN_API_KEY!,
});import { RevKeen } from "@revkeen/sdk";
// Client-credentials grant — the SDK acquires, caches, and rotates tokens.
const client = new RevKeen({
oauth: {
clientId: process.env.REVKEEN_CLIENT_ID!,
clientSecret: process.env.REVKEEN_CLIENT_SECRET!,
scopes: ["customers:read", "invoices:write"],
},
});See the OAuth guide for authorization-code + PKCE, MCP integrations, and the full scope reference.
Common workflows
Create a customer and invoice
const customer = await client.customers.create({
email: "ops@acme.example",
name: "Acme Inc.",
});
const invoice = await client.invoices.create({
customer_id: customer.id,
currency: "USD",
lines: [{
description: "Pro plan — January 2026",
unit_amount_minor: 9999,
quantity: 1,
}],
});
await client.invoices.finalize(invoice.id);
await client.invoices.send(invoice.id);Start a hosted checkout
const session = await client.checkoutSessions.create({
mode: "payment",
customer_id: customer.id,
success_url: "https://yourapp.com/success",
cancel_url: "https://yourapp.com/cancel",
line_items: [{ price_id: "price_01HT...", quantity: 1 }],
});
return Response.redirect(session.url, 303);Iterate with auto-pagination
// Streams every page automatically — no manual offset tracking.
for await (const invoice of client.invoices.list({ status: "open" })) {
console.log(invoice.id, invoice.amount_due_minor);
}
// Or materialise the first N.
const first100 = await client.invoices.list({ limit: 100 }).toArray();Verify a webhook
import { RevKeen, RevKeenError } from "@revkeen/sdk";
const client = new RevKeen({ apiKey: process.env.REVKEEN_API_KEY! });
export async function POST(request: Request) {
const rawBody = await request.text();
const signature = request.headers.get("x-revkeen-signature");
const secret = process.env.REVKEEN_WEBHOOK_SECRET!;
try {
const event = client.webhooks.verify(rawBody, signature!, secret);
if (event.type === "invoice.paid") {
await fulfil(event.data.object);
}
return new Response(null, { status: 200 });
} catch (err) {
if (err instanceof RevKeenError) return new Response(err.message, { status: 400 });
throw err;
}
}See webhook signing for the wire format and replay protection.
Error handling
Every non-2xx response throws a typed RevKeenError with the same envelope documented on the errors page:
import { RevKeen, RevKeenError } from "@revkeen/sdk";
try {
await client.customers.retrieve("cus_does_not_exist");
} catch (err) {
if (err instanceof RevKeenError) {
console.log(err.code); // "resource_missing"
console.log(err.status); // 404
console.log(err.requestId); // "req_01HT..."
}
throw err;
}Idempotency
Mutations automatically carry an idempotency key. Override per-request when you need deterministic retry across processes:
import { randomUUID } from "node:crypto";
const refund = await client.refunds.create(
{ charge: "ch_01HT...", amount_minor: 1500 },
{ idempotencyKey: randomUUID() },
);See idempotency for the replay contract.
Retries and timeouts
const client = new RevKeen({
apiKey: process.env.REVKEEN_API_KEY!,
maxRetries: 3, // default 2
timeout: 30_000, // default 60_000ms
});Retries apply to 5xx, 429, and network errors on safe methods. Non-idempotent mutations without an idempotency key never retry.
Compatibility
| Runtime | Status |
|---|---|
| Node.js 18+ | Supported |
| Bun 1+ | Supported |
| Deno 1.40+ | Supported |
| Cloudflare Workers | Supported |
| Vercel Edge Runtime | Supported |
| Browsers | Not supported — API keys must stay server-side |
Package format: ESM and CommonJS. API version pinned via apiVersion on the constructor — see versioning.