npm.io
0.2.0 • Published 2h ago

@chiahq/sdk

Licence
MIT
Version
0.2.0
Deps
4
Size
422 kB
Vulns
0
Weekly
0
Stars
3

Chia SDK

A TypeScript SDK for integrating African mobile money payments. Unified, type-safe API for PayChangu, PawaPay, and OneKhusa.

npm version License: MIT

Standalone by design

The SDK talks directly to the provider APIs with your own credentials - a PayChangu secret key, a PawaPay API token, or OneKhusa API credentials. There is no Chia account, no proxy, and no platform dependency: your requests go straight to the providers, and nothing here phones home.

Reach for the SDK when you need:

  • Custom payment flows under your full control
  • Direct access to provider APIs (deposits, payouts, refunds, wallets)
  • Integration into an existing backend where you manage your own provider accounts
  • Batch disbursements or approval workflows (OneKhusa)
  • The unified payments surface: one call that routes across whichever providers you configure

The hosted platform (optional)

If what you actually want is recurring billing - plans, hosted checkout, automatic renewals and retries, failed-payment recovery, webhooks, and weekly payouts - the Chia platform runs all of that on top of this SDK. Sign up, create a plan, share a link; no provider accounts needed. The SDK remains the right tool for custom flows; the platform is the shortcut for subscriptions. Neither requires the other.

Features

  • Multi-Provider Support - PayChangu, PawaPay, and OneKhusa in one SDK
  • Full TypeScript Support - Comprehensive type definitions for all APIs
  • Sandbox & Production - Easy environment switching
  • Comprehensive Error Handling - Detailed error messages and types

Supported Providers

Provider Region Capabilities
PayChangu Malawi Payments, Mobile Money, Bank Transfers
PawaPay Sub-Saharan Africa Deposits, Payouts, Refunds, Wallets
OneKhusa Malawi & Southern Africa Collections, Disbursements, Batch Payouts

Installation

npm install @chiahq/sdk
# or
pnpm add @chiahq/sdk
# or
yarn add @chiahq/sdk

Quick Start

import { ChiaSDK } from "@chiahq/sdk";

const sdk = ChiaSDK.initialize({
  pawapay: {
    jwt: "your-pawapay-jwt"
  },
  paychangu: {
    secretKey: "your-paychangu-secret"
  },
  onekhusa: {
    apiKey: "your-onekhusa-api-key",
    apiSecret: "your-onekhusa-api-secret",
    organisationId: "your-organisation-id"
  }
});

ChiaSDK has a private constructor - use ChiaSDK.initialize(config) to create (or fetch) the singleton, or ChiaSDK.create(config) for an independent instance. Both accept the same SDKConfig shape.

You only need to configure the providers you plan to use.

Unified payments API

Instead of calling each provider directly, sdk.payments and sdk.payouts route a request to whichever configured provider can serve it:

const payment = await sdk.payments.initiate({
  reference: "order-123",
  amount: "50.00",
  currency: "ZMW",
  msisdn: "260971234567",
  country: "ZMB",
  description: "Payment for services",
});

payment.provider   // "pawapay"      - paychangu was skipped, it cannot serve ZMW in ZMB
payment.status     // "pending"
payment.nextAction // { type: "pin_prompt" }
payment.operator   // "AIRTEL_ZMB"   - inferred from the msisdn

Routing is by country and currency, preferring PayChangu, then PawaPay, then OneKhusa. Providers that cannot serve the route are skipped, not contacted. Pin a single provider with provider: "pawapay", or give an ordered shortlist with providers: ["pawapay", "paychangu"].

payment.attempts records every provider tried, skipped or refused, with the reason. payment.raw always carries the untouched response from whichever provider handled the request.

Coverage today
Provider Countries
PawaPay 19 countries across Sub-Saharan Africa
PayChangu Malawi only
OneKhusa Malawi only

Outside Malawi, PawaPay is currently the only candidate.

