PPaye Developer Docs

Integration & API Reference

Paye is a unified payment gateway abstraction layer. Instead of writing separate integrations for Paystack, Flutterwave, or other regional gateways, you build once against Paye's interface. Paye handles routing, provider failovers, record persistence, and webhook normalization under the hood.

Ways to Use Paye

Paye Dashboard (No-Code)

A visual interface for business operators. Manage your projects, configure provider secret/public keys, view transaction analytics, design billing plans, issue refunds, and initiate visual payouts to Nigeria banks with no programming required.

Paye API & SDK (Developers)

Programmatic libraries to embed checkouts directly inside React/Next.js/mobile applications, initiate automated vendor payout pipelines on your servers, sync sub-merchants, and automate multi-provider subscription billing workflows.

The Paye Promise: You never need to know which payment provider is running underneath. You configure your providers once in the dashboard, and from that point on, you interact only with the Paye API/SDK. If you switch from Paystack to Flutterwave tomorrow, your code stays completely untouched.

Authentication & Multi-Project Scoping

Every resource in Paye is isolated inside a **Project**. A merchant can create multiple projects (e.g. staging vs production, or separate business lines).

Server-to-Server Private Endpoints

Requires your project-specific API key, passed in the HTTP Header:

X-Paye-API-Key: paye_test_merchant_api_key_xxxxx
Browser-Safe Public SDK Client

Requires your project-specific Public ID, embedded directly into the JS SDK source URL:

<script src="https://paye-1akj.onrender.com/sdk/your_merchant_public_id.js"></script>

Configuring Payment Providers

Paye integrates seamlessly with external payment gateways like Paystack and Flutterwave. Instead of writing custom integration code for each provider, you simply configure them once in the Paye dashboard and let Paye handle the rest.

Paystack Setup

To connect Paystack, you need to provide your API keys from the Paystack Dashboard (Settings > API Keys & Webhooks).

  • Secret Key: Used by Paye backend to verify transactions, process refunds, and manage subscriptions.
  • Public Key: Used by the Paye JS SDK to securely initialize the Paystack inline checkout popup.

Flutterwave Setup

To connect Flutterwave, retrieve your API keys from the Flutterwave Dashboard (Settings > API).

  • Secret Key: Used by Paye to securely communicate with Flutterwave API for transaction verification and more.
  • Public Key: Used by the Paye JS SDK to launch the Flutterwave standard checkout inline modal.
  • Webhook Secret Hash: To receive automatic transaction updates from Flutterwave, you must configure a Webhook Secret Hash on your Flutterwave Dashboard. Important: Paye requires you to set your Webhook Secret Hash to exactly match your Flutterwave Secret Key.
Why does Paye need these? Providing your API keys allows Paye to act as a secure proxy and abstraction layer. Your secret keys are encrypted using bank-grade AES-256-GCM before being stored in the database.

JavaScript SDK - One-Time Payments

Accept one-time checkouts programmatically. Include the script tag on your page and call the checkout loader:

window.Paye.pay({
  type: "payment", // default
  amount: 7500,
  email: "buyer@example.com",
  currency: "NGN",
  onSuccess: function(reference) {
    console.log("Payment successful! Reference: " + reference);
  },
  onFailure: function(error) {
    console.error("Payment failed: " + error);
  }
});

JavaScript SDK - Subscription Checkouts

Start recurring billing for a plan. Set type: "subscription" and provide your plan UUID. The SDK automatically performs the initial card auth charge, updates the database via webhooks, and programmatically establishes the active subscription:

window.Paye.pay({
  type: "subscription",
  planId: "8b7fae01-1b9a-4121-aa05-e3d179d679b4",
  email: "buyer@example.com",
  onSuccess: function(subscription) {
    console.log("Subscription created successfully! Code: " + subscription.subscription_code);
  },
  onFailure: function(error) {
    console.error("Subscription failed: " + error);
  }
});
How Paye-Managed Subscriptions Work under the hood:
  • Initial Authorization Charge: The JS SDK initializes a one-time transaction using either Paystack or Flutterwave. Once the customer completes checkout, Paye captures the payment authorization details (e.g. authorization_code for Paystack, or a card token for Flutterwave) securely.
  • Subscription Registration: Paye creates a local subscription record linked to the customer email and selected plan, calculating the NextBillingDateautomatically based on the plan's interval (daily, weekly, monthly, annually).
  • Automated Billing (Cron Engine):A background cron worker iterates through active subscriptions that are due for billing. It dynamically retrieves the stored authorization details and charges the customer using the provider's tokenized charge API.
  • Provider Agnostic:Subscriptions are completely controlled inside Paye. If you deactivate Paystack and activate Flutterwave, Paye will automatically route the next recurring billing attempt using Flutterwave's tokenized charge process, ensuring no disruption to your recurring revenue.

Declarative HTML Checkouts (No-JS Trigger)

Alternatively, render payment buttons declaratively using HTML tags. Link to form fields or specify static attributes. The script will intercept click handlers and configure the popups:

<div data-paye-checkout
     data-type="subscription"
     data-plan-id="PLAN_UUID_HERE"
     data-email="customer@email.com"
     data-button-text="Subscribe Now">
