SDK

The Kyshi MOR SDK is the official TypeScript and Node.js package for integrating with Kyshi MOR external APIs from your backend.

Use the SDK when you want typed resource methods, consistent error handling, request timeouts, retries, idempotency support, and webhook signature helpers without writing raw HTTP calls for every endpoint.

This page is separate from the API guides and API Reference. Use it as the SDK starting point, then use the API Reference only when you need exact endpoint schemas or raw HTTP details.

Install

npm install @kyshi/mor-sdk

For the beta release:

npm install @kyshi/mor-sdk@beta

The SDK requires Node.js 18 or newer.

Quick Start

import { Kyshi } from '@kyshi/mor-sdk';

const kyshi = new Kyshi({
  secretKey: process.env.KYSHI_SECRET_KEY!,
  environment: 'test',
});

const checkout = await kyshi.transactions.initialize({
  email: '[email protected]',
  localCurrency: 'NGN',
  amount: 100000,
  reference: 'ORDER-001',
  redirectUrl: 'https://merchant.example/return',
});

console.log(checkout.authorizationUrl);

Use environment: 'live' with a live secret key when you are ready to process live traffic.

Credentials

Use environment variables for secrets:

KYSHI_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxx
KYSHI_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxx
SecretUsed For
KYSHI_SECRET_KEYOutbound SDK API calls from your backend using x-api-key.
KYSHI_WEBHOOK_SECRETInbound webhook signature verification.

Keep secret keys on your server. Do not use your Kyshi secret key directly in browser JavaScript, mobile apps, or other public clients.

SDK Resources

Product AreaSDK Resource
Transactionskyshi.transactions
Payment Linkskyshi.paymentLinks
General Payment Linkskyshi.generalPaymentLinks
Virtual Accountskyshi.virtualAccounts
Transferskyshi.transfers
Virtual Account Transferskyshi.virtualAccountTransfers
Planskyshi.plans
Subscriptionskyshi.subscriptions
Rateskyshi.rates
Custom Rateskyshi.customRates
Webhookskyshi.webhooks

Configuration

const kyshi = new Kyshi({
  secretKey: process.env.KYSHI_SECRET_KEY!,
  environment: 'test',
  timeoutMs: 30_000,
  maxRetries: 2,
  retryDelayMs: 250,
});
OptionTypeDescription
secretKeystringRequired Kyshi secret key.
environmenttest or liveSDK environment label. Defaults to test.
baseUrlstringOptional custom API base URL.
timeoutMsnumberRequest timeout in milliseconds. Defaults to 30000.
maxRetriesnumberDefault retry count for retryable requests. Defaults to 2.
retryDelayMsnumberInitial retry delay in milliseconds. Defaults to 250.
fetchfunctionOptional custom Fetch implementation.

Transactions

Initialize checkout from your backend:

const checkout = await kyshi.transactions.initialize({
  email: '[email protected]',
  localCurrency: 'NGN',
  amount: 100000,
  reference: 'ORDER-001',
  redirectUrl: 'https://merchant.example/return',
});

Verify payments before giving value:

const transaction = await kyshi.transactions.verify('ORDER-001');

Common methods:

  • kyshi.transactions.initialize(params)
  • kyshi.transactions.charge(params)
  • kyshi.transactions.verify(reference)
  • kyshi.transactions.retrieve(id)
  • kyshi.transactions.list(query)

Payment Links

Create a customer-specific payment link:

const link = await kyshi.paymentLinks.create({
  customer: { email: '[email protected]' },
  expiresAt: '2026-12-31T23:59:59Z',
  localCurrency: 'NGN',
  description: 'Invoice INV-001',
  metadata: [{ name: 'Invoice', amount: 100000, quantity: 1 }],
});

Create a reusable general payment link:

const general = await kyshi.generalPaymentLinks.create({
  metadata: [{ name: 'Consulting', amount: 250000, quantity: 1 }],
});

Common methods:

  • kyshi.paymentLinks.create(params)
  • kyshi.paymentLinks.verify(code)
  • kyshi.paymentLinks.verifyPublic(code)
  • kyshi.paymentLinks.verifyReceipt(reference)
  • kyshi.generalPaymentLinks.create(params)
  • kyshi.generalPaymentLinks.verify(code)
  • kyshi.generalPaymentLinks.checkout(code, params)

Transfers And Virtual Accounts

Create a beneficiary and initiate a transfer:

const beneficiary = await kyshi.transfers.createBeneficiary({
  accountName: 'Jane Doe',
  accountNumber: '0123456789',
  bankName: 'Test Bank',
  bankCode: '000013',
  currency: 'NGN',
});

const payout = await kyshi.transfers.create({
  beneficiaryId: beneficiary.id!,
  currency: 'NGN',
  amount: 100000,
  narration: 'Vendor payout',
  reference: 'PAYOUT-001',
});

Create a virtual account:

const account = await kyshi.virtualAccounts.create({
  customer: { email: '[email protected]' },
  currency: 'NGN',
  accountType: 'INDIVIDUAL',
  accountCategory: 'VIRTUAL_ACCOUNT',
  bank: 'VFD',
});

