TypeScript SDK
Official RevKeen SDK for TypeScript and JavaScript
The RevKeen TypeScript SDK provides a type-safe interface to the RevKeen API. It works with Node.js, Deno, Bun, and modern browsers.
Installation
npm install @revkeen/sdkRequirements
- Node.js 18+ (or Deno, Bun)
- TypeScript 4.7+ (optional, for type checking)
Quick Start
import RevKeen from '@revkeen/sdk';
const client = new RevKeen({
apiKey: process.env.REVKEEN_API_KEY,
});
// Create a customer
const customer = await client.customers.create({
email: 'john@example.com',
name: 'John Doe',
});
console.log(customer.data.id);Configuration
import RevKeen from '@revkeen/sdk';
const client = new RevKeen({
// Required
apiKey: 'rk_live_xxxxxxxx',
// Optional
baseUrl: 'https://api.revkeen.com', // API base URL
timeout: 30000, // Request timeout in ms
maxRetries: 3, // Retry attempts for failures
fetch: customFetch, // Custom fetch implementation
httpAgent: customAgent, // Custom HTTP agent (Node.js)
});Environment Variables
The SDK automatically reads from environment variables:
REVKEEN_API_KEY=rk_live_xxxxxxxxResources
Customers
// List customers
const customers = await client.customers.list({
limit: 20,
page: 1,
});
// Create a customer
const customer = await client.customers.create({
email: 'john@example.com',
name: 'John Doe',
companyName: 'Acme Inc',
metadata: {
salesforce_id: '00Q123',
},
});
// Retrieve a customer
const customer = await client.customers.retrieve('cus_xxxxxxxx');
// Update a customer
const customer = await client.customers.update('cus_xxxxxxxx', {
name: 'John Smith',
});
// Delete a customer
await client.customers.delete('cus_xxxxxxxx');Products
// List products
const products = await client.products.list({
kind: 'subscription',
isActive: true,
});
// Create a product
const product = await client.products.create({
productId: 'pro_monthly',
name: 'Pro Plan',
kind: 'subscription',
pricingModel: 'recurring',
amountMinor: 2900,
currency: 'USD',
interval: 'month',
intervalCount: 1,
trialDays: 14,
});
// Retrieve a product
const product = await client.products.retrieve('prod_xxxxxxxx');
// Update a product
const product = await client.products.update('prod_xxxxxxxx', {
name: 'Pro Plan (Updated)',
});Subscriptions
// List subscriptions
const subscriptions = await client.subscriptions.list({
customerId: 'cus_xxxxxxxx',
status: 'active',
});
// Create a subscription
const subscription = await client.subscriptions.create({
customerId: 'cus_xxxxxxxx',
productId: 'prod_xxxxxxxx',
trialDays: 14,
});
// Retrieve a subscription
const subscription = await client.subscriptions.retrieve('sub_xxxxxxxx');
// Update a subscription (change plan)
const subscription = await client.subscriptions.update('sub_xxxxxxxx', {
productId: 'prod_yyyyyyyy',
proration: 'create_prorations',
});
// Cancel a subscription
await client.subscriptions.cancel('sub_xxxxxxxx', {
cancelAtPeriodEnd: true,
});
// Pause a subscription
await client.subscriptions.pause('sub_xxxxxxxx', {
resumeAt: '2025-03-01T00:00:00Z',
});
// Resume a subscription
await client.subscriptions.resume('sub_xxxxxxxx');Invoices
// List invoices
const invoices = await client.invoices.list({
customerId: 'cus_xxxxxxxx',
status: 'sent',
});
// Create an invoice
const invoice = await client.invoices.create({
customerId: 'cus_xxxxxxxx',
currency: 'USD',
dueDate: '2025-02-15T00:00:00Z',
lineItems: [
{
description: 'Consulting Services',
quantity: 10,
unitAmountMinor: 15000,
},
],
});
// Submit for approval
await client.invoices.submit('inv_xxxxxxxx');
// Approve an invoice
await client.invoices.approve('inv_xxxxxxxx');
// Send an invoice
await client.invoices.send('inv_xxxxxxxx');
// Void an invoice
await client.invoices.void('inv_xxxxxxxx', {
reason: 'Duplicate invoice',
});
// Download PDF
const pdfBuffer = await client.invoices.getPdf('inv_xxxxxxxx');Checkout Sessions
// Create a checkout session
const session = await client.checkoutSessions.create({
mode: 'subscription',
productId: 'prod_xxxxxxxx',
customerId: 'cus_xxxxxxxx',
successUrl: 'https://yourapp.com/success',
cancelUrl: 'https://yourapp.com/cancel',
});
// Redirect to checkout
window.location.href = session.data.url;
// Retrieve a session
const session = await client.checkoutSessions.retrieve('chk_xxxxxxxx');
// Expire a session
await client.checkoutSessions.expire('chk_xxxxxxxx');Webhooks
// List webhook endpoints
const webhooks = await client.webhooks.list();
// Create a webhook endpoint
const webhook = await client.webhooks.create({
url: 'https://yourapp.com/webhooks/revkeen',
events: ['invoice.paid', 'subscription.created'],
});
// Store the secret for verification
console.log(webhook.data.secret);
// Update a webhook
const webhook = await client.webhooks.update('whk_xxxxxxxx', {
events: ['invoice.paid', 'subscription.created', 'subscription.cancelled'],
});
// Delete a webhook
await client.webhooks.delete('whk_xxxxxxxx');Pagination
Manual Pagination
const page1 = await client.customers.list({ limit: 20, page: 1 });
const page2 = await client.customers.list({ limit: 20, page: 2 });
console.log('Total:', page1.pagination.total);
console.log('Pages:', page1.pagination.totalPages);Auto-Pagination
// Iterate through all results
for await (const customer of client.customers.list()) {
console.log(customer.id, customer.email);
}
// Get all results as array
const allCustomers = await client.customers.list().all();Error Handling
import RevKeen, {
RevKeenError,
NotFoundError,
ValidationError,
UnauthorizedError,
ForbiddenError,
RateLimitError,
InternalServerError,
} from '@revkeen/sdk';
try {
const customer = await client.customers.retrieve('cus_invalid');
} catch (error) {
if (error instanceof NotFoundError) {
// 404 - Resource not found
console.log('Customer not found');
} else if (error instanceof ValidationError) {
// 400/422 - Validation failed
console.log('Validation error:', error.message);
console.log('Details:', error.details);
} else if (error instanceof UnauthorizedError) {
// 401 - Invalid API key
console.log('Invalid API key');
} else if (error instanceof ForbiddenError) {
// 403 - Insufficient permissions
console.log('Permission denied');
} else if (error instanceof RateLimitError) {
// 429 - Rate limited
console.log('Rate limited, retry after:', error.retryAfter, 'seconds');
} else if (error instanceof InternalServerError) {
// 5xx - Server error
console.log('Server error, please retry');
} else if (error instanceof RevKeenError) {
// Generic API error
console.log('API error:', error.code, error.message);
}
}Webhook Verification
import { verifyWebhook, WebhookEvent } from '@revkeen/sdk/webhooks';
// Express.js example
app.post('/webhooks/revkeen', express.raw({ type: 'application/json' }), (req, res) => {
const payload = req.body.toString();
const signature = req.headers['x-revkeen-signature'] as string;
try {
const event: WebhookEvent = verifyWebhook(
payload,
signature,
process.env.WEBHOOK_SECRET!
);
switch (event.type) {
case 'invoice.paid':
handleInvoicePaid(event.data);
break;
case 'subscription.created':
handleSubscriptionCreated(event.data);
break;
case 'subscription.cancelled':
handleSubscriptionCancelled(event.data);
break;
}
res.json({ received: true });
} catch (error) {
console.error('Webhook verification failed:', error);
res.status(400).send('Invalid signature');
}
});TypeScript Types
All types are exported from the package:
import RevKeen, {
// Resource types
Customer,
Product,
Subscription,
Invoice,
CheckoutSession,
Webhook,
// Request types
CustomerCreateParams,
ProductCreateParams,
SubscriptionCreateParams,
InvoiceCreateParams,
// Response types
CustomerListResponse,
ProductListResponse,
// Enums
SubscriptionStatus,
InvoiceStatus,
ProductKind,
BillingInterval,
} from '@revkeen/sdk';
// Use types in your code
async function createCustomer(params: CustomerCreateParams): Promise<Customer> {
const response = await client.customers.create(params);
return response.data;
}Request Options
Pass request options to individual calls:
// Custom timeout for slow operations
const customers = await client.customers.list({}, {
timeout: 60000,
});
// Idempotency key for POST requests
const customer = await client.customers.create(
{ email: 'john@example.com' },
{ idempotencyKey: 'unique-request-id' }
);
// Custom headers
const customer = await client.customers.retrieve('cus_xxx', {
headers: { 'X-Custom-Header': 'value' },
});Debugging
Enable debug logging:
const client = new RevKeen({
apiKey: 'rk_live_xxx',
debug: true,
});Framework Examples
Next.js App Router
// app/api/checkout/route.ts
import { NextResponse } from 'next/server';
import RevKeen from '@revkeen/sdk';
const client = new RevKeen();
export async function POST(request: Request) {
const { productId, customerId } = await request.json();
const session = await client.checkoutSessions.create({
mode: 'subscription',
productId,
customerId,
successUrl: `${process.env.NEXT_PUBLIC_URL}/dashboard`,
cancelUrl: `${process.env.NEXT_PUBLIC_URL}/pricing`,
});
return NextResponse.json({ url: session.data.url });
}Express.js
import express from 'express';
import RevKeen from '@revkeen/sdk';
const app = express();
const client = new RevKeen();
app.post('/api/customers', async (req, res) => {
try {
const customer = await client.customers.create(req.body);
res.json(customer.data);
} catch (error) {
res.status(error.status || 500).json({ error: error.message });
}
});