Skip to content

JavaScript/TypeScript SDK

The official Cashfin SDK for JavaScript and TypeScript applications.

Installation

bash
npm install @cashfin/node
bash
yarn add @cashfin/node
bash
pnpm add @cashfin/node

Requirements

  • Node.js 16.x or later
  • TypeScript 4.7+ (optional, for TypeScript projects)

Quick Start

typescript
import Cashfin from "@cashfin/node";

const cashfin = new Cashfin({
  apiKey: process.env.CASHFIN_API_KEY!,
  // Optional: Use sandbox for testing
  environment: process.env.NODE_ENV === "production" ? "live" : "sandbox",
});

// Your code here

Configuration Options

typescript
const cashfin = new Cashfin({
  // Required
  apiKey: "cs_your_client_secret",

  // Optional
  environment: "live", // 'live' or 'sandbox'
  timeout: 30000, // Request timeout in ms
  maxRetries: 3, // Number of retries on failure
  debug: false, // Enable debug logging
});

Products

List Products

typescript
// List all products
const products = await cashfin.products.list();

// With pagination
const products = await cashfin.products.list({
  page: 1,
  limit: 20,
  status: "published",
});

// Iterate over all products
for await (const product of cashfin.products.listAll()) {
  console.log(product.title);
}

Get Product

typescript
const product = await cashfin.products.get("507f1f77bcf86cd799439011");

console.log(product.title);
console.log(product.price);

Create Product

typescript
const product = await cashfin.products.create({
  title: "Premium Widget",
  description: "A high-quality widget",
  price: 1999.99,
  stock: 100,
  type: "product",
  status: "published",
  featured: true,
  variants: [
    {
      attributetitle: "Color",
      valuetitle: "Blue",
      valueprice: 1999.99,
      valuestock: 50,
    },
  ],
});

console.log(`Created: ${product.id}`);

Update Product

typescript
const product = await cashfin.products.update("507f1f77bcf86cd799439011", {
  price: 2499.99,
  stock: 75,
});

Categories

List Categories

typescript
const categories = await cashfin.categories.list();

Create Category

typescript
const category = await cashfin.categories.create({
  title: "Electronics",
  description: "Electronic devices and accessories",
  status: "active",
});

Update Category

typescript
const category = await cashfin.categories.update("507f191e810c19729de860ea", {
  description: "Updated description",
});

Orders

Create Checkout

typescript
const order = await cashfin.orders.checkout({
  customeremail: "[email protected]",
  items: [
    {
      itemid: "507f1f77bcf86cd799439011",
      quantity: 2,
      rate: 1999.99,
    },
  ],
  shippingaddress: {
    name: "John Doe",
    address: "123 Main St",
    city: "Nairobi",
    country: "Kenya",
    phone: "+254712345678",
  },
});

console.log(`Order: ${order.orderno}`);
console.log(`Payment: ${order.paymentlink.shorturl}`);

Payments

M-Pesa Payment

typescript
const payment = await cashfin.payments.mpesa({
  amount: 1500,
  phone: "254712345678",
  referenceid: "ORDER-001",
  description: "Payment for Order #001",
});

console.log(`Checkout ID: ${payment.checkoutrequestid}`);

Invoices

Create Invoice

typescript
const invoice = await cashfin.invoices.create({
  customerid: "507f1f77bcf86cd799439011",
  items: [
    {
      itemid: "507f191e810c19729de860ea",
      name: "Consulting Services",
      quantity: 10,
      rate: 5000.0,
    },
  ],
  title: "Monthly Consulting Invoice",
  duedate: "2024-02-15",
  discount: 10,
  discounttype: "percentage",
});

console.log(`Invoice: ${invoice.invoiceno}`);
console.log(`Payment Link: ${invoice.paymentlink.shorturl}`);

List Invoices

typescript
// List all invoices
const invoices = await cashfin.invoices.list();

// With filters
const unpaidInvoices = await cashfin.invoices.list({
  status: "unpaid",
  page: 1,
  limit: 20,
});

// Iterate through invoices
for (const invoice of unpaidInvoices.data) {
  console.log(`${invoice.invoiceno}: KES ${invoice.balance}`);
}

Get Invoice Details

typescript
const invoice = await cashfin.invoices.get("507f1f77bcf86cd799439020");

console.log(`Invoice: ${invoice.invoiceno}`);
console.log(`Status: ${invoice.status}`);
console.log(`Balance: ${invoice.balance}`);
console.log(`Customer: ${invoice.customer.name}`);

Update Invoice

typescript
const invoice = await cashfin.invoices.update("507f1f77bcf86cd799439020", {
  status: "paid",
  description: "Paid via M-Pesa on 2024-01-20",
});

Customers

Create Customer

typescript
const customer = await cashfin.customers.create({
  name: "John Doe",
  email: "[email protected]",
  phone: "+254712345678",
  country: "Kenya",
  currency: "KES",
  type: "individual",
});

