lomi.
SDKs

TypeScript SDK

Official TypeScript/JavaScript SDK for lomi. payments API.

Official Node.js/TypeScript SDK for lomi.. payments API. Works with Node.js, Deno, Bun, and browser environments.

Installation

bash npm install @lomi./sdk
bash pnpm add @lomi./sdk
bash yarn add @lomi./sdk
bash bun add @lomi./sdk

Before you start

  1. Create a lomi. account and complete onboarding.
  2. Copy a test secret key from Settings → Access tokens (lomi_sk_test_…). See Access tokens.
  3. Add it to a .env file (see Environment variables).
  4. Install the SDK (below), set environment: 'test', then run the first API call example.

Environments and base URLs

Use test while building. The SDK maps environment to the API host automatically:

environmentAPI base URLSecret key prefix
'test'https://sandbox.api.lomi.africalomi_sk_test_…
'live'https://api.lomi.africalomi_sk_live_…

You can override the host with baseUrl if needed, but matching key prefix and environment is enough for most integrations.

Quick start

import { LomiSDK } from '@lomi./sdk';

const lomi = new LomiSDK({
  apiKey: process.env.LOMI_SECRET_KEY!,
  environment: 'test', // sandbox: use 'live' only in production
});

First API call (sandbox)

Copy-paste runnable example: install the SDK, set LOMI_SECRET_KEY in .env, then fetch your sandbox balance.

import { LomiSDK, LomiAuthError, LomiNotFoundError } from '@lomi./sdk';

const lomi = new LomiSDK({
  apiKey: process.env.LOMI_SECRET_KEY!,
  environment: 'test',
});

async function main() {
  try {
    const balance = await lomi.accounts.getBalance();
    console.log('Balance:', balance);
  } catch (error) {
    if (error instanceof LomiAuthError) {
      console.error(`Auth failed [${error.statusCode}]: ${error.message}`);
      if (error.requestId) console.error('request_id:', error.requestId);
      process.exit(1);
    }
    throw error;
  }
}

main();
LOMI_SECRET_KEY=lomi_sk_test_xxxxxxxxxxxxxxxxxxxxxx
npm install @lomi./sdk
# load .env with your tooling (dotenv, Next.js, etc.)
npx tsx first-call.ts

Expected: balance payload from GET https://sandbox.api.lomi.africa/accounts/balance. For raw HTTP without the SDK, see API integration.


Payment Examples

Create a Checkout Session

const session = await lomi.checkoutSessions.create({
  amount: 10000,
  currency_code: 'XOF',
  title: 'Premium Subscription',
  description: 'Monthly access to premium features',
  customer_email: 'customer@example.com',
  success_url: 'https://yoursite.com/success',
  cancel_url: 'https://yoursite.com/cancel',
  metadata: { order_id: 'ORD-123' },
});

console.log('Redirect to:', session.checkout_url);
const link = await lomi.paymentLinks.create({
  link_type: 'product',
  title: 'Pro Plan',
  currency_code: 'XOF',
  product_id: 'prod_abc123...',
  allow_coupon_code: true,
});

console.log('Share this link:', link.url);

List Transactions with Filters

const transactions = await lomi.transactions.list({
  status: 'completed',
  provider: 'WAVE',
  startDate: '2024-01-01T00:00:00Z',
  pageSize: 50,
});

for (const tx of transactions) {
  console.log(`${tx.id}: ${tx.gross_amount} ${tx.currency_code}`);
}

Customer Management

Create a Customer

const customer = await lomi.customers.create({
  name: 'Amadou Ba',
  email: 'amadou@example.com',
  phone_number: '+221771234567',
  country: 'Senegal',
  city: 'Dakar',
  metadata: { source: 'website' },
});

console.log('Customer ID:', customer.id);

Get Customer Transactions

const transactions = await lomi.customers.getTransactions('cus_abc123...');

Products & Subscriptions

Create a Product

const product = await lomi.products.create({
  name: 'Premium Plan',
  description: 'Full access to all features',
  product_type: 'recurring',
  prices: [
    {
      amount: 15000,
      currency_code: 'XOF',
      billing_interval: 'month',
      is_default: true,
    },
  ],
  trial_enabled: true,
  trial_period_days: 7,
});

Add a New Price

const price = await lomi.products.addPrice('prod_abc123...', {
  amount: 150000,
  currency_code: 'XOF',
  billing_interval: 'year',
});

Cancel a Subscription

const cancelled = await lomi.subscriptions.cancel('sub_abc123...', {
  cancellation_reason: 'Customer request',
});

Payouts & rails-specific calls

Payout (POST /payouts)

await lomi.payouts.create({
  destination: 'beneficiary',
  rail: 'wave',
  amount: 10000,
  currency_code: 'XOF',
  recipient: { name: 'Aicha Diallo', phone: '+221771234567' },
});

Direct mobile-money charge (POST /charge/wave)

await lomi.charges.createWaveCharge({
  amount: 5000,
  currency: 'XOF',
  customer: {
    name: 'Moussa Ndiaye',
    phoneNumber: '+221771234567',
    email: 'moussa@example.com',
  },
});

Embedded card charge (POST /charge/card)

const charge = await lomi.charges.createCardCharge({
  amount: 2500,
  currency_code: 'XOF',
  customer_email: 'buyer@example.com',
  customer_name: 'Buyer Name',
});

// Use charge.data.client_secret with Payment Elements on your frontend
console.log(charge.data?.client_secret);

Switch charge, server-side card authorization (POST /charge/switch)

