prostackng
v1.0.0
Published
Official JavaScript/TypeScript SDK for ProStack NG — Africa's unified API gateway
Maintainers
Readme
prostackng
Official JavaScript/TypeScript SDK for ProStack NG — Africa's unified API gateway for Nigerian developers.
One key. Five APIs. Billed in Naira.
Installation
npm install prostackng
# or
yarn add prostackng
# or
pnpm add prostackngQuick Start
import { ProStack } from 'prostackng';
const client = new ProStack({ apiKey: 'psk_live_...' });
// Send an SMS
const sms = await client.notifications.sendSms({
to: '08012345678',
message: 'Your OTP is 4821. Valid for 5 minutes.',
});
// Verify a BVN
const bvn = await client.identity.verifyBvn({
bvn: '12345678901',
first_name: 'John',
last_name: 'Doe',
});
// Initiate a payment
const payment = await client.payments.initiate({
amount: 5000, // ₦5,000 — kobo conversion handled automatically
email: '[email protected]',
});
window.location.href = payment.authorization_url;Get your API key at prostack-api-dashboard.vercel.app.
Configuration
const client = new ProStack({
apiKey: 'psk_live_...', // Required
environment: 'live', // Optional: 'test' | 'live' — inferred from key prefix
timeout: 30_000, // Optional: request timeout in ms (default: 30000)
maxRetries: 3, // Optional: retries on 429 / 5xx (default: 3)
baseUrl: 'https://...', // Optional: override API base URL
});The SDK automatically infers the environment from your API key prefix:
psk_test_...→test(free, sandbox responses, no real charges)psk_live_...→live(real providers, balance debited)
Services
Notifications
// Send a single SMS
await client.notifications.sendSms({
to: '08012345678',
message: 'Hello!',
sender_id: 'MyApp', // optional
});
// Send an email
await client.notifications.sendEmail({
to: '[email protected]',
subject: 'Welcome to MyApp',
body: 'Thanks for signing up.',
html: '<p>Thanks for signing up.</p>', // optional
});
// Bulk SMS (up to 10,000 recipients — async processing)
const job = await client.notifications.sendBulkSms({
recipients: [
{ to: '08012345678', message: 'Hi John!' },
{ to: '08098765432', message: 'Hi Jane!' },
],
callback_url: 'https://yourapp.com/webhooks/bulk', // optional
});
// Poll bulk job status
const status = await client.notifications.getBulkJobStatus(job.job_id);
console.log(`${status.sent}/${status.total} sent`);Payments
// Initiate payment (Paystack or Flutterwave)
const payment = await client.payments.initiate({
amount: 5000, // ₦5,000
email: '[email protected]',
provider: 'paystack', // optional, default: 'paystack'
reference: 'MY-REF-001', // optional, auto-generated if omitted
metadata: { order_id: '99' }, // optional, returned in webhooks
});
// Redirect user to payment.authorization_url
// Verify after payment
const verified = await client.payments.verify('MY-REF-001');
if (verified.status === 'success') {
// Fulfill order
}
// List transactions
const txns = await client.payments.list(50);Identity / KYC
BVN and NIN verification require a LIVE API key.
// Verify BVN
const result = await client.identity.verifyBvn({
bvn: '12345678901',
first_name: 'John', // optional cross-validation
last_name: 'Doe',
date_of_birth: '1990-01-15', // YYYY-MM-DD
});
// Verify NIN
const nin = await client.identity.verifyNin({
nin: '12345678901',
first_name: 'Jane',
});
// Verify phone number
const phone = await client.identity.verifyPhone({
phone: '08012345678',
network: 'mtn', // optional hint
});
// List recent checks
const checks = await client.identity.list(50);VTU / Utility Bills
// Buy airtime
await client.vtu.buyAirtime({ phone: '08012345678', amount: 500, network: 'mtn' });
// Buy mobile data
const plans = await client.vtu.listDataPlans('airtel');
await client.vtu.buyData({ phone: '08012345678', plan_id: plans[0].id, network: 'airtel' });
// Pay electricity bill
const bill = await client.vtu.payElectricity({
meter_number: '12345678901',
disco: 'phed',
meter_type: 'prepaid',
amount: 5000,
});
console.log(bill.token); // Meter token for prepaid
// Pay cable TV
await client.vtu.payCableTv({
decoder_number: '1234567890',
provider: 'dstv',
package: 'CONFAM',
});Reports
// Generate a PDF report (async — poll for completion)
const report = await client.reports.generate({
title: 'April 2026 Sales',
output_format: 'pdf', // 'pdf' | 'excel' | 'both'
data: [
{ date: '2026-04-01', product: 'Widget A', amount: 15000 },
{ date: '2026-04-02', product: 'Widget B', amount: 7500 },
],
});
// Poll until complete
let result = await client.reports.getById(report.id);
while (result.status === 'pending' || result.status === 'processing') {
await new Promise(r => setTimeout(r, 3000));
result = await client.reports.getById(report.id);
}
console.log(result.output_url); // Download URLWebhooks
// Register endpoint
const wh = await client.webhooks.create({
url: 'https://yourapp.com/webhooks/prostack',
events: ['payment.success', 'identity.verified', 'vtu.success'],
});
// List and delete
const list = await client.webhooks.list();
await client.webhooks.delete(wh.id);Webhook Verification
Always verify incoming webhook signatures before processing events.
// Express.js example
import express from 'express';
import { ProStack } from 'prostackng';
const app = express();
app.post(
'/webhooks/prostack',
express.raw({ type: 'application/json' }),
async (req, res) => {
const isValid = await ProStack.verifyWebhook({
payload: req.body, // raw Buffer — do NOT parse first
signature: req.headers['x-prostack-signature'] as string,
secret: process.env.PROSTACK_WEBHOOK_SECRET!,
});
if (!isValid) {
return res.status(400).send('Invalid signature');
}
const event = ProStack.parseWebhookPayload(req.body.toString());
switch (event.event) {
case 'payment.success':
// event.data contains the payment object
break;
case 'identity.verified':
// event.data contains the identity check
break;
}
res.status(200).send('OK');
}
);Available webhook events
| Event | Fired when |
|---|---|
| payment.success | Payment verified as successful |
| payment.failed | Payment failed or was abandoned |
| notification.sent | SMS or email delivered |
| notification.failed | SMS or email delivery failed |
| identity.verified | BVN/NIN/phone check passed |
| identity.failed | BVN/NIN/phone check failed |
| vtu.success | Airtime/data/utility purchase succeeded |
| vtu.failed | VTU purchase failed |
| report.completed | Report generation finished |
| report.failed | Report generation failed |
Error Handling
The SDK throws typed errors — catch them specifically for clean error handling:
import {
ProStack,
ProStackError,
AuthenticationError,
ValidationError,
InsufficientBalanceError,
RateLimitError,
NetworkError,
} from 'prostackng';
try {
await client.identity.verifyBvn({ bvn: '12345678901' });
} catch (err) {
if (err instanceof InsufficientBalanceError) {
console.error(`Insufficient balance. Have ₦${err.balance}, need ₦${err.required}`);
// Prompt user to top up wallet
} else if (err instanceof RateLimitError) {
console.error(`Rate limited. Retry in ${err.retryAfter}s`);
} else if (err instanceof AuthenticationError) {
console.error('Invalid API key — check your ProStack dashboard');
} else if (err instanceof ValidationError) {
console.error('Validation failed:', err.fields);
} else if (err instanceof NetworkError) {
console.error('Connection failed:', err.message);
} else if (err instanceof ProStackError) {
console.error(`API error ${err.statusCode}:`, err.message);
}
}Automatic Retries
The SDK automatically retries on 429 Too Many Requests and 5xx server errors with exponential backoff (500ms → 1s → 2s, with ±10% jitter). Auth errors (401/403) and validation errors (400/422) are not retried.
Configure via maxRetries (default: 3, set to 0 to disable).
TypeScript
The SDK is written in TypeScript and ships full type definitions. No @types/prostackng needed.
import type {
SendSmsRequest,
IdentityVerificationResponse,
PaymentTransaction,
VtuTransaction,
WebhookEvent,
} from 'prostackng';Environments
| Environment | Key prefix | Behaviour |
|---|---|---|
| test | psk_test_... | Sandbox responses, no real charges, balance not deducted |
| live | psk_live_... | Real providers, real charges, requires verified account |
Pricing (NGN)
| Service | Cost per call | |---|---| | SMS | ₦4 | | Email | ₦0.50 | | BVN verification | ₦100 | | NIN verification | ₦150 | | Phone verification | ₦50 | | Airtime VTU | Face value + 1.5% | | Report (PDF/Excel) | ₦20 |
All costs are deducted from your ProStack wallet balance.
Requirements
- Node.js 16+ (uses native
fetchandcrypto) - Browser: any modern browser with
fetchandSubtleCryptosupport - Frameworks: Works with Express, Fastify, Next.js, Remix, NestJS, Deno, Bun, etc.
License
MIT © ProStack NG Technologies Ltd
Built in Port Harcourt, Nigeria 🇳🇬