Failover is deliberately conservative

This is not retry-on-failure. When a shortlist is given, the SDK advances to the next provider only on outcomes that provably moved no money: the provider isn't configured, it can't serve the route, validation was rejected, or it explicitly refused the request. On a timeout or a 5xx after the request was sent, it aborts rather than trying another provider - a client-side timeout is indistinguishable from a successful charge, and retrying elsewhere would risk charging the customer twice.

Fetching a payment later

sdk.payments.get(id, { provider }) requires an explicit provider: an opaque id carries no routing information on its own. Pass back the provider field from the ChiaPayment that initiate() returned.

Provider-specific features

Anything the providers do not share stays on its own namespace: sdk.pawapay.refunds, sdk.pawapay.remittances, sdk.paychangu hosted checkout, sdk.onekhusa.disbursements, and so on.

OneKhusa payouts need approval

sdk.payouts.send() on OneKhusa returns status: "pending_approval" and requiresApproval: true, because its API opens a maker-checker flow rather than sending. Advance it with sdk.onekhusa.disbursements.approveSingle(id). Check sdk.capabilities("onekhusa").payouts.requiresApproval before calling.

PawaPay

Mobile money payments across Sub-Saharan Africa.

Request a Deposit via the Hosted Payment Page
const deposit = await sdk.pawapay.payments.initiatePayment({
  depositId: "order-123",
  returnUrl: "https://your-app.com/callback",
  msisdn: "260971234567",
  amount: "50.00",
  country: "ZMB",
  reason: "Service payment",
  language: "EN"
});

// Redirect the customer to deposit.redirectUrl to complete the payment
Send a Payout
const payout = await sdk.pawapay.payouts.sendPayout({
  payoutId: "payout-123",
  amount: "50.00",
  currency: "ZMW",
  recipient: {
    type: "MMO",
    accountDetails: {
      phoneNumber: "260701234567",
      provider: "AIRTEL_ZMB"
    }
  }
});
Check Wallet Balance
const balances = await sdk.pawapay.wallets.getAllBalances();

PayChangu

Payment services in Malawi.

Initiate Payment
const txRef = "order-456";

const payment = await sdk.paychangu.initiatePayment({
  amount: "1000",
  currency: "MWK",
  tx_ref: txRef,
  email: "customer@example.com",
  first_name: "John",
  last_name: "Doe",
  callback_url: "https://your-app.com/webhook",
  return_url: "https://your-app.com/success"
});

// Redirect customer to checkout
console.log("Checkout URL:", payment.data.checkout_url);
Verify Transaction
const verification = await sdk.paychangu.verifyTransaction(txRef);
Mobile Money Payout

initializeMobileMoneyPayout takes positional arguments, not an options object:

const payout = await sdk.paychangu.initializeMobileMoneyPayout(
  "265991234567", // recipient mobile number
  "operator-ref-id", // from sdk.paychangu.getMobileMoneyOperators()
  2000, // amount
  "payout-123" // charge_id
);

OneKhusa

Enterprise payment platform with collections and disbursements.

Request-to-Pay Collection

initiateRequestToPay returns CollectionResponse | ServiceError - narrow with isServiceError before reading the success fields:

import { isServiceError } from "@chiahq/sdk";

const collection = await sdk.onekhusa.collections.initiateRequestToPay({
  amount: 5000,
  currency: "MWK",
  phone: "265991234567",
  paymentMethod: "MOBILE_MONEY",
  reference: "order-789",
  description: "Payment for goods"
});

if (isServiceError(collection)) {
  throw new Error(collection.errorMessage);
}

console.log("TAN:", collection.tan);
Single Disbursement
const disbursement = await sdk.onekhusa.disbursements.addSingle({
  amount: 10000,
  currency: "MWK",
  paymentMethod: "MOBILE_MONEY",
  recipient: {
    name: "John Doe",
    phone: "265991234567"
  },
  reference: "payout-001",
  description: "Salary payment"
});

