Merchant Developer Portal

Integration guide for the Airpero multi-tenant fintech ecosystem. Build scaleable payment applications on top of the 9PSB infrastructure.

The Airpero SaaS API implements a robust, secure, and multi-tenant resilient architecture. Whether you are using our Dashboard or integrating via API, we provide the tools to manage customers and track financial flows with ease.

Authentication

We use a dual-auth system depending on your integration type. Never share your private keys.

Dashboard (JWT)

Used for UI-based management. Authenticate once and use the Bearer token.

Authorization: Bearer 

Server-to-Server (Keys)

Used for backend automation. Required for customer creation.

x-public-key: pk_...
x-private-key: sk_...
POST /merchants/register

Self-onboard your business to the Airpero ecosystem. Returns your unique API keys and 9PSB funding account.

Headers: None (Public)
Body: businessName, email, password
{
  "businessName": "My Fintech",
  "email": "dev@myfintech.com",
  "password": "secure_password"
}

Success Response:

{
  "success": true,
  "message": "Merchant registered successfully",
  "data": {
    "businessName": "My Fintech",
    "email": "dev@myfintech.com",
    "publicKey": "pk_live_...",
    "privateKey": "sk_live_...",
    "merchantAccountNumber": "99XXXXXXXX",
    "bankName": "9PSB"
  }
}
POST /merchants/login

Authenticate to your merchant dashboard. Returns a JWT Bearer token.

Headers: None (Public)
Body: email, password
{
  "email": "dev@myfintech.com",
  "password": "secure_password"
}

Success Response:

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "merchant": {
    "id": "uuid",
    "businessName": "My Fintech",
    "email": "dev@myfintech.com"
  }
}

Reporting Dashboards

Real-time financial metrics for your business overview.

GET /merchants/stats JWT Required

Fetches cumulative inflow, outflow, and total funds held by your customers.

Headers: Authorization: Bearer <JWT>
{
  "success": true,
  "data": {
    "merchantBalance": "50000.00",
    "totalCustomerFunds": 2500.00,
    "totalInflow": 12000.00,
    "customerCount": 42
  }
}
GET /merchants/transactions JWT Required

Detailed log of all customer financial flows. Support for filtering.

Headers: Authorization: Bearer <JWT>

Query Params: ?period=daily|monthly|yearly&status=success

Success Response:

{
  "success": true,
  "count": 2,
  "data": [
    {
      "transaction_id": "MCH-PAY-abc123",
      "type": "debit",
      "class": "payout",
      "amount": "1000.00",
      "status": "success",
      "createdAt": "2026-04-01T12:00:00.000Z"
    }
  ]
}

Customer Creation

For security, customer creation is restricted to **API Key Auth** only. This prevents unauthorized sessions from minting virtual accounts.

POST /customers API Keys Only

Register a new customer and assign a 9PSB virtual account. The account name will be prefixed with your preview name (or business name by default).

Headers: x-public-key, x-private-key
Body: fullName, email, phoneNumber
{
  "fullName": "Jane Doe",
  "email": "jane@example.com",
  "phoneNumber": "08100000000"
}

Success Response:

{
  "success": true,
  "message": "Customer created successfully",
  "data": {
    "id": "customer-uuid",
    "fullName": "Jane Doe",
    "accountNumber": "99XXXXXXXX",
    "bankName": "9PSB"
  }
}
GET /customers/{id} Auth Required

Retrieve full details for a specific customer, including their balance and virtual account information.

Headers: API Keys OR JWT Bearer

Success Response:

{
  "success": true,
  "data": {
    "id": "customer-uuid",
    "merchantId": "merchant-uuid",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "phoneNumber": "08100000000",
    "accountNumber": "99XXXXXXXX",
    "balance": "5000.00",
    "createdAt": "2026-04-01T12:00:00.000Z"
  }
}
POST /customers/{id}/payout Private Key Required

Send money out of a specific customer's balance. Requires Private Key auth.

Headers: x-private-key
Body: amount, accountNumber, bankCode, accountName
{
  "amount": 2000,
  "accountNumber": "0123456789",
  "bankCode": "90052",
  "accountName": "John Doe"
}

Success Response:

{
  "status": "SUCCESS",
  "responseCode": "00",
  "message": "Transaction Successful",
  "data": {
    "reference": "PAYOUT-abc123",
    "fee": 20.00,
    "transaction_id": "PAYOUT-abc123"
  }
}
POST /customers/{id}/debit Auth Required

Directly debit a customer's balance (moves funds to your merchant wallet).

Headers: API Keys OR JWT Bearer
Body: amount, reason
{
  "amount": 1500,
  "reason": "Service Charge"
}

Success Response:

{
  "success": true,
  "message": "Successfully debited customer Jane Doe",
  "data": {
    "transaction_id": "MCH-DR-xyz789",
    "amount": 1500.00,
    "fee": 0,
    "status": "success"
  }
}
POST /customers/{id}/credit Auth Required

Directly credit a customer's balance from your merchant wallet.

Headers: API Keys OR JWT Bearer
Body: amount, narration
{
  "amount": 2500,
  "narration": "Customer Reward"
}

Success Response:

{
  "success": true,
  "message": "Successfully credited customer Jane Doe",
  "data": {
    "transaction_id": "MCH-CR-abc123",
    "amount": 2500.00,
    "fee": 0,
    "status": "success"
  }
}

Bank Utilities

Helper tools for bank identification and account validation.

