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-sdkFor the beta release:
npm install @kyshi/mor-sdk@betaThe 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| Secret | Used For |
|---|---|
KYSHI_SECRET_KEY | Outbound SDK API calls from your backend using x-api-key. |
KYSHI_WEBHOOK_SECRET | Inbound 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 Area | SDK Resource |
|---|---|
| Transactions | kyshi.transactions |
| Payment Links | kyshi.paymentLinks |
| General Payment Links | kyshi.generalPaymentLinks |
| Virtual Accounts | kyshi.virtualAccounts |
| Transfers | kyshi.transfers |
| Virtual Account Transfers | kyshi.virtualAccountTransfers |
| Plans | kyshi.plans |
| Subscriptions | kyshi.subscriptions |
| Rates | kyshi.rates |
| Custom Rates | kyshi.customRates |
| Webhooks | kyshi.webhooks |
Configuration
const kyshi = new Kyshi({
secretKey: process.env.KYSHI_SECRET_KEY!,
environment: 'test',
timeoutMs: 30_000,
maxRetries: 2,
retryDelayMs: 250,
});| Option | Type | Description |
|---|---|---|
secretKey | string | Required Kyshi secret key. |
environment | test or live | SDK environment label. Defaults to test. |
baseUrl | string | Optional custom API base URL. |
timeoutMs | number | Request timeout in milliseconds. Defaults to 30000. |
maxRetries | number | Default retry count for retryable requests. Defaults to 2. |
retryDelayMs | number | Initial retry delay in milliseconds. Defaults to 250. |
fetch | function | Optional 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.
