BSTPay API v1

Accept payments with BSTPay

Integrate BSTPay into your website and let your customers pay through bank transfer, mobile money, card, or BSTPay ID using a secure hosted checkout.

Simple API

Create a checkout with one API request.

Secure

Payment confirmation is server-to-server.

Multiple Methods

Give customers multiple ways to pay.

Overview

How the integration works

Your Website
     │
     │ POST /v1/checkout.php
     ▼
BSTPay API
     │
     │ returns checkout_url
     ▼
BSTPay Hosted Checkout
     │
     ├── Bank Transfer
     ├── Mobile Money
     ├── Card
     └── BSTPay ID
     │
     ▼
Payment Provider
     │
     ▼
BSTPay Webhook Processing
     │
     ├── Validate payment
     ├── Update transaction
     ├── Settle merchant
     └── Send merchant webhook
     │
     ▼
Your Website

Your website does not need direct access to BSTPay's payment-provider credentials. BSTPay handles the payment infrastructure and sends your website a normalized payment notification.

Step 1

API credentials

Your BSTPay API key authenticates requests made from your server. Never expose the API key in frontend JavaScript, HTML, mobile applications, or public repositories.

Keep your API key private

API requests should be made from your backend server.

Authorization

Authorization: Bearer bst_live_YOUR_API_KEY

Step 2

Create a checkout

When your customer is ready to pay, your backend sends a request to BSTPay.

POST https://checkout.bstpays.com/v1/checkout.php

Request

{
    "amount": 25000,
    "currency": "NGN",

    "merchant_order_reference": "ORDER-100025",

    "description": "Payment for Order #100025",

    "customer": {
        "name": "John Doe",
        "email": "customer@example.com",
        "phone": "08012345678"
    },

    "redirect_url":
        "https://example.com/payment-complete.php",

    "metadata": {
        "order_id": "100025"
    }
}

PHP example

<?php

$apiUrl =
    'https://checkout.bstpays.com/v1/checkout.php';

$apiKey =
    'bst_live_YOUR_API_KEY';

$payload = [

    'amount' => 25000,

    'currency' => 'NGN',

    'merchant_order_reference' =>
        'ORDER-100025',

    'description' =>
        'Payment for Order #100025',

    'customer' => [

        'name' =>
            'John Doe',

        'email' =>
            'customer@example.com',

        'phone' =>
            '08012345678'

    ],

    'redirect_url' =>
        'https://example.com/payment-complete.php',

    'metadata' => [

        'order_id' =>
            '100025'

    ]

];


$ch = curl_init($apiUrl);

curl_setopt_array($ch, [

    CURLOPT_POST => true,

    CURLOPT_RETURNTRANSFER => true,

    CURLOPT_POSTFIELDS =>
        json_encode($payload),

    CURLOPT_HTTPHEADER => [

        'Content-Type: application/json',

        'Accept: application/json',

        'Authorization: Bearer ' . $apiKey

    ]

]);

$response = curl_exec($ch);

$httpCode =
    curl_getinfo(
        $ch,
        CURLINFO_HTTP_CODE
    );

curl_close($ch);

$result =
    json_decode(
        $response,
        true
    );


if (
    $httpCode >= 200
    &&
    $httpCode < 300
    &&
    isset(
        $result['data']['checkout_url']
    )
) {

    header(
        'Location: '
        . $result['data']['checkout_url']
    );

    exit;
}

die(
    $result['message']
    ?? 'Unable to create payment.'
);

Checkout response

BSTPay returns a secure checkout URL. Redirect your customer to this URL.

{
    "status": "success",
    "message": "Checkout created successfully.",
    "data": {
        "checkout_reference":
            "BSTCHK-20260912180200-A12B34CD",

        "merchant_order_reference":
            "ORDER-100025",

        "amount": "25000.00",

        "currency": "NGN",

        "checkout_url":
            "https://checkout.bstpays.com/checkout.php?token=BSTCHK_...",

        "status": "pending"
    }
}

Redirect the customer

Never create your own payment form for this integration unless you are using BSTPay's API directly. The hosted checkout handles the customer payment experience.

Hosted checkout

The checkout URL opens the BSTPay payment page. Your customer can select their preferred payment method.

Example

Choose payment method

Bank Transfer

Mobile Money

Card

BSTPay ID

Payment methods

Bank Transfer

BSTPay generates a temporary payment account for the checkout. The customer transfers the exact payment amount into that account.

Mobile Money

Customers can use a supported mobile-money payment flow where available for the checkout currency.

Card

Customers can pay using supported debit or credit cards through the configured payment provider.

BSTPay ID

Customers with a BSTPay account can authorize a payment from their BSTPay balance.

Redirect handling

After payment, BSTPay can redirect the customer to the URL supplied when creating the checkout.

Important

Do not mark an order as paid solely because the customer reached your redirect URL. The redirect is a customer experience feature. Your server should rely on the BSTPay webhook or a verified status request to confirm payment.

Check payment status

You can query a checkout when you need to verify its current state.

GET /v1/checkout-status.php
GET
https://checkout.bstpays.com/v1/checkout-status.php?token=CHECKOUT_TOKEN

