Skip to content

grtsnx/payba3

Repository files navigation

payba3

Framework-neutral payment integration surface for many payment channels.

License · Docs · Contributing · Security · Support

payba3

payba3 is an open-source collection of payment-channel integrations built for developers, teams, codebases, automations, and AI agents that need a simple way to plug into different payment providers from server-side TypeScript or JavaScript.

Configure the provider you want, select it through payba3, and call the channel.

const paystack = payba3.use('paystack');

await paystack.initializeOneTimeCheckout({
  email: 'customer@example.com',
  amountInKobo: 500000,
  currency: 'NGN',
});

payba3 is growing. More providers, methods, adapters, and examples will be added over time.

Documentation

Detailed Mintlify documentation lives in docs/ with the site map in docs.json. The repository supports both Mintlify project-directory layouts:

  • repository root: docs.json
  • docs subdirectory: docs/docs.json

Preview locally:

bun run docs:dev

Preview the /docs project-directory setup:

bun run docs:dev:docs

Use a Mintlify-supported LTS Node runtime for docs commands. Node 26 is not supported by the Mintlify CLI at the moment.

The docs cover installation, configuration, provider-specific usage, examples for common frameworks, agent and IDE integration, security, migration, and a separate API Reference tab.

About

Modern products rarely stay tied to one payment provider forever. A team may start with one checkout provider, add virtual accounts later, route a payout through another provider, run identity checks with a verification API, and still need a clean way for application code, scripts, background jobs, and AI agents to call those channels without learning every provider from scratch.

payba3 is a developer-friendly payment integration layer for that reality. It gives each provider a named channel, keeps provider credentials in configuration, and exposes direct methods for common actions such as checkout, virtual accounts, transfers, subaccounts, account linking, and identity checks.

Use payba3 when you want:

  • One dependency for multiple payment and verification providers.
  • A simple provider selector: payba3.use('provider').
  • Provider-specific methods without rewriting authentication and token-refresh logic.
  • A project that can be used by normal application code, workflow automations, scripts, and AI agents.
  • A growing open-source base where more providers can be added over time.

Supported Channels

Channel Common use cases Provider signup Provider docs
Paystack Checkout, subscriptions, transfers, dedicated accounts Create account Docs
Safehaven Virtual accounts, subaccounts, banking APIs Sandbox Docs
SeerBit Collections, virtual accounts, online payments Create account Docs
OPay Checkout, signed payment APIs, refunds Merchant dashboard Docs
Mono Open banking, account linking, DirectPay, lookup Create account Docs
Monnify Checkout, reserved accounts, transfers, wallets Create account Docs
QoreID KYC, CAC lookup, identity verification Create account Docs

Installation

npm install @grtsnx/payba3
yarn add @grtsnx/payba3
pnpm add @grtsnx/payba3
bun add @grtsnx/payba3

payba3 ships compiled JavaScript, TypeScript declarations, and an npm exports map. It is tested with npm and Bun install smoke checks in CI. Yarn and pnpm can consume the same npm package metadata.

Runtime Requirements

payba3 2.x is framework-neutral. It does not require Nest, Express, Fastify, Next.js, or any other framework package to import or use the provider clients.

Use it in server-side JavaScript or TypeScript with a runtime that provides fetch, URLSearchParams, and Node-compatible crypto APIs. Node.js 18+ and Bun are covered by package smoke tests.

If you are using the repository directly:

bun install

Quick Usage

Create a payba3 client, configure the providers you want, then select a channel.

import { createPayba3 } from '@grtsnx/payba3';

const payba3 = createPayba3({
  paystack: {
    secretKey: process.env.PAYSTACK_SECRET_KEY,
  },
  safehaven: {
    environment: 'sandbox',
    clientId: process.env.SAFEHAVEN_CLIENT_ID,
    clientAssertion: process.env.SAFEHAVEN_CLIENT_ASSERTION,
  },
});

const checkout = await payba3.use('paystack').initializeOneTimeCheckout({
  email: 'customer@example.com',
  amountInKobo: 250000,
  currency: 'NGN',
  reference: 'order_123',
});

