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.

Integration 02

Inline integration

Inline integration allows you to keep your customer on your website while the secure BSTPay checkout opens inside an overlay. The actual payment interface remains hosted by BSTPay.

Pay without leaving your website

Your backend creates the checkout and your frontend opens the secure checkout inside a BSTPay payment modal.

Your Website
      │
      │ Your backend creates checkout
      ▼
 BSTPay API
      │
      │ checkout_url / token
      ▼
 BSTPay JavaScript SDK
      │
      │ opens secure iframe
      ▼
┌──────────────────────────────┐
│       BSTPay Checkout        │
│                              │
│  Bank Transfer               │
│  Card                        │
│  Mobile Money                │
│  BSTPay ID                   │
│                              │
└──────────────────────────────┘
      │
      │ payment completed
      ▼
 postMessage event
      │
      ▼
Your Website
      │
      ▼
Webhook confirmation

Do not put your secret key in JavaScript

Your server must create the checkout. The browser receives only the checkout URL/token required to open that specific transaction.

Integration 01

Standard integration

Standard integration redirects your customer from your website to the secure BSTPay hosted checkout page. This is the simplest and recommended integration for most merchants.

1. Create checkout

Your backend sends the payment information to BSTPay using your secret API key.

2. Receive checkout URL

BSTPay returns a unique checkout URL for the transaction.

3. Redirect customer

Redirect the customer to BSTPay to complete payment.

Recommended

PHP server integration

Secure
<?php

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

$apiKey =
    'bst_live_YOUR_SECRET_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

    ],

    CURLOPT_TIMEOUT =>
        30

]);


$response =
    curl_exec($ch);


$httpCode =
    curl_getinfo(
        $ch,
        CURLINFO_HTTP_CODE
    );


$curlError =
    curl_error($ch);


curl_close($ch);


if ($response === false) {

    die(
        'BSTPay connection failed: '
        . $curlError
    );

}


$result =
    json_decode(
        $response,
        true
    );


if (
    $httpCode >= 200
    &&
    $httpCode < 300
    &&
    ($result['status'] ?? '')
        === 'success'
    &&
    !empty(
        $result['data']['checkout_url']
    )
) {

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

    exit;

}


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

Secret key stays on your server

Never put the BSTPay secret API key in browser JavaScript. The browser should only receive the checkout URL or checkout token generated by your backend.

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 an eligible BSTPay account can authorize a payment through BSTPay, subject to the available payment method, currency, account status and applicable transaction limits.

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.

Inline SDK

Load the BSTPay JavaScript SDK on your payment page and provide it with the checkout URL returned by your server.

1. Load the SDK

<script
src="https://checkout.bstpays.com/js/bstpay.js">
</script>

2. Create the checkout on your server

Your backend should call the normal BSTPay checkout API. Never call the API using your secret key directly from browser JavaScript.

3. Open the checkout

<button
    type="button"
    onclick="startBSTPay()"
    class="px-6 py-3 rounded-xl bg-blue-600 text-white font-bold">

    Pay with BSTPay

</button>


<script>

function startBSTPay()
{

    BSTPay.open({

        checkoutUrl:
            '<?php echo $checkoutUrl; ?>',

        onClose:
            function () {

                console.log(
                    'BSTPay checkout closed'
                );

            }

    });

}

</script>

Payment success

window.BSTPayOnSuccess =
    function (payment) {

        console.log(
            'Payment successful:',
            payment
        );


        /*
         * Do not rely only on this
         * browser event to fulfil
         * the order.
         *
         * Confirm the payment on
         * your backend using the
         * BSTPay webhook or status API.
         */


        window.location.href =
            '/payment-success.php';

    };

Recommended

Use the inline event for the customer interface, but use the BSTPay webhook or server-side status API as the authoritative payment confirmation.