Response

{
    "status": "success",
    "data": {
        "checkout_reference":
            "BSTCHK-20260912180200-A12B34CD",

        "merchant_order_reference":
            "ORDER-100025",

        "amount": "25000.00",

        "currency": "NGN",

        "payment_method":
            "bank_transfer",

        "status":
            "successful",

        "amount_received":
            "25000.00",

        "provider_reference":
            "FINCRA_REFERENCE",

        "paid_at":
            "2026-09-12 18:10:23"
    }
}

Server-to-server

Webhooks

Webhooks are the recommended way to know when a payment has actually been completed.

01

Customer pays

The customer completes payment.

02

BSTPay confirms

BSTPay verifies the provider notification.

03

Your server receives event

Your order can now be marked paid.

Webhook payload

A successful payment notification looks like this:

{
    "event": "payment.successful",

    "data": {

        "checkout_reference":
            "BSTCHK-20260912180200-A12B34CD",

        "merchant_id":
            "BSTMERCHANT001",

        "merchant_order_reference":
            "ORDER-100025",

        "amount": 25000,

        "amount_received": 25000,

        "currency": "NGN",

        "payment_method":
            "bank_transfer",

        "status": "successful",

        "provider_reference":
            "FINCRA_REFERENCE",

        "customer": {

            "name": "John Doe",

            "email":
                "customer@example.com",

            "phone":
                "08012345678"

        },

        "paid_at":
            "2026-09-12 18:10:23"

    }
}

Verify the webhook signature

Every webhook request contains an X-BSTPay-Signature header.

<?php

$payload =
    file_get_contents('php://input');

$signature =
    $_SERVER['HTTP_X_BSTPAY_SIGNATURE']
    ?? '';

$webhookSecret =
    'YOUR_WEBHOOK_SECRET';


$expected =
    hash_hmac(
        'sha256',
        $payload,
        $webhookSecret
    );


if (
    !hash_equals(
        $expected,
        $signature
    )
) {

    http_response_code(401);

    exit('Invalid signature');
}


$data =
    json_decode(
        $payload,
        true
    );


if (
    ($data['event'] ?? '')
    === 'payment.successful'
) {

    $payment =
        $data['data'];

    $orderReference =
        $payment[
            'merchant_order_reference'
        ];

    /*
    | Mark the order as paid here.
    */

}

http_response_code(200);

echo json_encode([
    'status' => 'received'
]);

Complete webhook example

Create an endpoint on your website such as:

/api/bstpay-webhook.php
<?php

$payload =
    file_get_contents('php://input');

$signature =
    $_SERVER['HTTP_X_BSTPAY_SIGNATURE']
    ?? '';

$secret =
    'YOUR_WEBHOOK_SECRET';


$expected =
    hash_hmac(
        'sha256',
        $payload,
        $secret
    );


if (
    !hash_equals(
        $expected,
        $signature
    )
) {

    http_response_code(401);

    exit('Invalid signature');
}


$data =
    json_decode(
        $payload,
        true
    );


if (!is_array($data)) {

    http_response_code(400);

    exit('Invalid payload');
}


if (
    ($data['event'] ?? '')
    !== 'payment.successful'
) {

    http_response_code(200);

    exit('Event ignored');
}


$payment =
    $data['data'];


$orderReference =
    $payment[
        'merchant_order_reference'
    ];


$amount =
    $payment['amount'];


$currency =
    $payment['currency'];


$status =
    $payment['status'];


/*
|--------------------------------------------------------------------------
| Verify payment
|--------------------------------------------------------------------------
*/

if ($status !== 'successful') {

    http_response_code(200);

    exit('Payment not successful');
}


/*
|--------------------------------------------------------------------------
| IMPORTANT
|--------------------------------------------------------------------------
|
| Look up your order using $orderReference.
| Do not trust the amount alone.
|
*/


/*
|--------------------------------------------------------------------------
| Example:
|--------------------------------------------------------------------------
|
| UPDATE orders
| SET payment_status = 'paid'
| WHERE order_reference = ?
|
*/


http_response_code(200);

echo json_encode([
    'status' => 'received'
]);

Security requirements

Keep API keys on your server

Never place a secret API key inside frontend JavaScript.

Verify webhook signatures

Always verify X-BSTPay-Signature before processing a payment notification.

Use order references

Match the webhook's merchant_order_reference against an order in your own database.

Make webhook processing idempotent

The same notification may be delivered more than once. Your order should only be marked paid once.

Use HTTPS

Your redirect URL and webhook endpoint should use HTTPS.

Testing your integration

Before going live, test the complete lifecycle.

Test Expected Result
Create checkout BSTPay returns checkout_url.
Open checkout Customer sees available payment methods.
Make payment Payment provider confirms payment.
Receive webhook Your endpoint receives payment.successful.
Verify signature Signature matches your webhook secret.
Mark order paid Your order is updated once.

Before going live

Production checklist

Store API keys securely.
Configure your webhook URL.
Store your webhook secret securely.
Verify webhook signatures.
Implement idempotent order updates.
Use HTTPS for all endpoints.
Test payment success and failure.
Confirm your production webhook.