Complete integration guide for CheckoutPay Payment Gateway API. Build powerful payment solutions with our RESTful API.
Create an account and get your API key from the dashboard. Your API key is required for all authenticated requests.
Sign Up Nowhttps://check-outnow.com/api/v1
All API requests must:
X-API-Key header for authenticated endpointsContent-Type: application/json headerAll authenticated API requests require your API key in the request header.
X-API-Key: pk_your_api_key_here
Security: Keep your API key secure and never expose it in client-side code. Store it securely on your server.
/payment-request
Create a new payment request. Returns account details for the customer to make payment.
{
"amount": 5000.00,
"payer_name": "John Doe",
"bank": "GTBank",
"webhook_url": "https://yourwebsite.com/webhook/payment-status",
"service": "Product Purchase",
"transaction_id": "TXN-1234567890",
"business_website_id": 1,
"website_url": "https://yourwebsite.com"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | decimal | Yes | Payment amount (minimum 0.01) |
| payer_name | string | Yes | Customer's name (required to get account number) |
| name | string | Yes* | Alternative to payer_name (either 'name' or 'payer_name' is required) |
| bank | string | No | Customer's bank name |
| webhook_url | string | Yes | URL to receive payment notifications (must be from approved website) |
| service | string | No | Description of the service/product |
| transaction_id | string | No | Your unique transaction ID (auto-generated if not provided) |
| business_website_id | integer | No | ID of your approved website (for website-specific webhooks) |
| website_url | string | No | Your website URL (for website identification) |
{
"success": true,
"message": "Payment request created successfully",
"data": {
"transaction_id": "TXN-1234567890",
"amount": 5000.00,
"payer_name": "John Doe",
"account_number": "0123456789",
"account_name": "Your Business Name",
"bank_name": "GTBank",
"status": "pending",
"expires_at": "2024-01-15T12:00:00Z",
"created_at": "2024-01-15T10:00:00Z",
"charges": {
"percentage": 50.00,
"fixed": 50.00,
"total": 100.00,
"paid_by_customer": false,
"amount_to_pay": 5000.00,
"business_receives": 4900.00
},
"website": {
"id": 1,
"url": "https://yourwebsite.com"
}
}
}
/payment/{transactionId}
Retrieve payment details by transaction ID.
{
"success": true,
"data": {
"transaction_id": "TXN-1234567890",
"amount": 5000.00,
"payer_name": "John Doe",
"bank": "GTBank",
"account_number": "0123456789",
"account_name": "Your Business Name",
"bank_name": "GTBank",
"status": "approved",
"webhook_url": "https://yourwebsite.com/webhook/payment-status",
"expires_at": "2024-01-15T12:00:00Z",
"matched_at": "2024-01-15T10:30:00Z",
"approved_at": "2024-01-15T10:35:00Z",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:35:00Z",
"charges": {
"percentage": 50.00,
"fixed": 50.00,
"total": 100.00,
"paid_by_customer": false,
"business_receives": 4900.00
},
"website": {
"id": 1,
"url": "https://yourwebsite.com"
}
}
}
/payments
List all payments for your business with optional filters.
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: pending, approved, rejected |
| from_date | date | Filter payments from this date (YYYY-MM-DD) |
| to_date | date | Filter payments until this date (YYYY-MM-DD) |
| website_id | integer | Filter by website ID |
| per_page | integer | Number of results per page (default: 15) |
GET https://check-outnow.com/api/v1/payments?status=approved&from_date=2024-01-01&per_page=20
X-API-Key: pk_your_api_key_here
Webhooks allow you to receive real-time notifications when payment events occur. You can set webhook URLs at the business level or per-website level for more granular control.
Webhooks are sent in the following priority order:
When a payment is approved, you'll receive a POST request to your webhook URL with the following payload:
{
"event": "payment.approved",
"transaction_id": "TXN-1234567890",
"status": "approved",
"amount": 5000.00,
"received_amount": 5000.00,
"payer_name": "John Doe",
"bank": "GTBank",
"payer_account_number": "0123456789",
"account_number": "0987654321",
"account_details": {
"account_name": "Your Business Name",
"bank_name": "GTBank"
},
"is_mismatch": false,
"mismatch_reason": null,
"name_mismatch": false,
"name_similarity_percent": 100,
"matched_at": "2024-01-15T10:30:00Z",
"approved_at": "2024-01-15T10:35:00Z",
"created_at": "2024-01-15T10:00:00Z",
"timestamp": "2024-01-15T10:35:00Z",
"website": {
"id": 1,
"url": "https://yourwebsite.com"
},
"charges": {
"percentage": 50.00,
"fixed": 50.00,
"total": 100.00,
"paid_by_customer": false,
"business_receives": 4900.00
},
"email": {
"subject": "Credit Alert",
"from": "noreply@gtbank.com",
"date": "2024-01-15T10:30:00Z"
}
}
Automatic Charges Mismatch Detection: Our system automatically detects when a customer pays the base amount without including charges.
If the following conditions are met, the payment will be automatically approved with a mismatch flag:
In this case, the webhook will include:
is_mismatch: truereceived_amount - The actual amount received (base amount without charges)mismatch_reason - Explanation of the mismatchamount - The originally requested amount (includes charges){
"event": "payment.approved",
"transaction_id": "TXN-1234567890",
"status": "approved",
"amount": 2070.00, // Requested amount (includes charges)
"received_amount": 2000.00, // Actual amount received (base amount)
"is_mismatch": true,
"mismatch_reason": "Customer paid base amount without charges. Expected: ₦2,070.00, Received: ₦2,000.00 (charges: ₦70.00)",
"name_mismatch": false,
"charges": {
"percentage": 20.00,
"fixed": 50.00,
"total": 70.00,
"paid_by_customer": false,
"business_receives": 1930.00 // received_amount - charges
},
...
}
Important: When handling charges mismatch, your business balance will be credited with the business_receives amount (received_amount minus charges), not the full requested amount. Always check is_mismatch and received_amount fields in your webhook handler to process payments correctly.
Important: Always validate webhook requests on your server. Consider implementing:
You can set webhook URLs in two ways:
Note: Webhook URLs must be from your approved website domains. Add and approve websites in your dashboard before using them.
$apiKey = 'pk_your_api_key_here';
$apiUrl = 'https://check-outnow.com/api/v1';
$data = [
'amount' => 5000.00,
'payer_name' => 'John Doe', // Required
'bank' => 'GTBank',
'webhook_url' => 'https://yourwebsite.com/webhook/payment-status',
'service' => 'Product Purchase'
];
$ch = curl_init($apiUrl . '/payment-request');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-API-Key: ' . $apiKey
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($response, true);
if ($httpCode === 201 && $result['success']) {
echo "Payment created: " . $result['data']['transaction_id'];
echo "Account Number: " . $result['data']['account_number'];
} else {
echo "Error: " . $result['message'];
}
const apiKey = 'pk_your_api_key_here';
const apiUrl = 'https://check-outnow.com/api/v1';
const createPayment = async () => {
const response = await fetch(`${apiUrl}/payment-request`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({
amount: 5000.00,
payer_name: 'John Doe',
bank: 'GTBank',
webhook_url: 'https://yourwebsite.com/webhook/payment-status',
service: 'Product Purchase'
})
});
const result = await response.json();
if (result.success) {
console.log('Payment created:', result.data.transaction_id);
console.log('Account Number:', result.data.account_number);
} else {
console.error('Error:', result.message);
}
};
createPayment();
import requests
import json
api_key = 'pk_your_api_key_here'
api_url = 'https://check-outnow.com/api/v1'
data = {
'amount': 5000.00,
'payer_name': 'John Doe', # Required
'bank': 'GTBank',
'webhook_url': 'https://yourwebsite.com/webhook/payment-status',
'service': 'Product Purchase'
}
headers = {
'Content-Type': 'application/json',
'X-API-Key': api_key
}
response = requests.post(
f'{api_url}/payment-request',
headers=headers,
data=json.dumps(data)
)
result = response.json()
if response.status_code == 201 and result['success']:
print(f"Payment created: {result['data']['transaction_id']}")
print(f"Account Number: {result['data']['account_number']}")
else:
print(f"Error: {result['message']}")
<?php
// webhook-handler.php
$payload = json_decode(file_get_contents('php://input'), true);
if ($payload['event'] === 'payment.approved') {
$transactionId = $payload['transaction_id'];
$amount = $payload['amount'];
$status = $payload['status'];
// Update your database
// Mark order as paid, send confirmation email, etc.
// Always return 200 OK to acknowledge receipt
http_response_code(200);
echo json_encode(['status' => 'received']);
} else {
http_response_code(400);
echo json_encode(['error' => 'Unknown event']);
}
?>
All errors follow a consistent format:
{
"success": false,
"message": "Error description here"
}
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (payment request created) |
| 400 | Bad Request (validation error) |
| 401 | Unauthorized (invalid or missing API key) |
| 404 | Not Found |
| 500 | Internal Server Error |
Status: 401
{
"success": false,
"message": "Invalid API key"
}
Status: 400
{
"success": false,
"message": "The payer name field is required. Please provide either \"name\" or \"payer_name\"."
}
Status: 400
{
"success": false,
"message": "Webhook URL must be from your approved website domain."
}
Status: 400
{
"success": false,
"message": "Insufficient balance",
"available_balance": 5000.00
}
API rate limits are applied per API key. Current limits:
If you exceed rate limits, you'll receive a 429 Too Many Requests response. Implement exponential backoff for retries.
Get support from our team or check out additional resources.