GET /customers/:customerId/report Auth Required

Fetch summarized inflow/outflow report for a customer.

Headers: API Keys OR JWT Bearer
Query Params: period (daily/monthly/yearly), startDate, endDate

Success Response:

{
  "success": true,
  "data": {
    "totalVolume": 5000.00,
    "totalCredit": 3500.00,
    "totalDebit": 1500.00,
    "transactionCount": 12
  }
}
GET /customers/:customerId/transactions Auth Required

Get the full granular list of transactions for a customer.

Headers: API Keys OR JWT Bearer

Success Response:

{
  "success": true,
  "count": 1,
  "data": [
    {
      "transaction_id": "DEP-123",
      "type": "credit",
      "amount": 500.00,
      "status": "success"
    }
  ]
}
GET /banks Auth Required

Get a list of all Nigerian banks and their codes.

Headers: API Keys OR JWT Bearer

Success Response:

{
  "success": true,
  "data": [
    { "name": "Access Bank", "code": "044" },
    { "name": "Guaranty Trust Bank", "code": "058" }
  ]
}
POST /banks/enquiry Auth Required

Verify the account name for a given number and bank.

Headers: API Keys OR JWT Bearer
Body: accountNumber, bankCode
{
  "accountNumber": "0123456789",
  "bankCode": "058"
}

Success Response:

{
  "success": true,
  "data": {
    "accountName": "JOHN DOE",
    "accountNumber": "0123456789",
    "bankCode": "058"
  }
}
POST /transactions/requery Auth Required

Verify the status of a specific transaction ID. Optional `accountNo` improves accuracy.

Headers: API Keys OR JWT Bearer
Body: transactionId, accountNo (optional)
{ 
  "transactionId": "PAYOUT-12345",
  "accountNo": "0123456789"
}

Success Response:

{
  "success": true,
  "data": {
    "status": "SUCCESS",
    "amount": 2000,
    "transactionId": "PAYOUT-12345",
    "updatedAt": "2026-04-01T15:00:00Z"
  }
}

Webhooks & Hooks

Airpero delivers instant POST notifications. We recommend logging all inbound payloads for audit purposes.

PATCH /merchants/webhook JWT Required

Update your destination URL for notifications.

Headers: Authorization: Bearer <JWT>
Body: webhookUrl
{ "webhookUrl": "https://api.yourdomain.com/hooks" }

Success Response:

{
  "success": true,
  "message": "Webhook URL updated successfully",
  "data": {
    "businessName": "My Fintech",
    "webhookUrl": "https://api.yourdomain.com/hooks"
  }
}
PATCH /merchants/profile JWT Required

Update your business name or current 'preview' prefix for virtual accounts.

Headers: Authorization: Bearer <JWT>
Body: preview, businessName
{ "preview": "AIRPERO", "businessName": "Airpero Global" }

Success Response:

{
  "success": true,
  "message": "Profile updated successfully",
  "data": {
    "preview": "AIRPERO",
    "businessName": "Airpero Global"
  }
}

Detailed Webhook Payload (PAYIN_SUCCESS):

Sent to your callback URL when a customer successfully deposits funds via their virtual account.

{
  "event": "PAYIN_SUCCESS",
  "merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-04-06T10:45:10.000Z",
  "data": {
    "transactionId": "100004260402085201156174739776",
    "customerId": "88776655-4433-2211-0099-aabbccddeeff",
    "customerName": "DESTINY MOMODU",
    "senderName": "DANIEL OSAGIE ABIEVBODE",
    "senderAccountNumber": "8032184432",
    "senderBankName": "Palmpay",
    "senderBankCode": "100033",
    "amount": 10000.00,
    "fee": 50.00,
    "total_amount": 10000.00,
    "currency": "NGN",
    "reference": "CUST-VA-17be8eaf",
    "transactionDate": "2026-04-02T17:09:05"
  }
}

Detailed Webhook Payload (WALLET_FUNDED):

Sent to your callback URL when you fund your own merchant wallet directly.

{
  "event": "WALLET_FUNDED",
  "merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-04-06T10:45:10.000Z",
  "data": {
    "transactionId": "100004260402085201156174739776",
    "amount": 50000.00,
    "currency": "NGN",
    "reference": "MCH-VA-ref123",
    "senderName": "DANIEL OSAGIE ABIEVBODE",
    "senderAccountNumber": "8032184432",
    "senderBankName": "Palmpay",
    "transactionDate": "2026-04-02T17:09:05"
  }
}

Payout Operations

Initiate transfers out of your merchant wallet to any destination bank.

💡 Stamp Duty: Transfers above ₦10,000 attract a mandatory ₦50 stamp duty fee, as per regulatory requirements.
POST /merchants/payout Auth Required

Real-time transfer via 9PSB infrastructure.

Headers: API Keys OR JWT Bearer
Body: amount, accountNumber, bankCode, accountName, narration
{
  "amount": 1000,
  "accountNumber": "0123456789",
  "bankCode": "90052",
  "accountName": "John Doe",
  "narration": "Monthly Settlement"
}

Success Response:

{
  "success": true,
  "message": "Payout initiated successfully",
  "data": {
    "reference": "MCH-PAY-xyz789",
    "status": "SUCCESS",
    "fee": "20.00",
    "transaction_id": "MCH-PAY-xyz789"
  }
}

© 2026 Airpero SaaS. Branded documentation for authorized merchants.