For PCI-compliant fintech integrations that authorize cards server-side (not hosted checkout):

const result = await lomi.charges.createSwitchCharge(
  {
    amount: 10000,
    currency_code: 'XOF',
    pan: '4221941234569109',
    expiry: '06/30',
    cvv: '123',
    card_holder_name: 'Amadou Ba',
  },
  { idempotencyKey: 'switch-attempt-001' },
);

if (result.status === 'redirect_3ds') {
  console.log('Complete 3DS at:', result.three_ds_url);
}

Switch requires a PCI-DSS-compliant integration. For most merchants, use Payment Elements or checkout sessions instead.


Account & Organization

Get Account Balance

const balances = await lomi.accounts.getBalance();
const xofBalance = await lomi.accounts.getBalance({ currency: 'XOF' });

console.log('Available:', xofBalance.available);

Get Organization Metrics

const metrics = await lomi.organizations.getMetrics();

console.log('MRR:', metrics.mrr);
console.log('Total Customers:', metrics.total_customers);

Error Handling

The SDK throws typed LomiError subclasses with the API message, HTTP status, error code, and request_id:

import {
  LomiSDK,
  LomiAuthError,
  LomiNotFoundError,
  LomiValidationError,
  LomiRateLimitError,
} from '@lomi./sdk';

try {
  const customer = await lomi.customers.get('invalid_id');
} catch (error) {
  if (error instanceof LomiNotFoundError) {
    console.error('Customer not found:', error.message);
  } else if (error instanceof LomiValidationError) {
    console.error('Invalid request:', error.details);
  } else if (error instanceof LomiRateLimitError) {
    console.error('Rate limited, retry later');
  } else if (error instanceof LomiAuthError) {
    console.error(`Auth error [${error.statusCode}]: ${error.message}`);
  }
  console.error('request_id:', error.requestId);
}

Configuration Options

Each LomiSDK instance is isolated, safe for multi-tenant workers and tests:

const lomi = new LomiSDK({
  apiKey: process.env.LOMI_SECRET_KEY!,
  environment: 'test',           // 'live' in production
  account: 'acct_connected_…',   // default Lomi-Account header (operator mode)
  timeout: 30_000,               // request timeout in ms (default: 30000)
  retries: 2,                    // retry idempotent GETs + 429s with backoff
  headers: { 'X-Custom': '1' },
});

Per-request options

Pass on any create-style call:

await lomi.checkoutSessions.create(body, {
  idempotencyKey: 'checkout-001',  // Idempotency-Key header
  account: 'acct_other_…',         // override Lomi-Account for this call
  signal: abortController.signal,  // AbortSignal
});

Webhooks

Verify incoming webhook signatures without hand-rolling HMAC:

const valid = lomi.webhooks.verifySignature(
  rawBody,                          // string or Buffer (use raw body, not parsed JSON)
  req.headers['x-lomi-signature'],
  process.env.LOMI_WEBHOOK_SECRET!,
);

if (!valid) return res.status(401).send('Invalid signature');

Auto-pagination

List endpoints expose an async iterator via listAll:

for await (const tx of lomi.transactions.listAll({ status: 'completed' })) {
  console.log(tx.id, tx.gross_amount);
}

Payment Elements

import { loadLomi } from '@lomi./sdk';

// Your lomi_pk_… is validated; Elements run on lomi.'s PCI platform infrastructure.
const elements = await loadLomi('lomi_pk_test_…');

Payment Elements initialize on lomi.'s platform account. Your publishable key identifies your merchant context; you never handle raw card numbers.


Available Services

ServiceMethods
accountsgetBalance, getBalanceBreakdown, checkBalance
chargescreateWaveCharge, createMtnCharge, createCardCharge, createSwitchCharge, getCardCharge, cancelCardCharge
checkoutSessionslist, listAll, get, create
customerslist, listAll, get, create, update, delete, getTransactions, createPortalLaunchSession, getPortalAudit
discountCouponslist, listAll, get, create, getPerformance
disputeslist, listAll, get
logslist, listAll, get
merchantsget, getArr, getBalance, getMrr
meterslist, listAll, get, create, update, getCustomerBalance
organizationget
organizationslist, listAll, get, getMetrics
paymentLinkslist, listAll, get, create
paymentRequestslist, listAll, get, create
payoutscreate, list, listAll, get
productslist, listAll, get, create, addPrice, setDefaultPrice
providerslist, listAll
refundscreate, list, listAll, get
riskAssessmentslist, listAll, get
settlementsfindAll, findAllAll, findTransactions
subscriptionslist, listAll, get, findByCustomer, cancel, uncancel, changePlan, update
transactionslist, listAll, get
usageBillingcheckEntitlement, listPeriods, getRevenue, getSubscriptionUsage, grantCredits, createEntitlement
usageEventslist, listAll, get, create
usageSubscriptionscreate
webhookDeliveryLogslist, listAll, get
webhookslist, listAll, get, create, update, delete, test, retryDelivery, verifySignature

TypeScript types

Request and response bodies are fully typed from the OpenAPI schema:

import type {
  CreateSwitchCharge,
  SwitchChargeResponse,
  components,
  paths,
} from '@lomi./sdk';

// DTO aliases (generated from components.schemas)
type SwitchBody = CreateSwitchCharge;

// Or reference paths directly
type CheckoutCreate =
  paths['/checkout-sessions']['post']['requestBody']['content']['application/json'];

Database row types also ship for advanced integrations:

import type { Database } from '@lomi./sdk';

type Customer = Database['public']['Tables']['customers']['Row'];

Resources

On this page