StableNaira is a platform for buying and selling stablecoins in Nigeria with secure fiat on/off-ramp infrastructure for developers and businesses. This type-safe TypeScript/JavaScript SDK helps you integrate the StableNaira v1 API to manage accounts, wallets, payouts, and related workflows. Generate your API key from app.stablenaira.com before using the SDK.
- Node.js
>= 18(nativefetchrequired) - A StableNaira API key
npm install @stablenaira/sdkThe package exports:
createStableNairaClientStableNairaClientStableNairaApiErrorStableNairaNetworkError- all public SDK types from
src/types.ts
import { createStableNairaClient } from "@stablenaira/sdk";
const client = createStableNairaClient({
apiKey: process.env.STABLENAIRA_API_KEY!,
});
const banks = await client.banks.list();
console.log(banks.data[0]?.name);import {
createStableNairaClient,
type StableNairaClientOptions,
} from "@stablenaira/sdk";
const options: StableNairaClientOptions = {
apiKey: process.env.STABLENAIRA_API_KEY!, // required
baseUrl: "https://api.stablenaira.com/v1", // optional (default)
authMode: "x-api-key", // "x-api-key" | "bearer", default "x-api-key"
timeoutMs: 15_000, // default 15000ms
headers: {
"X-Correlation-Id": "req_123",
}, // optional extra headers
// fetch: customFetch, // optional fetch implementation
};
const client = createStableNairaClient(options);apiKeymust be non-empty (constructor throws otherwise).baseUrldefaults tohttps://api.stablenaira.com/v1.authMode: "x-api-key"sendsX-Api-Key: <key>.authMode: "bearer"sendsAuthorization: Bearer <key>.- For non-GET requests with a body, SDK sets
Content-Type: application/json.
All successful calls resolve with:
type StableNairaSuccessResponse<TData> = {
success: true;
data: TData;
message?: string;
error: null;
};Failures throw typed errors (see Error Handling), instead of returning success: false.
GET /v1/banks
const res = await client.banks.list({ scope: "transfer" });
// res.data is Bank[]ListBanksQuery:
type ListBanksQuery = {
scope?: string;
};GET /v1/wallet
const wallets = await client.wallet.list();
// wallets.data is MerchantWallet[]GET /v1/wallet/balance
const balance = await client.wallet.getBalance({
walletAddress: "0xA7A3D7e7E4A2AbcD20DA74E846A7fA1d677f8E27",
});
// balance.data is WalletBalance
const primaryBalance = await client.wallet.getBalance();
// if walletAddress is omitted, API resolves merchant primary walletGET /v1/recipients
const recipients = await client.recipients.list();
// recipients.data is Recipient[]POST /v1/recipients
const recipient = await client.recipients.create({
accountNumber: "0123456789",
accountName: "Jane Doe",
bankId: "bank_01JXYZ...",
});
// recipient.data is RecipientDELETE /v1/recipients/:recipientId
await client.recipients.remove("recipient_01...");
// response.data is nullPOST /v1/recipients/:recipientId/default
await client.recipients.setDefault("recipient_01...");
// response.data is nullGET /v1/virtual-account
const va = await client.virtualAccount.details();
// va.data is VirtualAccountGET /v1/virtual-account/balance
const vaBalance = await client.virtualAccount.balance();
// vaBalance.data is VirtualAccountBalancePOST /v1/virtual-account/withdraw
const withdrawal = await client.virtualAccount.withdraw({
amount: 25000,
recipientId: "recipient_01...", // optional
});
// withdrawal.data is { transaction: Transaction }GET /v1/transactions
const txs = await client.transactions.list();
// txs.data is Transaction[]POST /v1/transactions/redeem
const redeemed = await client.transactions.redeem({
amount: 15000,
recipientId: "recipient_01...", // optional
});
// redeemed.data is RedeemResponseDataPOST /v1/transactions/acquire
const acquired = await client.transactions.acquire({
amount: 50000,
destinationWalletAddress: "0xabc...", // optional
});
// acquired.data is { transaction: Transaction }POST /v1/transactions/withdraw
const withdrawn = await client.transactions.withdraw({
amount: 5000,
recipientId: "recipient_01...", // optional
});
// withdrawn.data is { transaction: Transaction }Thrown when:
- the API responds with a non-2xx status, or
- the API returns
success: false
Properties:
name: "StableNairaApiError"status: number(HTTP status)code: number(API error code or fallback status code)message: stringdetails?: StableNairaFailureResponse
Thrown on transport-level failures (network issues, timeout, invalid response body).
Properties:
name: "StableNairaNetworkError"message: stringcause?: unknown
import {
createStableNairaClient,
StableNairaApiError,
StableNairaNetworkError,
} from "@stablenaira/sdk";
const client = createStableNairaClient({
apiKey: process.env.STABLENAIRA_API_KEY!,
timeoutMs: 5_000,
});
try {
await client.transactions.redeem({ amount: 0 });
} catch (error) {
if (error instanceof StableNairaApiError) {
console.error("API error", error.status, error.code, error.message);
console.error("details", error.details);
} else if (error instanceof StableNairaNetworkError) {
console.error("Network error", error.message, error.cause);
} else {
console.error("Unknown error", error);
}
}Commonly used types:
BankMerchantWalletWalletBalanceRecipientVirtualAccountVirtualAccountBalanceTransactionRedeemResponseDataStableNairaSuccessResponse<T>StableNairaFailureResponse
Import any type directly:
import type {
Transaction,
StableNairaSuccessResponse,
} from "@stablenaira/sdk";import { createStableNairaClient } from "@stablenaira/sdk";
const client = createStableNairaClient({
apiKey: process.env.STABLENAIRA_API_KEY!,
});
const wallets = await client.wallet.list();
const primaryWallet = wallets.data.find((w) => w.isPrimary) ?? wallets.data[0];
const recipient = await client.recipients.create({
accountNumber: "0123456789",
accountName: "Jane Doe",
bankId: "bank_01JXYZ...",
});
const acquireTx = await client.transactions.acquire({
amount: 25000,
destinationWalletAddress: primaryWallet?.address,
});
const redeemTx = await client.transactions.redeem({
amount: 10000,
recipientId: recipient.data.id,
});
console.log({
acquireReference: acquireTx.data.transaction.reference,
redeemReference: redeemTx.data.transaction.reference,
});