if (isServiceError(disbursement)) {
  throw new Error(disbursement.errorMessage);
}

// Approve the disbursement
await sdk.onekhusa.disbursements.approveSingle(disbursement.id);
Batch Disbursement

Batch items each carry their own amount, currency, paymentMethod and recipient - there is no top-level currency/paymentMethod/recipients on the batch request:

const batch = await sdk.onekhusa.disbursements.addBatch({
  name: "January Salaries",
  items: [
    {
      amount: 50000,
      currency: "MWK",
      paymentMethod: "MOBILE_MONEY",
      recipient: { name: "John Doe", phone: "265991234567" }
    },
    {
      amount: 45000,
      currency: "MWK",
      paymentMethod: "MOBILE_MONEY",
      recipient: { name: "Jane Smith", phone: "265999876543" }
    }
  ]
});

if (isServiceError(batch)) {
  throw new Error(batch.errorMessage);
}

// Approve and transfer funds
await sdk.onekhusa.disbursements.approveBatch(batch.id);
await sdk.onekhusa.disbursements.transferBatchFunds(batch.id);

Configuration

Use environment variables for secure credential management. There is no top-level environment option - each provider takes its own environment field ("DEVELOPMENT" or "PRODUCTION", defaulting to "DEVELOPMENT"):

import { ChiaSDK, ENVIRONMENTS } from "@chiahq/sdk";

const sdk = ChiaSDK.initialize({
  pawapay: {
    jwt: process.env.PAWAPAY_TOKEN,
    environment: ENVIRONMENTS.PRODUCTION // or ENVIRONMENTS.DEVELOPMENT
  },
  paychangu: {
    secretKey: process.env.PAYCHANGU_SECRET,
    environment: ENVIRONMENTS.PRODUCTION
  },
  onekhusa: {
    apiKey: process.env.ONEKHUSA_API_KEY,
    apiSecret: process.env.ONEKHUSA_API_SECRET,
    organisationId: process.env.ONEKHUSA_ORGANISATION_ID,
    environment: ENVIRONMENTS.PRODUCTION
  }
});
Custom API URLs

Override default provider endpoints for testing or regional deployments:

const sdk = ChiaSDK.initialize({
  pawapay: {
    jwt: "your-jwt",
    environment: "DEVELOPMENT",
    sandboxUrl: "https://custom-sandbox.pawapay.io/v1",
    productionUrl: "https://custom-prod.pawapay.io/v1"
  },
  paychangu: {
    secretKey: "your-secret",
    sandboxUrl: "https://custom.paychangu.com"
  },
  onekhusa: {
    apiKey: "your-key",
    apiSecret: "your-secret",
    organisationId: "your-org-id",
    sandboxUrl: "https://custom-sandbox.onekhusa.com/v1"
  }
});

Both sandboxUrl and productionUrl are optional. The URL used depends on the environment setting.

Type Definitions

All types are exported from the main package:

import type {
  PayChanguTypes,
  PawaPayTypes,
  OneKhusaTypes
} from "@chiahq/sdk";

Requirements

  • Node.js 18.0.0 or higher
  • TypeScript 5.0+ (optional, but recommended)

Getting API Credentials

These credentials are needed when using the SDK directly. If you're using the Chia platform, you don't need provider API keys - Chia handles payment collection for you.

PawaPay
  1. Visit PawaPay and create a developer account
  2. Complete onboarding and verification
  3. Get your API token from the dashboard
PayChangu
  1. Sign up at PayChangu
  2. Complete business verification
  3. Get your secret key from the merchant dashboard
OneKhusa
  1. Contact OneKhusa to create a business account
  2. Complete KYC verification
  3. Get your API Key, API Secret, and Organisation ID

Documentation

For full documentation, visit docs.usechia.com or see the docs.

MCP Server

For AI-powered payment operations with Claude, check out @chiahq/mcp.

License

MIT

Keywords