console.log(`Customer ID: ${customer.id}`);

Subscriptions

Create Subscription

typescript
const subscription = await cashfin.subscriptions.create({
  customerid: "507f1f77bcf86cd799439011",
  items: [
    {
      itemid: "507f191e810c19729de860ea",
      quantity: 1,
      rate: 2999.0,
    },
  ],
  billingcycle: "monthly",
  autorenew: true,
  trial: {
    startdate: new Date().toISOString(),
    enddate: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString(),
  },
});

console.log(`Subscription: ${subscription.subscriptionno}`);

Get Subscription

typescript
const subscription = await cashfin.subscriptions.get(
  "507f1f77bcf86cd799439020"
);

console.log(`Status: ${subscription.status}`);
console.log(`Next Billing: ${subscription.nextbillingdate}`);

Error Handling

typescript
import Cashfin, {
  CashfinError,
  ValidationError,
  AuthenticationError,
  NotFoundError,
  RateLimitError,
} from "@cashfin/node";

try {
  const product = await cashfin.products.create({
    title: "Widget",
    // Missing required fields
  });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log("Validation errors:", error.errors);
    // { price: 'Price is required' }
  } else if (error instanceof AuthenticationError) {
    console.log("Check your API key");
  } else if (error instanceof NotFoundError) {
    console.log("Resource not found");
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof CashfinError) {
    console.log("API Error:", error.message);
    console.log("Status:", error.statusCode);
  }
}

Webhooks

Verify Signature

typescript
import { verifyWebhookSignature } from "@cashfin/node";

app.post(
  "/webhooks/cashfin",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.headers["x-cashfin-signature"] as string;
    const payload = req.body.toString();

    const isValid = verifyWebhookSignature(
      payload,
      signature,
      process.env.CASHFIN_WEBHOOK_SECRET!
    );

    if (!isValid) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const event = JSON.parse(payload);

    switch (event.type) {
      case "payment.completed":
        handlePaymentCompleted(event.data);
        break;
      case "order.created":
        handleOrderCreated(event.data);
        break;
      case "subscription.renewed":
        handleSubscriptionRenewed(event.data);
        break;
    }

    res.json({ received: true });
  }
);

TypeScript Support

The SDK includes full TypeScript definitions:

typescript
import Cashfin, {
  Product,
  Category,
  Order,
  Customer,
  Subscription,
  PaymentResult
} from '@cashfin/node';

// All methods are fully typed
const product: Product = await cashfin.products.get('...');
const order: Order = await cashfin.orders.checkout({...});

Pagination

Manual Pagination

typescript
let page = 1;
let hasMore = true;

while (hasMore) {
  const response = await cashfin.products.list({ page, limit: 100 });

  for (const product of response.data) {
    console.log(product.title);
  }

  hasMore = page < response.meta.pages;
  page++;
}

Auto-Pagination

typescript
// Automatically handles pagination
for await (const product of cashfin.products.listAll()) {
  console.log(product.title);
}

Retry Configuration

typescript
const cashfin = new Cashfin({
  apiKey: process.env.CASHFIN_API_KEY!,
  maxRetries: 5,
  retryConfig: {
    initialDelay: 1000, // 1 second
    maxDelay: 30000, // 30 seconds
    factor: 2, // Exponential backoff factor
  },
});

Debugging

typescript
const cashfin = new Cashfin({
  apiKey: process.env.CASHFIN_API_KEY!,
  debug: true, // Logs all requests and responses
});

// Or set via environment variable
// CASHFIN_DEBUG=true

Examples

E-commerce Integration

typescript
import Cashfin from "@cashfin/node";

const cashfin = new Cashfin({ apiKey: process.env.CASHFIN_API_KEY! });

async function processCheckout(cart: Cart, customerEmail: string) {
  // Create order
  const order = await cashfin.orders.checkout({
    customeremail: customerEmail,
    items: cart.items.map((item) => ({
      itemid: item.productId,
      quantity: item.quantity,
      rate: item.price,
    })),
  });

  // Return payment URL
  return order.paymentlink.shorturl;
}

SaaS Subscription

typescript
async function createSubscription(userId: string, planId: string) {
  // Get or create customer
  const user = await db.users.findById(userId);

  let customerId = user.cashfinCustomerId;

  if (!customerId) {
    const customer = await cashfin.customers.create({
      name: user.name,
      email: user.email,
      phone: user.phone,
      country: "Kenya",
      currency: "KES",
    });

    customerId = customer.id;
    await db.users.update(userId, { cashfinCustomerId: customerId });
  }

  // Create subscription
  const subscription = await cashfin.subscriptions.create({
    customerid: customerId,
    items: [{ itemid: planId, quantity: 1, rate: 999 }],
    billingcycle: "monthly",
    autorenew: true,
  });

  return subscription;
}

Cashfin Business API Documentation