Technical Support
For API integration help:
- Email: canpaybnpl@gmail.com
- Response Time: 24–48 hours
- Hours: Monday–Friday, 9:00AM – 6:00PM GMT
Include your Merchant ID and detailed error descriptions for faster resolution.
Contact Support
Connect your business to CanPay's secure payment ecosystem for effortless customer transactions.
Integrate CanPay BNPL flexible payment checkout into your application with our comprehensive RESTful API. Accept payments from our customers with enterprise-grade security.
Get started in minutes with our simple REST API
High-grade security with HMAC signature verification
Works with any programming language or framework
Merchant API uses API keys to authenticate requests. You can obtain your credentials from your merchant portal account.
Merchant API supports both sandbox (testing) and production environments. Always test in sandbox first before going live.
Use for: Development, testing, integration
X-Environment: sandbox
Credentials: Use test_* prefixed API keys
Use for: Live payments, real money
X-Environment: production
Credentials: Use production API keys (no prefix)
| Credential | Header | Description | Location |
|---|---|---|---|
Merchant ID |
X-Merchant-Key |
Your unique merchant identifier | Merchant Dashboard > Account > Configuration |
API Key |
X-API-Key |
API authentication key | Merchant Dashboard > Account > Configuration |
Client Secret |
- | Used for webhook signature verification | Merchant Dashboard > Account > Configuration |
| Production API Key | X-API-Key |
Production API key (no prefix) | Merchant Dashboard > Account > Configuration > Production Mode |
| Production Merchant ID | X-Merchant-Key |
Production merchant identifier (no prefix) | Merchant Dashboard > Account > Configuration > Production Mode |
Get up and running with Merchant API in just a few steps:
/api/v1/initiate-paymentTry Merchant API endpoints directly in your browser
Create a new payment request and get a secure checkout URL for your customer. This endpoint works in both sandbox and production environments based on your X-Environment header.
/api/v1/initiate-payment
| Header | Value | Required | Description |
|---|---|---|---|
Content-Type |
application/json |
✅ | Request content type |
X-Environment |
sandbox | production |
✅ | API environment mode |
X-Merchant-Key |
{merchant_key} |
✅ | Your Merchant ID (sandbox: test_ prefix, production: no prefix) |
X-API-Key |
{api_key} |
✅ | Your API Key (sandbox: test_ prefix, production: no prefix) |
| Parameter | Type | Required | Description |
|---|---|---|---|
payment_amount |
number | ✅ | Payment amount (minimum 100.00) |
currency_code |
string | ✅ | 3-letter currency code (GHC, GHS) |
ref_trx |
string | ✅ | Your unique transaction reference |
description |
string | ❌ | Payment description |
callback_url |
string | ✅ | Redirect URL |
curl -X POST "https://pay.canpaybnpl.com/api/v1/initiate-payment" \
-H "Content-Type: application/json" \
-H "X-Environment: {environment}" \
-H "X-Merchant-Key: {merchant_key}" \
-H "X-API-Key: {api_key}" \
-d '{"payment_amount": 250.00, "currency_code": "GHC", "ref_trx": "ORDER_12345", "description": "Premium Subscription", "callback_url": "https://yoursite.com/payment/callback_url"}'
<?php
use App\Enums\EnvironmentMode;
use Illuminate\Support\Facades\Http;
class PaymentInitiator
{
private $environment;
private $merchantKey;
private $apiKey;
private $baseUrl = 'https://pay.canpaybnpl.com/api/v1';
public function __construct(EnvironmentMode $environment, $merchantKey, $apiKey)
{
$this->environment = $environment;
$this->merchantKey = $merchantKey;
$this->apiKey = $apiKey;
}
// Factory methods for easy configuration
public static function sandbox($testMerchantKey, $testApiKey): self
{
return new self(EnvironmentMode::SANDBOX, $testMerchantKey, $testApiKey);
}
public static function production($merchantKey, $apiKey): self
{
return new self(EnvironmentMode::PRODUCTION, $merchantKey, $apiKey);
}
public function initiatePayment($paymentData)
{
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'X-Environment' => $this->environment->value,
'X-Merchant-Key' => $this->merchantKey,
'X-API-Key' => $this->apiKey,
])->post("{$this->baseUrl}/initiate-payment", $paymentData);
if ($response->successful()) {
$data = $response->json();
if ($data['success']) {
return ['success' => true, 'data' => $data];
}
return ['success' => false, 'status' => $data['status'], 'message' => $data['message'] ?? 'Payment initiation failed'];
}
return ['success' => false, 'error' => 'API request failed'];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
}
// Usage: Choose appropriate factory method based on your environment
$initiator = PaymentInitiator::sandbox('test_merchant_key', 'test_api_key'); // For testing
// $initiator = PaymentInitiator::production('merchant_key', 'api_key'); // For production
$paymentData = [
'payment_amount' => 250.00,
'currency_code' => 'GHS',
'ref_trx' => 'ORDER_12345',
'description' => 'Premium Subscription',
'callback_url' => 'https://yoursite.com/payment/callback_url',
];
$result = $initiator->initiatePayment($paymentData);
const axios = require('axios');
const EnvironmentMode = {
SANDBOX: 'sandbox',
PRODUCTION: 'production'
};
class PaymentInitiator {
constructor(environment, merchantKey, apiKey) {
this.environment = environment;
this.merchantKey = merchantKey;
this.apiKey = apiKey;
this.baseUrl = 'https://pay.canpaybnpl.com/api/v1';
}
// Factory methods
static sandbox(testMerchantKey, testApiKey) {
return new PaymentInitiator(EnvironmentMode.SANDBOX, testMerchantKey, testApiKey);
}
static production(merchantKey, apiKey) {
return new PaymentInitiator(EnvironmentMode.PRODUCTION, merchantKey, apiKey);
}
async initiatePayment(paymentData) {
try {
const response = await axios.post(`${this.baseUrl}/initiate-payment`, paymentData, {
headers: {
'Content-Type': 'application/json',
'X-Environment': this.environment,
'X-Merchant-Key': this.merchantKey,
'X-API-Key': this.apiKey
}
});
const data = response.data;
if (data.success) {
return { success: true, data };
}
return {
success: false,
status: data.status,
message: data.message || 'Payment initiation failed'
};
} catch (error) {
if (error.response) {
return {
success: false,
error: error.response.data.error || 'API request failed'
};
}
return { success: false, error: error.message };
}
}
}
// Usage: Choose appropriate factory method based on your environment
const initiator = PaymentInitiator.sandbox('test_merchant_key', 'test_api_key'); // For testing
// const initiator = PaymentInitiator.production('merchant_key', 'api_key'); // For production
const paymentData = {
payment_amount: 250.00,
currency_code: 'GHC',
ref_trx: 'ORDER_12345',
description: 'Premium Subscription',
callback_url: 'https://yoursite.com/payment/callback_url',
};
initiator.initiatePayment(paymentData)
.then(result => console.log(result))
.catch(error => console.error(error));
import requests
import logging
from enum import Enum
class EnvironmentMode(Enum):
SANDBOX = 'sandbox'
PRODUCTION = 'production'
class PaymentInitiator:
def __init__(self, environment, merchant_key, api_key):
self.environment = environment
self.merchant_key = merchant_key
self.api_key = api_key
self.base_url = 'https://pay.canpaybnpl.com/api/v1'
@classmethod
def sandbox(cls, test_merchant_key, test_api_key):
return cls(EnvironmentMode.SANDBOX, test_merchant_key, test_api_key)
@classmethod
def production(cls, merchant_key, api_key):
return cls(EnvironmentMode.PRODUCTION, merchant_key, api_key)
def initiate_payment(self, payment_data):
try:
headers = {
'Content-Type': 'application/json',
'X-Environment': self.environment.value,
'X-Merchant-Key': self.merchant_key,
'X-API-Key': self.api_key
}
response = requests.post(
f"{self.base_url}/initiate-payment",
headers=headers,
json=payment_data,
timeout=30
)
if response.status_code == 200:
data = response.json()
if data['success']:
return {'success': True, 'data': data}
return {
'success': False,
'status': data['status'],
'message': data.get('message', 'Payment initiation failed')
}
return {'success': False, 'error': f'HTTP {response.status_code}'}
except requests.RequestException as e:
return {'success': False, 'error': str(e)}
# Usage: Choose appropriate factory method based on your environment
initiator = PaymentInitiator.sandbox('test_merchant_key', 'test_api_key') # For testing
# initiator = PaymentInitiator.production('merchant_key', 'api_key') # For production
payment_data = {
'payment_amount': 250.00,
'currency_code': 'GHC',
'ref_trx': 'ORDER_12345',
'description': 'Premium Subscription',
'callback_url': 'https://yoursite.com/payment/callback_url'
}
result = initiator.initiate_payment(payment_data)
print(result)
{
"payment_url": "https://pay.canpaybnpl.com/api/v1/payment/checkout?expires=1753724376&token=AmQvJdGIdGUVJUUMayJZZreBv2UcTyIHclk9Ps1s1pZhLpVlIqIBVPqGTRKQ3NUSehyM3qRUIf69IhLbNfJ1JqiMxlxNrnn22lNz1N01hZQn65r5VZnvhWmQPxQO8UX6rE4yfRUvT6bHdqLj7UDJhRPYRFSgCsG1b86sxSdKTZNOVJdWV5z8L6a5pNMZ2KlpG5e7bYa&signature=e9q7ea91456dcc167e7d498ea486f923570821957be8881566186655950f364",
"info": {
"ref_trx": "TXNT4AQFESTAG4F",
"description": "Order #1234",
"callback_url": "https://merchant.com/callback_url",
"merchant_id": 1,
"merchant_name": "Xanthus Wiggins",
"amount": 200,
"currency_code": "GHC",
"environment": "production",
"is_sandbox": false
}
}
{
"success": false,
"message": "Validation failed",
"errors": {
"payment_amount": ["The payment amount field is required."],
"currency_code": ["The currency code field is required."]
}
}
Verify the status of a payment using the transaction ID returned from the payment initiation.
/api/v1/verify-payment/{trxId}
| Header | Value | Required | Description |
|---|---|---|---|
Accept |
application/json |
✅ | Request content type |
X-Environment |
sandbox | production |
✅ | API environment mode |
X-Merchant-Key |
{merchant_key} |
✅ | Your Merchant ID (sandbox: test_ prefix, production: no prefix) |
X-API-Key |
{api_key} |
✅ | Your API Key (sandbox: test_ prefix, production: no prefix) |
| Parameter | Type | Required | Description |
|---|---|---|---|
trxId |
string | ✅ | Merchant transaction ID (e.g., TXNQ5V8K2L9N3XM1) |
curl -X GET "https://pay.canpaybnpl.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
-H "Accept: application/json" \
-H "X-Environment: {environment}" \
-H "X-Merchant-Key: {merchant_key}" \
-H "X-API-Key: {api_key}"
<?php
use App\Enums\EnvironmentMode;
use Illuminate\Support\Facades\Http;
class PaymentVerifier
{
private $environment;
private $merchantKey;
private $apiKey;
private $baseUrl = 'https://pay.canpaybnpl.com/api/v1';
public function __construct(EnvironmentMode $environment, $merchantKey, $apiKey)
{
$this->environment = $environment;
$this->merchantKey = $merchantKey;
$this->apiKey = $apiKey;
}
// Factory methods for easy configuration
public static function sandbox($testMerchantKey, $testApiKey): self
{
return new self(EnvironmentMode::SANDBOX, $testMerchantKey, $testApiKey);
}
public static function production($merchantKey, $apiKey): self
{
return new self(EnvironmentMode::PRODUCTION, $merchantKey, $apiKey);
}
public function verifyPayment($trxId)
{
try {
$response = Http::withHeaders([
'Accept' => 'application/json',
'X-Environment' => $this->environment->value,
'X-Merchant-Key' => $this->merchantKey,
'X-API-Key' => $this->apiKey,
])->get("{$this->baseUrl}/verify-payment/{$trxId}");
if ($response->successful()) {
$data = $response->json();
if ($data['status'] === 'success') {
// Payment completed successfully
$this->fulfillOrder($data);
return ['success' => true, 'data' => $data];
}
return ['success' => false, 'status' => $data['status'], 'message' => $data['message'] ?? 'Payment not completed'];
}
return ['success' => false, 'error' => 'API request failed'];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
private function fulfillOrder($paymentData)
{
// Your order fulfillment logic here
logger('Payment verified successfully', $paymentData);
}
}
// Usage: Choose appropriate factory method based on your environment
$verifier = PaymentVerifier::sandbox('test_merchant_key', 'test_api_key'); // For testing
// $verifier = PaymentVerifier::production('merchant_key', 'api_key'); // For production
$result = $verifier->verifyPayment('TXNQ5V8K2L9N3XM1');
const axios = require('axios');
const EnvironmentMode = {
SANDBOX: 'sandbox',
PRODUCTION: 'production'
};
class PaymentVerifier {
constructor(environment, merchantKey, apiKey) {
this.environment = environment;
this.merchantKey = merchantKey;
this.apiKey = apiKey;
this.baseUrl = 'https://pay.canpaybnpl.com/api/v1';
}
// Factory methods
static sandbox(testMerchantKey, testApiKey) {
return new PaymentVerifier(EnvironmentMode.SANDBOX, testMerchantKey, testApiKey);
}
static production(merchantKey, apiKey) {
return new PaymentVerifier(EnvironmentMode.PRODUCTION, merchantKey, apiKey);
}
async verifyPayment(trxId) {
try {
const response = await axios.get(`${this.baseUrl}/verify-payment/${trxId}`, {
headers: {
'Accept': 'application/json',
'X-Environment': this.environment,
'X-Merchant-Key': this.merchantKey,
'X-API-Key': this.apiKey
}
});
const data = response.data;
if (data.status === 'success') {
// Payment completed successfully
await this.fulfillOrder(data);
return { success: true, data };
}
return {
success: false,
status: data.status,
message: data.message || 'Payment not completed'
};
} catch (error) {
if (error.response) {
return {
success: false,
error: error.response.data.error || 'API request failed'
};
}
return { success: false, error: error.message };
}
}
async fulfillOrder(paymentData) {
// Your order fulfillment logic here
console.log('Payment verified successfully:', paymentData);
}
}
// Usage: Choose appropriate factory method based on your environment
const verifier = PaymentVerifier.sandbox('test_merchant_key', 'test_api_key'); // For testing
// const verifier = PaymentVerifier.production('merchant_key', 'api_key'); // For production
verifier.verifyPayment('TXNQ5V8K2L9N3XM1')
.then(result => console.log(result))
.catch(error => console.error(error));
import requests
import logging
from enum import Enum
class EnvironmentMode(Enum):
SANDBOX = 'sandbox'
PRODUCTION = 'production'
class PaymentVerifier:
def __init__(self, environment, merchant_key, api_key):
self.environment = environment
self.merchant_key = merchant_key
self.api_key = api_key
self.base_url = 'https://pay.canpaybnpl.com/api/v1'
@classmethod
def sandbox(cls, test_merchant_key, test_api_key):
return cls(EnvironmentMode.SANDBOX, test_merchant_key, test_api_key)
@classmethod
def production(cls, merchant_key, api_key):
return cls(EnvironmentMode.PRODUCTION, merchant_key, api_key)
def verify_payment(self, trx_id):
try:
headers = {
'Accept': 'application/json',
'X-Environment': self.environment.value,
'X-Merchant-Key': self.merchant_key,
'X-API-Key': self.api_key
}
response = requests.get(
f"{self.base_url}/verify-payment/{trx_id}",
headers=headers,
timeout=30
)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
# Payment completed successfully
self.fulfill_order(data)
return {'success': True, 'data': data}
return {
'success': False,
'status': data['status'],
'message': data.get('message', 'Payment not completed')
}
return {'success': False, 'error': f'HTTP {response.status_code}'}
except requests.RequestException as e:
return {'success': False, 'error': str(e)}
def fulfill_order(self, payment_data):
"""Your order fulfillment logic here"""
logging.info(f"Payment verified successfully: {payment_data}")
# Usage: Choose appropriate factory method based on your environment
verifier = PaymentVerifier.sandbox('test_merchant_key', 'test_api_key') # For testing
# verifier = PaymentVerifier.production('merchant_key', 'api_key') # For production
result = verifier.verify_payment('TXNQ5V8K2L9N3XM1')
print(result)
{
"status": "success",
"trx_id": "TXNQ5V8K2L9N3XM1",
"amount": 237.5,
"fee": 12.5,
"currency": "GHC",
"net_amount": 237.5,
"customer": {
"name": "John Doe",
"email": "john@example.com"
},
"description": "Premium Subscription Payment",
"created_at": "2024-01-15T10:30:00.000000Z",
"updated_at": "2024-01-15T10:35:45.000000Z"
}
{
"status": "failed",
"trx_id": "TXNQ5V8K2L9N3XM1",
"message": "Payment failed or canceled."
}
{
"status": "pending",
"trx_id": "TXNQ5V8K2L9N3XM1",
"message": "Payment is still pending."
}
| Status | Description | Action Required |
|---|---|---|
pending |
Payment is still processing | Wait until transaction completes |
completed |
Payment was successful | Fulfill order/service |
failed |
Payment failed | Handle failed payment |
cancelled |
Payment was cancelled by user | Handle cancellation |
expired |
Payment session expired | Create new payment |
Complete integration examples for popular platforms and frameworks.
<?php
// Laravel Integration Service
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Exception;
class CanPayService
{
private string $baseUrl;
private string $merchantKey;
private string $apiKey;
private string $environment;
public function __construct()
{
$this->baseUrl = config('canpaybnpl.base_url');
$this->merchantKey = config('canpaybnpl.merchant_key');
$this->apiKey = config('canpaybnpl.api_key');
$this->environment = config('canpaybnpl.environment'); // 'sandbox' or 'production'
}
public function initiatePayment(array $paymentData): array
{
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'X-Environment' => $this->environment,
'X-Merchant-Key' => $this->merchantKey,
'X-API-Key' => $this->apiKey,
])->post("{$this->baseUrl}/api/v1/initiate-payment", $paymentData);
if ($response->successful()) {
return $response->json();
}
throw new Exception('Payment initiation failed');
} catch (Exception $e) {
throw new Exception('CanPayBNPL API Error: ' . $e->getMessage());
}
}
public function verifyPayment(string $transactionId): array
{
try {
$response = Http::withHeaders([
'Accept' => 'application/json',
'X-Environment' => $this->environment,
'X-Merchant-Key' => $this->merchantKey,
'X-API-Key' => $this->apiKey,
])->get("{$this->baseUrl}/api/v1/verify-payment/{$transactionId}");
if ($response->successful()) {
return $response->json();
}
throw new Exception('Payment verification failed');
} catch (Exception $e) {
throw new Exception('CanPayBNPL API Error: ' . $e->getMessage());
}
}
}
// Configuration (config/canpaybnpl.php)
return [
'base_url' => env('CANPAYBNPL_BASE_URL', 'https://pay.canpaybnpl.com'),
'environment' => env('CANPAYBNPL_ENVIRONMENT', 'sandbox'), // sandbox or production
'merchant_key' => env('CANPAYBNPL_MERCHANT_KEY'), // Use appropriate prefix
'api_key' => env('CANPAYBNPL_API_KEY'), // Use appropriate prefix
];
// Usage in Controller
class PaymentController extends Controller
{
public function initiatePayment(Request $request, CanPayService $canpaybnpl)
{
$paymentData = [
'payment_amount' => $request->amount,
'currency_code' => 'GHC',
'ref_trx' => 'ORDER_' . time(),
'description' => $request->description,
'callback_url' => route('payment.callback_url'),
];
try {
$result = $canpaybnpl->initiatePayment($paymentData);
return redirect($result['payment_url']);
} catch (Exception $e) {
return back()->withErrors(['error' => $e->getMessage()]);
}
}
}
// Node.js Integration Service
const axios = require('axios');
class CanPayService {
constructor() {
this.baseUrl = process.env.CANPAYBNPL_BASE_URL || 'https://pay.canpaybnpl.com';
this.environment = process.env.CANPAYBNPL_ENVIRONMENT || 'sandbox'; // sandbox or production
this.merchantKey = process.env.CANPAYBNPL_MERCHANT_KEY; // Use appropriate prefix
this.apiKey = process.env.CANPAYBNPL_API_KEY; // Use appropriate prefix
}
async initiatePayment(paymentData) {
try {
const response = await axios.post(`${this.baseUrl}/api/v1/initiate-payment`, paymentData, {
headers: {
'Content-Type': 'application/json',
'X-Environment': this.environment,
'X-Merchant-Key': this.merchantKey,
'X-API-Key': this.apiKey
}
});
return response.data;
} catch (error) {
throw new Error(`CanPay BNPL API Error: ${error.message}`);
}
}
async verifyPayment(transactionId) {
try {
const response = await axios.get(`${this.baseUrl}/api/v1/verify-payment/${transactionId}`, {
headers: {
'Accept': 'application/json',
'X-Environment': this.environment,
'X-Merchant-Key': this.merchantKey,
'X-API-Key': this.apiKey
}
});
return response.data;
} catch (error) {
throw new Error(`CanPay BNPL API Error: ${error.message}`);
}
}
}
// Express.js Route Example
const express = require('express');
const app = express();
const canpaybnpl = new CanPayService();
app.post('/initiate-payment', async (req, res) => {
const paymentData = {
payment_amount: req.body.amount,
currency_code: 'GHC',
ref_trx: `ORDER_${Date.now()}`,
description: req.body.description,
callback_url: `${req.protocol}://${req.get('host')}/payment/callback_url`,
};
try {
const result = await canpaybnpl.initiatePayment(paymentData);
res.redirect(result.payment_url);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = CanPayService;
# Python/Django Integration Service
import os
import requests
from django.conf import settings
class CanPayService:
def __init__(self):
self.base_url = getattr(settings, 'CANPAYBNPL_BASE_URL', 'https://pay.canpaybnpl.com')
self.environment = getattr(settings, 'CANPAYBNPL_ENVIRONMENT', 'sandbox') # sandbox or production
self.merchant_key = getattr(settings, 'CANPAYBNPL_MERCHANT_KEY') # Use appropriate prefix
self.api_key = getattr(settings, 'CANPAYBNPL_API_KEY') # Use appropriate prefix
def initiate_payment(self, payment_data):
try:
headers = {
'Content-Type': 'application/json',
'X-Environment': self.environment,
'X-Merchant-Key': self.merchant_key,
'X-API-Key': self.api_key
}
response = requests.post(
f"{self.base_url}/api/v1/initiate-payment",
headers=headers,
json=payment_data,
timeout=30
)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
raise Exception(f'CanPay BNPL API Error: {str(e)}')
def verify_payment(self, transaction_id):
try:
headers = {
'Accept': 'application/json',
'X-Environment': self.environment,
'X-Merchant-Key': self.merchant_key,
'X-API-Key': self.api_key
}
response = requests.get(
f"{self.base_url}/api/v1/verify-payment/{transaction_id}",
headers=headers,
timeout=30
)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
raise Exception(f'CanPay BNPL API Error: {str(e)}')
# Django Settings Configuration
CANPAYBNPL_BASE_URL = 'https://pay.canpaybnpl.com'
CANPAYBNPL_ENVIRONMENT = 'sandbox' # Change to 'production' for live
CANPAYBNPL_MERCHANT_KEY = os.environ.get('CANPAYBNPL_MERCHANT_KEY') # Use appropriate prefix
CANPAYBNPL_API_KEY = os.environ.get('CANPAYBNPL_API_KEY') # Use appropriate prefix
# Django View Example
from django.shortcuts import redirect
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
canpaybnpl = CanPayService()
@csrf_exempt
def initiate_payment(request):
if request.method == 'POST':
data = json.loads(request.body)
payment_data = {
'payment_amount': data['amount'],
'currency_code': 'GHS',
'ref_trx': f'ORDER_{int(time.time())}',
'description': data['description'],
'callback_url': request.build_absolute_uri('/payment/callback_url/'),
}
try:
result = canpaybnpl.initiate_payment(payment_data)
return redirect(result['payment_url'])
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
# Environment Variables Setup
export CANPAYBNPL_ENVIRONMENT="sandbox" # or "production"
export CANPAYBNPL_MERCHANT_KEY="test_merchant_your_key" # or "merchant_your_key" for production
export CANPAYBNPL_API_KEY="test_your_api_key" # or "your_api_key" for production
# Initiate Payment
curl -X POST "https://pay.canpaybnpl.com/api/v1/initiate-payment" \
-H "Content-Type: application/json" \
-H "X-Environment: $CANPAYBNPL_ENVIRONMENT" \
-H "X-Merchant-Key: $CANPAYBNPL_MERCHANT_KEY" \
-H "X-API-Key: $CANPAYBNPL_API_KEY" \
-d '{
"payment_amount": 250.00,
"currency_code": "GHC",
"ref_trx": "ORDER_12345",
"description": "Premium Subscription",
"callback_url": "https://yoursite.com/payment/callback_url"
}'
# Verify Payment
curl -X GET "https://pay.canpaybnpl.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
-H "Accept: application/json" \
-H "X-Environment: $CANPAYBNPL_ENVIRONMENT" \
-H "X-Merchant-Key: $CANPAYBNPL_MERCHANT_KEY" \
-H "X-API-Key: $CANPAYBNPL_API_KEY"
# Environment-specific credential examples:
# Sandbox: test_merchant_xxxxx, test_api_key_xxxxx
# Production: merchant_xxxxx, api_key_xxxxx
Complete integration guide for CanPay BNPL payment gateway with WooCommerce. Follow best practices for secure and reliable payment processing.
Seamlessly integrate CanPay BNPL payment gateway with your WooCommerce store for secure, fast transactions.
Ready-to-use WooCommerce payment gateway plugin for CanPay BNPL.
Everything you need for seamless payment processing
End-to-end encryption with PCI DSS compliance
Responsive design for all devices and screen sizes
Follow these simple steps to get started with CanPay BNPL WooCommerce integration
Download the CanPay BNPL WooCommerce plugin ZIP file from the Quick Download section above.
Go to your WordPress admin panel → Plugins → Add New → Upload Plugin and select the downloaded ZIP file.
After successful upload, click Activate Plugin to enable CanPay BNPL payment gateway in your WooCommerce store.
Navigate to WooCommerce → Settings → Payments → CanPay BNPL and enter your API credentials.
Enable Test/Sandbox Mode first and process a test/sandbox transaction to ensure everything works correctly before going live/production.
Essential settings for optimal performance
Obtain your Merchant ID, API Key from CanPay merchant account configuration section
RequiredEnsure your site has a valid SSL certificate for secure transactions
RequiredEnsure everything is ready before going live
Our technical team is here to assist you with integration and troubleshooting.
CanPay provides a set of ready-made, pre-designed checkout button images — complete with branding, colours, and text already built in. Download the variant that fits your design and drop it into your storefront, cart page, or payment flow as a clickable button. No custom styling needed.
Browse, preview, and download all official checkout button images from the public asset library. No API key required.
Open Asset LibraryEach image is a fully-designed button. Use it as-is — wrap it in an <a> or <button> tag to make it interactive.
Standalone CanPay logos for use in headers, receipts, and email templates.
| Method | Endpoint | Description |
|---|---|---|
| GET | /media-assets |
Browse the full asset library in-browser |
| GET | /media-assets/download/{id} |
Download a single asset by its numeric ID |
| GET | /media-assets/category/{folder}/download |
Download a full category as a ZIP file (checkout, logos) |
<!-- Step 1: Download your preferred variant from the asset library -->
<!-- Step 2: Upload to your server or CDN -->
<!-- Step 3: Reference with your own URL as shown below -->
<!-- "Checkout with CanPay" button -->
<a href="#" onclick="initiateCanPayCheckout(); return false;">
<img
src="/assets/canpay/checkout-with-canpay.webp"
alt="Checkout with CanPay BNPL"
height="48"
loading="lazy"
>
</a>
<!-- "Pay with CanPay" button (white background variant) -->
<a href="#" onclick="initiateCanPayCheckout(); return false;">
<img
src="/assets/canpay/white-pay-with-canpay.webp"
alt="Pay with CanPay BNPL"
height="48"
loading="lazy"
>
</a>
<!-- Best practice: choose the variant that fits your page background -->
<!-- Dark backgrounds → use the dark or yellow-text variants -->
<!-- Light backgrounds → use the white-background variants -->
// CanPayButton.jsx
// Download your preferred asset variant and host it alongside your app.
const CHECKOUT_BUTTONS = {
'checkout-dark': '/assets/canpay/checkout-with-canpay.webp',
'pay-dark': '/assets/canpay/pay-with-canpay.webp',
'checkout-white': '/assets/canpay/white-checkout-with-canpay.webp',
'pay-white': '/assets/canpay/white-pay-with-canpay.webp',
'pay-yellow': '/assets/canpay/yellow-pay-with-canpay.webp',
'checkout-yellow': '/assets/canpay/yellow-checkout-with-canpay.webp',
};
export function CanPayButton({ variant = 'checkout-dark', onClick, height = 48 }) {
const src = CHECKOUT_BUTTONS[variant] ?? CHECKOUT_BUTTONS['checkout-dark'];
return (
<button
type="button"
onClick={onClick}
style= background: 'none', border: 'none', padding: 0, cursor: 'pointer'
>
<img src={src} alt="Checkout with CanPay BNPL" height={height} loading="lazy" />
</button>
);
}
// Usage in your checkout page
import { CanPayButton } from './CanPayButton';
function CheckoutPage() {
const handleCanPay = () => initiateCanPayPayment({ amount, ref });
return (
<div className="payment-actions">
<CanPayButton variant="checkout-dark" onClick={handleCanPay} />
</div>
);
}
<?php
// config/canpaybnpl.php
// After downloading assets, place them in your public directory
// and reference them via your application's asset helper.
return [
'checkout_buttons' => [
'checkout_dark' => 'assets/canpay/checkout-with-canpay.webp',
'pay_dark' => 'assets/canpay/pay-with-canpay.webp',
'checkout_white' => 'assets/canpay/white-checkout-with-canpay.webp',
'pay_white' => 'assets/canpay/white-pay-with-canpay.webp',
'pay_yellow' => 'assets/canpay/yellow-pay-with-canpay.webp',
'checkout_yellow' => 'assets/canpay/yellow-checkout-with-canpay.webp',
],
];
// In your Blade template:
// <a href="https://pay.canpaybnpl.com/payment/checkout">
// <img
// src="https://pay.canpaybnpl.com/"
// alt="Checkout with CanPay BNPL"
// height="48"
// >
// </a>
// Choose the variant that suits your page:
// Dark page background → checkout_dark / pay_dark
// Light page background → checkout_white / pay_white
// Coloured CTA area → checkout_yellow / pay_yellow
// CanPayButton.vue
// Place downloaded assets in /public/assets/canpay/ and reference as shown.
<template>
<button type="button" class="canpay-btn" @click="$emit('click')">
<img :src="src" :alt="alt" :height="height" loading="lazy" />
</button>
</template>
<script setup>
const VARIANTS = {
'checkout-dark': '/assets/canpay/checkout-with-canpay.webp',
'pay-dark': '/assets/canpay/pay-with-canpay.webp',
'checkout-white': '/assets/canpay/white-checkout-with-canpay.webp',
'pay-white': '/assets/canpay/white-pay-with-canpay.webp',
'pay-yellow': '/assets/canpay/yellow-pay-with-canpay.webp',
'checkout-yellow': '/assets/canpay/yellow-checkout-with-canpay.webp',
};
const props = defineProps({
variant: { type: String, default: 'checkout-dark' },
height: { type: Number, default: 48 },
alt: { type: String, default: 'Checkout with CanPay BNPL' },
});
const src = computed(() => VARIANTS[props.variant] ?? VARIANTS['checkout-dark']);
</script>
<style scoped>
.canpay-btn {
background: none;
border: none;
padding: 0;
cursor: pointer;
display: inline-flex;
}
</style>
<!-- Usage -->
<CanPayButton variant="checkout-white" @click="initiateCheckout" />
Test Merchant API endpoints directly from this documentation. Use the demo credentials below for sandbox testing.
Use these demo credentials to test all payment methods in sandbox environment:
X-ENVIRONMENT: sandbox in your API requestssandbox for testing and production for live transactions. Only sandbox credentials use test_ prefix, production credentials have no prefix.
Base URL: https://pay.canpaybnpl.com
Environment Header: X-Environment: sandbox
Credentials: Use test_ prefixed keys
Purpose: Safe testing without real money
Base URL: https://pay.canpaybnpl.com
Environment Header: X-Environment: production
Credentials: No prefix for production keys
Purpose: Live transactions with real money
Merchant API uses conventional HTTP response codes to indicate the success or failure of API requests.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Invalid or missing API credentials |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error occurred |
| Error Code | Description | Solution |
|---|---|---|
INVALID_CREDENTIALS |
Invalid API credentials provided | Check your Merchant ID and API Key |
INVALID_AMOUNT |
Payment amount is invalid | Check minimum and maximum amount limits |
INVALID_CURRENCY |
Unsupported currency code | Use a supported currency code (GHS, GHC) |
DUPLICATE_REFERENCE |
Transaction reference already exists | Use a unique transaction reference |
EXPIRED_SESSION |
Payment session has expired | Create a new payment request |
MERCHANT_SUSPENDED |
Merchant account is suspended | Contact CanPay BNPL support |
{
"success": false,
"message": "Validation failed",
"error_code": "INVALID_AMOUNT",
"errors": {
"payment_amount": [
"The payment amount must be at least 1.00"
]
},
"timestamp": "2024-01-20T10:30:00Z"
}
Get help with your CanPay BNPL Merchant API integration from our support team and developer resources.
For API integration help:
Include your Merchant ID and detailed error descriptions for faster resolution.
Contact Support