const subAccount = await payba3.use('safehaven').createSubAccount({
  phoneNumber: '08000000000',
  identityType: 'vID',
  identityId: 'identity-id',
  emailAddress: 'customer@example.com',
  externalReference: 'customer_123',
});

You can also use a channel directly when you want provider-specific methods:

const monnify = payba3.use('monnify');

await monnify.createReservedAccount({
  accountReference: 'customer_123',
  accountName: 'Jane Doe',
  customerName: 'Jane Doe',
  customerEmail: 'jane@example.com',
  bvn: '00000000000',
});

Configuration

Only configure the providers you use. Missing credentials for unused providers should not block your application from starting.

You can configure providers through createPayba3() options, environment variables, or a mix of both. Explicit constructor options win over environment variables.

const payba3 = createPayba3({
  monnify: {
    environment: 'live',
    apiKey: process.env.MONNIFY_LIVE_API_KEY,
    secretKey: process.env.MONNIFY_LIVE_SECRET_KEY,
    contractCode: process.env.MONNIFY_LIVE_CONTRACT_CODE,
  },
  qoreid: {
    clientId: process.env.QOREID_CLIENT,
    secret: process.env.QOREID_SECRET,
  },
});

Paystack

PAYSTACK_ENVIRONMENT=sandbox
PAYSTACK_SECRET_KEY=
PAYSTACK_SECRET_KEY_LIVE=

Safehaven

SAFEHAVEN_ENVIRONMENT=sandbox
SAFEHAVEN_CLIENT_ID=
SAFEHAVEN_CLIENT_ASSERTION=
SAFEHAVEN_LIVE_CLIENT_ID=
SAFEHAVEN_LIVE_CLIENT_ASSERTION=
SAFEHAVEN_TIMEOUT_MS=10000

Switch to production:

SAFEHAVEN_ENVIRONMENT=live

SeerBit

SEERBIT_ENVIRONMENT=sandbox
SEERBIT_BASE_URL=
SEERBIT_PUBLIC_KEY=
SEERBIT_SECRET_KEY=
SEERBIT_LIVE_PUBLIC_KEY=
SEERBIT_LIVE_SECRET_KEY=

OPay

OPAY_ENVIRONMENT=sandbox
OPAY_MERCHANT_ID=
OPAY_PUBLIC_KEY=
OPAY_SECRET_KEY=
OPAY_LIVE_MERCHANT_ID=
OPAY_LIVE_PUBLIC_KEY=
OPAY_LIVE_SECRET_KEY=

Mono

MONO_ENVIRONMENT=sandbox
MONO_SECRET_KEY=
MONO_LIVE_SECRET_KEY=

Monnify

MONNIFY_ENVIRONMENT=sandbox
MONNIFY_API_KEY=
MONNIFY_SECRET_KEY=
MONNIFY_CONTRACT_CODE=
MONNIFY_LIVE_API_KEY=
MONNIFY_LIVE_SECRET_KEY=
MONNIFY_LIVE_CONTRACT_CODE=

QoreID

QOREID_ENVIRONMENT=sandbox
QOREID_BASE_URL=
QOREID_CLIENT=
QOREID_SECRET=
QOREID_LIVE_CLIENT=
QOREID_LIVE_SECRET=

Provider Selection

payba3.use('paystack');
payba3.use('safehaven');
payba3.use('seerbit');
payba3.use('opay');
payba3.use('mono');
payba3.use('monnify');
payba3.use('qoreid');

Unsupported providers throw a clear error.

payba3.use('unknown'); // throws Unsupported payment channel

Token Handling

payba3 refreshes expiring provider tokens before they become stale.

  • Safehaven uses expires_in from the token response.
  • Safehaven stores ibs_client_id from the token response for account-call ClientID headers.
  • QoreID accepts expiresIn or expires_in from the token response.
  • Monnify derives expiry from the JWT exp claim when available.

For AI Agents And Automation

payba3 is intended to be easy for agents, IDE assistants, code generators, and automation workflows to reason about:

  • Provider names are explicit.
  • Configuration is environment based.
  • Request signing and token refresh are handled by payba3.
  • Provider-specific actions remain discoverable through named channels.

Agent Documentation Files