</div>

Payments API Reference

POST/sdk/transactions/initialize

Initialize checkout page sessions. Called under-the-hood by the JavaScript SDK.

// POST /api/v1/sdk/transactions/initialize
// Request Body:
{
  "publicId": "paye_pub_test_12345",
  "amount": 250.00,
  "email": "customer@test.com",
  "currency": "NGN"
}

// Response Body (200 OK):
{
  "status": true,
  "message": "Transaction initialized successfully",
  "data": {
    "reference": "paye_ref_9999",
    "authorization_url": "https://checkout.paystack.com/abcdef",
    "access_code": "access_code_12345"
  }
}

GET/transactions/verify/:reference

Verify the status of a specific payment session. Requires private API Key authentication.

// GET /api/v1/transactions/verify/:reference
// Headers: X-Paye-API-Key: paye_test_key_xxxx

// Response Body (200 OK):
{
  "status": true,
  "message": "Transaction verified successfully",
  "data": {
    "reference": "paye_ref_9999",
    "status": "success",
    "amount": 250.00,
    "currency": "NGN",
    "provider": "paystack"
  }
}

POST/refund

Process a partial or full refund on a transaction. Original transaction reference must belong to the active project context. Requires private API Key authentication.

// POST /api/v1/refund
// Headers: X-Paye-API-Key: paye_test_key_xxxx
// Request Body:
{
  "transaction_reference": "paye_ref_9999",
  "amount": 100.00, // Optional: defaults to full refund if omitted
  "currency": "NGN",
  "customer_note": "Returning damaged goods",
  "merchant_note": "Internal refund authorization #45"
}

// Response Body (200 OK):
{
  "status": true,
  "message": "Refund processed successfully",
  "data": {
    "status": "success",
    "transaction_ref": "paye_ref_9999",
    "amount": 100.00,
    "currency": "NGN",
    "provider": "paystack"
  }
}

Transfers & Bank Payouts API

POST/recipients

Create and save a transfer recipient. Scoped to the project. Requires private API Key authentication.

// POST /api/v1/recipients
// Headers: X-Paye-API-Key: paye_test_key_xxxx
// Request Body:
{
  "name": "Jane Doe",
  "account_number": "0123456789",
  "bank_code": "058",
  "currency": "NGN"
}

// Response Body (200 OK):
{
  "status": true,
  "message": "Transfer recipient created successfully",
  "data": {
    "status": true,
    "message": "Recipient created",
    "recipient_code": "RCP_22222",
    "provider": "paystack"
  }
}

POST/transfers

Initiate a bank transfer. Supports explicit routing via the optional providerfield. If omitted, uses the project's default provider. If the selected provider fails, Paye automatically falls back to alternative active configs. Can resolve account names dynamically. Requires private API Key authentication.

// POST /api/v1/transfers
// Headers: X-Paye-API-Key: paye_test_key_xxxx
// Request Body:
{
  "amount": 50000,
  "recipientAccount": "0123456789", // Optional if recipient_code is specified
  "bankCode": "058",             // Optional if recipient_code is specified
  "recipient_code": "RCP_22222",   // Optional if account details are specified
  "reason": "Contractor Vendor Payment",
  "currency": "NGN",
  "provider": "paystack"           // Optional preferred provider
}

// Response Body (200 OK):
{
  "status": true,
  "message": "Transfer initiated successfully",
  "data": {
    "status": "success",
    "transfer_code": "TRF_33333",
    "reference": "ref_9999",
    "amount": 50000,
    "currency": "NGN",
    "provider": "paystack"
  }
}

Billing, Plans & Subscriptions API

GET/plans

List all created billing plans scoped to the current project context. Requires private API Key authentication.

// GET /api/v1/plans
// Headers: X-Paye-API-Key: paye_test_key_xxxx

// Response Body (200 OK):
{
  "status": true,
  "message": "Plans retrieved successfully",
  "data": [
    {
      "id": "8b7fae01-1b9a-4121-aa05-e3d179d679b4",
      "created_at": "2026-06-06T10:41:56Z",
      "plan_code": "PLN_44444",
      "name": "Gold Weekly",
      "amount": 5000.00,
      "interval": "weekly",
      "currency": "NGN",
      "description": "Weekly Premium Subscription",
      "provider": "paystack"
    }
  ]
}

POST/subscriptions

Create a recurring customer subscription using a saved authorization code (automatically gathered from a previous success checkout charge event on file). Requires private API Key authentication.

// POST /api/v1/subscriptions
// Headers: X-Paye-API-Key: paye_test_key_xxxx
// Request Body:
{
  "customer_email": "subscriber@example.com",
  "plan_code": "PLN_44444"
}

// Response Body (200 OK):
{
  "status": true,
  "message": "Subscription created successfully",
  "data": {
    "status": "active",
    "subscription_code": "SUB_55555",
    "customer_email": "subscriber@example.com",
    "plan_code": "PLN_44444",
    "provider": "paystack"
  }
}

Need Help?

If you have any questions or want to integrate Paye into a specific website builder (like WordPress or Webflow), contact our hackathon support team inside your Slack/Discord or email us at support@paye.ng.