const balance = await kyshi.virtualAccounts.getBalance('NGN');

Virtual account transfers use the same transfer methods through kyshi.virtualAccountTransfers, mapped to the virtual-account transfer API routes.

Plans And Subscriptions

Kyshi subscriptions support both card auto-collection and invoice-based collection for non-card methods such as bank_transfer, bank, and mobile_money.

Create a plan:

const plan = await kyshi.plans.create({
  name: 'Gold',
  description: 'Gold monthly plan',
  interval: 'monthly',
  amount: 100000,
  localCurrency: 'NGN',
  hostedPage: true,
});

Create a subscription:

const subscription = await kyshi.subscriptions.create({
  planCode: plan.code!,
  customer: '[email protected]',
  paymentMethod: 'card',
  redirectUrl: 'https://merchant.example/return',
});

Create an invoice-based subscription for bank transfer, bank, or mobile money collection:

const manualSubscription = await kyshi.subscriptions.create({
  planCode: plan.code!,
  customer: '[email protected]',
  paymentMethod: 'bank_transfer',
  redirectUrl: 'https://merchant.example/return',
});

card subscriptions can charge a saved card or authorization automatically. bank_transfer, bank, and mobile_money subscriptions generate invoices and payment links or instructions for the customer to complete payment. Use plans with sendInvoices: true when customers should receive invoice and payment reminders.

For non-card subscription methods, "manual" means the customer completes payment through the generated payment link or channel. It does not mean the merchant can mark an offline payment as paid unless a separate reconciliation or mark-paid endpoint is provided for that workflow.

Common methods:

  • kyshi.plans.create(params)
  • kyshi.plans.list(query)
  • kyshi.plans.retrieve(idOrCode)
  • kyshi.subscriptions.create(params)
  • kyshi.subscriptions.list(query)
  • kyshi.subscriptions.retrieve(idOrCode)
  • kyshi.subscriptions.manage(idOrCode, params)
  • kyshi.subscriptions.updateCard(idOrCode, params)
  • kyshi.subscriptions.retryPayment(idOrCode, params)
  • kyshi.subscriptions.charge(params)
  • kyshi.subscriptions.listInvoices(idOrCode, query)
  • kyshi.subscriptions.listPaymentAttempts(idOrCode, query)

Rates

const rateAndFee = await kyshi.rates.get({
  currency: 'NGN',
  rateType: 'MOR_RATES',
});

const customRateAndFee = await kyshi.customRates.get({
  currency: 'GHS',
});

Webhooks

Verify X-Kyshi-Signature before trusting an inbound webhook payload:

const event = kyshi.webhooks.constructEvent(
  rawRequestBody,
  request.headers['x-kyshi-signature'],
  process.env.KYSHI_WEBHOOK_SECRET!,
);

Webhook helper methods:

  • kyshi.webhooks.generateSignature(payload, secret)
  • kyshi.webhooks.verifySignature(payload, signature, secret)
  • kyshi.webhooks.constructEvent(payload, signature, secret)

Webhook operations:

  • kyshi.webhooks.listEvents(query)
  • kyshi.webhooks.retrieveEvent(eventId)
  • kyshi.webhooks.replayEvent(eventId)
  • kyshi.webhooks.listFailed(query)
  • kyshi.webhooks.retryTransaction(transactionId)
  • kyshi.webhooks.bulkRetry(params)
  • kyshi.webhooks.stats(query)
  • kyshi.webhooks.reliabilityStats(query)

Webhook delivery inspection and replay methods use the SDK secretKey. The integrating business must provide a Kyshi API key with access to those webhook operations routes.

Error Handling

import {
  KyshiApiError,
  KyshiAuthenticationError,
  KyshiNetworkError,
  KyshiTimeoutError,
  KyshiValidationError,
} from '@kyshi/mor-sdk';

try {
  await kyshi.transactions.verify('ORDER-001');
} catch (error) {
  if (error instanceof KyshiApiError) {
    console.error(error.statusCode, error.code, error.message);
  }

  if (error instanceof KyshiAuthenticationError) {
    console.error('Check your Kyshi secret key.');
  }

  if (error instanceof KyshiTimeoutError || error instanceof KyshiNetworkError) {
    console.error('The request did not complete. Retry safely if appropriate.');
  }

  if (error instanceof KyshiValidationError) {
    console.error('Check the request payload.');
  }
}

Low-Level Client

For routes that are not yet wrapped by a resource module, use the same authenticated HTTP client directly:

const transaction = await kyshi.client.get('transactions/history/trx_123');

The client handles x-api-key authentication, JSON request and response parsing, query parameters, response envelope unwrapping, idempotency keys, request timeouts, and transient retries for safe requests.

Other Languages

This release documents the Node.js and TypeScript SDK. Python, PHP, Java, Go, or other language SDKs should be released and documented as separate packages when they are available. They are not created automatically by publishing the Node.js SDK.

Release Status

The current package is @kyshi/[email protected].

During beta, endpoint coverage is limited to the SDK surface documented here and the package README.