The npm package includes an LLM index, a full LLM context file, an agent guide, a machine-readable manifest, a suggested MCP-style tool schema, and provider-specific references. Agents and IDEs can read these files from an installed package instead of scraping source code.

import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);

const indexPath = require.resolve('@grtsnx/payba3/llms.txt');
const fullContextPath = require.resolve('@grtsnx/payba3/llms-full.txt');
const agentGuidePath = require.resolve('@grtsnx/payba3/agents.md');
const manifestPath = require.resolve('@grtsnx/payba3/agents.json');
const paystackPath = require.resolve('@grtsnx/payba3/llms/paystack.txt');

const payba3Guide = readFileSync(indexPath, 'utf8');
const fullContext = readFileSync(fullContextPath, 'utf8');
const agentGuide = readFileSync(agentGuidePath, 'utf8');
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
const paystackGuide = readFileSync(paystackPath, 'utf8');

Available agent and provider docs:

@grtsnx/payba3/llms.txt
@grtsnx/payba3/llms-full.txt
@grtsnx/payba3/agents.md
@grtsnx/payba3/agents.json
@grtsnx/payba3/agents/ide-prompt.md
@grtsnx/payba3/agents/mcp-tools.json
@grtsnx/payba3/llms/paystack.txt
@grtsnx/payba3/llms/safehaven.txt
@grtsnx/payba3/llms/seerbit.txt
@grtsnx/payba3/llms/opay.txt
@grtsnx/payba3/llms/mono.txt
@grtsnx/payba3/llms/monnify.txt
@grtsnx/payba3/llms/qoreid.txt

IDE And Agent Workflow

For IDEs, coding agents, and internal app generators:

  1. Install @grtsnx/payba3.
  2. Read @grtsnx/payba3/llms.txt.
  3. Read @grtsnx/payba3/agents.md.
  4. Read @grtsnx/payba3/agents.json when a machine-readable manifest is useful.
  5. Read the provider file for the requested channel.
  6. Generate server-side code that imports from @grtsnx/payba3.
  7. Ask the developer for only the provider environment variables they need.
  8. Keep secrets on the server and verify provider callbacks before delivering value.

Example prompt for an IDE agent:

Use @grtsnx/payba3 to add Paystack checkout.
Read @grtsnx/payba3/llms.txt, @grtsnx/payba3/agents.md, and @grtsnx/payba3/llms/paystack.txt first.
Only add server-side code.
Use PAYSTACK_SECRET_KEY from the environment.
Verify transactions server-side before marking an order paid.

For MCP servers or similar tool runtimes, use @grtsnx/payba3/agents/mcp-tools.json as a starting contract. It describes safe, narrow tool shapes and marks actions that should generally require human approval, such as account creation and money-moving flows.

For AI tool servers, expose small provider actions instead of exposing raw secrets:

import { createPayba3, type Payba3ChannelName } from '@grtsnx/payba3';

type PaymentToolInput = {
  channel: Payba3ChannelName;
  action: 'initializeCheckout' | 'verifyTransaction';
  payload: Record<string, unknown>;
};

const payba3 = createPayba3({
  paystack: {
    secretKey: process.env.PAYSTACK_SECRET_KEY,
  },
});

export class PaymentTool {
  async run(input: PaymentToolInput) {
    const provider = payba3.use(input.channel);

    if (input.channel === 'paystack' && input.action === 'initializeCheckout') {
      return provider.initializeOneTimeCheckout({
        email: String(input.payload.email),
        amountInKobo: Number(input.payload.amountInKobo),
        reference: String(input.payload.reference),
      });
    }

    throw new Error('Unsupported payment tool action');
  }
}

Contributor Checks

bun install --frozen-lockfile
bun run lint
bun run test
bun run test:providers
bun run test:e2e
bun run build
bun run pack:dry
bun run test:package
bun run test:package:bun
bun audit

Contributing

payba3 welcomes provider additions, method coverage, docs, tests, examples, and security hardening.

Read CONTRIBUTING.md before opening a pull request.

Security

Do not open public issues for vulnerabilities. Read SECURITY.md for supported reporting channels and safe disclosure guidance.

License

MIT. See LICENSE.