fibsubscribe
v1.0.0
Published
Official Node.js SDK for the First Iraqi Bank (FIB) Subscription Service
Maintainers
Readme
FibSubscribe
Official Node.js SDK for the First Iraqi Bank (FIB) Subscription Service
Table of Contents
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Subscription Statuses
- ISO-8601 Period Cheatsheet
- Error Handling
- Webhook Integration
- Examples
- Publishing
Features
- ✅ Full coverage of the FIB Subscription API (create, get, cancel)
- 🔐 Automatic OAuth2 token management with expiry refresh
- ⏳ Built-in polling helper (
waitForActivation) - 🌍 Stage & Production environment support
- 📦 Zero runtime dependencies
- 🔷 ESM-native (
"type": "module") - 📝 Full JSDoc type annotations
Installation
npm install fibsubscribeRequires Node.js v14 or higher. This package is ESM-only — use
import, notrequire().
Quick Start
import { FibSubscribe } from 'fibsubscribe';
const fib = new FibSubscribe({
clientId: process.env.FIB_CLIENT_ID,
clientSecret: process.env.FIB_CLIENT_SECRET,
environment: 'stage', // or 'production'
});
// 1. Create a monthly subscription with a 7-day trial
const sub = await fib.createSubscription({
title: 'Premium Membership',
description: 'Full access to all premium features.',
amount: 5000,
currency: 'IQD',
interval: 'P1M', // every 1 month
trialPeriod: 'P7D', // 7-day free trial
expiresIn: 'P1DT12H', // QR valid for 1 day 12 hours
statusCallbackUrl: 'https://yoursite.com/fib/subscription/webhook',
});
// 2. Show QR code or app link to the subscriber
console.log('App Link:', sub.appLink);
// Render: <img src={sub.qrCode} />
// 3. Wait until subscriber confirms (or rejects)
const result = await fib.waitForActivation(sub.subscriptionId);
console.log('Status:', result.status); // 'ACTIVE' | 'TRIAL' | 'REJECTED' | 'CANCELLED'Configuration
const fib = new FibSubscribe({
clientId: 'YOUR_CLIENT_ID', // required
clientSecret: 'YOUR_CLIENT_SECRET', // required
environment: 'stage', // 'stage' (default) | 'production'
});| Option | Type | Required | Default | Description |
|-----------------|----------|----------|-----------|------------------------------------------------|
| clientId | string | ✅ | — | FIB-issued client ID |
| clientSecret | string | ✅ | — | FIB-issued client secret |
| environment | string | ❌ | 'stage' | 'stage' for testing, 'production' for live |
| Environment | Base URL | |-------------------|--------------------------| | Stage (Test Mode) | https://fib-stage.fib.iq | | Production (Live) | https://fib.prod.fib.iq |
API Reference
Create Subscription
const sub = await fib.createSubscription(options);| Parameter | Type | Required | Default | Description |
|---------------------|----------|----------|---------|------------------------------------------------------|
| title | string | ✅ | — | Display name (e.g. "Premium Streaming") |
| description | string | ❌ | — | What the subscriber gets |
| amount | number | ✅ | — | Charge per interval (positive number) |
| currency | string | ❌ | 'IQD' | ISO 4217 code |
| interval | string | ✅ | — | ISO-8601 billing period (e.g. "P1M", "P7D") |
| trialPeriod | string | ❌ | — | ISO-8601 free trial (e.g. "P7D"). Omit = no trial |
| expiresIn | string | ❌ | — | QR code validity (e.g. "P1DT12H") |
| statusCallbackUrl | string | ❌ | — | Webhook URL for status-change events |
Response
{
"subscriptionId": "1d1b9133-6932-45b6-94bc-c40882da1bf9",
"readableCode": "DMRJ-JAMJ-RN36",
"qrCode": "data:image/png;base64,...",
"validUntil": "2025-08-19T19:40:35.087Z",
"appLink": "https://p-stage.fib.iq/0fc8/subscription?identifier=DDRKDIOZJEUW"
}Get Subscription
const details = await fib.getSubscription(subscriptionId);Response
{
"id": "8d77b6b2-3eb3-4c74-9a95-9779ddfbbe94",
"readableCode": "DAID-9CTX-5YBU",
"title": "Premium Membership",
"description": "Full access to all premium features.",
"monetaryValue": { "amount": 5000, "currency": "IQD" },
"interval": "P1M",
"trialPeriod": "P7D",
"status": "TRIAL",
"activeUntil": 1755588900190,
"lastPaymentAt": null
}Cancel Subscription
Cancels an active or trial subscription. Returns null on success (HTTP 202).
await fib.cancelSubscription(subscriptionId);Wait for Activation
Polls getSubscription() until the subscription leaves DRAFT status or the timeout is exceeded.
const result = await fib.waitForActivation(subscriptionId, options);| Parameter | Type | Default | Description |
|--------------|----------|----------|--------------------------------------|
| intervalMs | number | 4000 | Polling interval in milliseconds |
| timeoutMs | number | 300000 | Max wait time in ms (default: 5 min) |
Subscription Statuses
| Status | Description |
|-------------|----------------------------------------------------------|
| DRAFT | Created, awaiting subscriber confirmation via QR/app |
| TRIAL | Subscriber confirmed, currently in free trial |
| ACTIVE | Trial ended or no trial — subscriber is actively charged |
| REJECTED | Subscriber declined the subscription |
| CANCELLED | Cancelled by merchant or subscriber |
ISO-8601 Period Cheatsheet
| Value | Meaning |
|------------|-----------------|
| P1D | Every day |
| P7D | Every 7 days |
| P1M | Every month |
| P3M | Every 3 months |
| P1Y | Every year |
| P1DT12H | 1 day 12 hours |
Error Handling
import { FibSubscribe, FibSubscribeError } from 'fibsubscribe';
try {
await fib.createSubscription({ title: 'Plan', amount: 1000, interval: 'P1M' });
} catch (err) {
if (err instanceof FibSubscribeError) {
console.error('API Error:', err.message);
console.error('Status Code:', err.statusCode);
console.error('Body:', err.body);
} else {
throw err;
}
}Webhook Integration
Pass a statusCallbackUrl when creating a subscription. FIB will POST to this URL on every status change.
app.post('/fib/subscription/webhook', (req, res) => {
const { subscriptionId, status } = req.body;
res.sendStatus(200); // acknowledge immediately
switch (status) {
case 'ACTIVE': /* enable full access */ break;
case 'TRIAL': /* enable trial access */ break;
case 'CANCELLED': /* revoke access */ break;
case 'REJECTED': /* notify the user */ break;
}
});Examples
| File | Description |
|------|-------------|
| examples/basic.js | Create → wait → cancel flow |
| examples/express-webhook.js | Express server with full webhook handling |
FIB_CLIENT_ID=xxx FIB_CLIENT_SECRET=yyy node examples/basic.jsESM Compatibility Note
This package is ESM-only. For CommonJS projects use a dynamic import:
const { FibSubscribe } = await import('fibsubscribe');License
MIT © Rageofkurd
