Payment / Alternative payment methods / Africa / Bank Transfer
H2H#
POST https://payments.apipro.io/v2/payment
Introduction#
Traditional bank transfers remain a popular payment method. This page describes the H2H (server-to-server) flow for Bank Transfer Africa.
ApiPro supports two integration options for this method:
-
H2H: your backend creates the payment and the customer stays on your site
-
HPP: the customer is redirected to a hosted payment page
How to start?#
-
Prepare a Create Payment request (see the Request Body example on this page).
-
Sign the request according to the Authentication & Signature rules.
-
Send the request to:
POST payments.apipro.io/v2/payment -
Parse the response:
-
check
error_code -
check
status.name -
follow the
challengeinstructions (see below)
-
-
Wait for the callback with the final status (recommended) or use Check status endpoints.
Create a Bank Transfer Africa payment#
In the request body you must set:
method = bank_transfer_africa
Example Create Payment request#
POST payments.apipro.io/v2/payment
{
"reference": "AfricaBankTransferH2H#1", // required, unique
"currency": "NGN", // required
"amount": 876, // required
"description": "My order h2h", // optional
"customer": // required
{
"identifier": "1111-1111-2211-2211", // required, any unique value from the merchant's system may be used.
"email": "juancarloos@hotmail.com", // required
"phone": "+2348031234567", // optional, Nigerian format number
"first_name": "Juan", // required
"last_name": "Garcisa Rodriiguez", // required
"middle_name": "Carlos", // optional
"country": "NG", // optional, Nigeria (ISO 3166-1 country code for Nigeria)
"state_code": "B", // optional
"city": "Buenos Aires", // optional
"address": "Calle Emilio Mitre 3256", // optional
"zip_code": "C1407", // optional
"itn": "2526232527", // conditional
"birthday": "2006-01-02", // optional
"ip": "192.168.0.1", // optional
"gender": "male" // optional
},
"method": "bank_transfer_africa", //required
"redirect_url": "redirect-url", // optional
"cancel_url": "cancel_url", // optional
"callback_url": "callback_url", // conditional
"extra": { // conditional, any field which may be needed for transaction routing and integration
"meta": {
"key": "value"
}
}
}
Response handling (200 OK)#
-
Check
error_code- if
error_code != 0— the request failed (see error examples below)
- if
-
Check
status.name- a non-final status (for example
created/pending) means you must follow thechallengeflow and then wait for the callback.
- a non-final status (for example
Challenge instructions#
challenge_type = "bank_transfer_africa" (bank requisites)#
If the response contains:
-
challenge.challenge_type = "bank_transfer_africa" -
challenge.challenge_bank_transfer_africa
We recommend allowing the customer to easily copy the bank requisites from challenge.challenge_bank_transfer_africa.
Example of the bank_transfer_africa challenge:
{
"challenge": {
"challenge_type": "bank_transfer_africa",
"challenge_bank_transfer_africa": {
"account_name": "54Pay Bank PLC",
"account_number": "8725720385",
"bank_name": "54Pay Bank PLC",
"bank_code": "999999",
"expiration_date": "2025-10-13 10:18:10"
}
}
}
then show the customer the bank requisites and allow them to copy:
-
account_number -
bank_name -
bank_code -
account_name(may be null) -
expiration_date(may be null)
After the customer completes the transfer:
-
collect payment confirmation details from the customer (for example, a transaction id)
-
send the confirmation data to:
payments.apipro.io/v2/payment/{request_id} -
wait for the callback with the final status
challenge_type = "redirect" (if returned)#
In some cases the API may return a redirect flow:
-
challenge.challenge_type = "redirect" -
challenge.challenge_redirect.url
If that happens, redirect the customer to challenge.challenge_redirect.url to complete the payment.
The final payment status will be delivered to your callback_url (if configured) and can also be verified using Check status.
Check status#
You can check the transaction status using:
-
By Reference:
POST payments.apipro.io/v2/check/transaction -
By Transaction ID:
GET payments.apipro.io/v2/transaction/{request_id}
Callback#
ApiPro sends a callback to the URL provided in callback_url when the transaction reaches a terminal state.
We strongly recommend validating the callback signature to avoid suspicious activity.
Headers#
| Header | Value |
|---|---|
Content-Type |
application/json |
Authorization |
{{authorization}} |
Digest |
{{digest}} |
Host |
{{host}} |
Date |
{{date}} |
See Authentication & Signature for how to build the signed headers.
Request body#
Annotations in the example are the field requirements: required, optional or conditional. Comments are stripped automatically by the Postman collection before signing; remove them in your own requests.
{
"reference": "AfricaBankTransferH2H#1", // required, unique
"currency": "NGN", // required
"amount": 876, // required
"description": "My order h2h", // optional
"customer": // required
{
"identifier": "1111-1111-2211-2211", // required, any unique value from the merchant's system may be used.
"email": "juancarloos@hotmail.com", // required
"phone": "+2348031234567", // optional, Nigerian format number
"first_name": "Juan", // required
"last_name": "Garcisa Rodriiguez", // required
"middle_name": "Carlos", // optional
"country": "NG", // optional, Nigeria (ISO 3166-1 country code for Nigeria)
"state_code": "B", // optional
"city": "Buenos Aires", // optional
"address": "Calle Emilio Mitre 3256", // optional
"zip_code": "C1407", // optional
"itn": "2526232527", // conditional
"birthday": "2006-01-02", // optional
"ip": "192.168.0.1", // optional
"gender": "male" // optional
},
"method": "bank_transfer_africa", // required, snake_case / lower case only: "bank_transfer_africa" (not "BANK_TRANSFER_AFRICA" or "BankTransferAfrica")
"redirect_url": "redirect-url", // optional
"cancel_url": "cancel_url", // optional
"callback_url": "callback_url", // conditional
"extra": { // conditional, any field which may be needed for transaction routing and integration
"meta": {
"key": "value"
}
}
}
Fields#
| Field | Type | Requirement / note |
|---|---|---|
reference |
string | required, unique |
currency |
string | required |
amount |
integer | required |
description |
string | optional |
customer |
object | required |
customer.identifier |
string | required, any unique value from the merchant's system may be used. |
customer.email |
string | required |
customer.phone |
string | optional, Nigerian format number |
customer.first_name |
string | required |
customer.last_name |
string | required |
customer.middle_name |
string | optional |
customer.country |
string | optional, Nigeria (ISO 3166-1 country code for Nigeria) |
customer.state_code |
string | optional |
customer.city |
string | optional |
customer.address |
string | optional |
customer.zip_code |
string | optional |
customer.itn |
string | conditional |
customer.birthday |
string | optional |
customer.ip |
string | optional |
customer.gender |
string | optional |
method |
string | required, snake_case / lower case only: "bank_transfer_africa" (not "BANK_TRANSFER_AFRICA" or "BankTransferAfrica") |
redirect_url |
string | optional |
cancel_url |
string | optional |
callback_url |
string | conditional |
extra |
object | conditional, any field which may be needed for transaction routing and integration |
extra.meta |
object | |
extra.meta.key |
string |
Responses#
Response Examples
Merchant not found
{
"error_code": 35,
"error_reason": "Merchant not found",
"description": "The requested resource is undefined",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:01:00.00Z"
}
Required fields are missing: method or widget.method, reference
{
"error_code": 31,
"error_reason": "Required fields are missing: method or widget.method, reference",
"timestamp": "2025-10-26T14:03:00.00Z"
}
Using 'method' and 'widget.method' at the same time.
{
"error_code": 30,
"error_reason": "Invalid params",
"description": "Widget and method cannot be used together",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:04:00.00Z"
}
Card can only be used with specific methods. Check documentation
{
"error_code": 30,
"error_reason": "Invalid params",
"description": "Card can only be used with specific methods. Check documentation",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:05:00.00Z"
}
Customer is blocked
{
"error_code": 451,
"error_reason": "General risk decline",
"description": "Customer is blocked",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:06:00.00Z"
}
Customer is blocked for all merchant projects
{
"error_code": 451,
"error_reason": "General risk decline",
"description": "Customer is blocked for all merchant projects",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:02.00Z"
}
Customer is blocked for the specified project
{
"error_code": 451,
"error_reason": "General risk decline",
"description": "Customer is blocked for the specified project",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:04.00Z"
}
Customer is blocked system-wide
{
"error_code": 451,
"error_reason": "General risk decline",
"description": "Customer is blocked system-wide",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:06.00Z"
}
Customer is globally locked
{
"error_code": 451,
"error_reason": "General risk decline",
"description": "Customer is globally locked",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:08.00Z"
}
Timeout while requesting routing
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Routing request timeout",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:01.00Z"
}
Payment transaction timeout after some time
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Payment transaction timeout after 30 seconds",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:03.00Z"
}
Unknown routing error
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Unknown routing error",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:02.00Z"
}
Payment transaction was cancelled
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Payment transaction was cancelled",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:04.00Z"
}
Internal error: Data is empty
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Internal error: Value cannot be null. (Parameter 'data')",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:05.00Z"
}
Endpoint type wasn't found
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Internal error: Endpoint type cannot be null or empty (Parameter 'endpointType')",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:06.00Z"
}
Mid configuration error
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Internal error: Mid [Mid ID] no longer exists in configuration",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:07.00Z"
}
Routing service error: Converting data error
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Routing service error: The JSON value could not be converted to System.Guid.",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:08.00Z"
}
Routing service error
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Routing service error",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:08.00Z"
}
Broker transport failure
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Internal error: Broker transport failure",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:09.00Z"
}
Internal error
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "Internal error",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:09.00Z"
}
An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank
{
"error_code": 121,
"error_reason": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"description": "An issue has been detected in the routing settings. For instance, it could be due to a disabled project or bank",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:08:10.00Z"
}
An unexpected error occurred while processing the request
{
"error_code": 200,
"error_reason": "Transaction processing error",
"description": "An unexpected error occurred while processing the request",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:09:00.00Z"
}
Invalid method challenge configuration. Settings not found.
{
"error_code": 121,
"error_reason": "Invalid method challenge configuration. Please reconfigure method challenge type settings",
"description": "Invalid method challenge configuration. Settings not found.",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:10:00.00Z"
}
Route is invalid (Incorrect method, mid settings)
{
"error_code": 121,
"error_reason": "Route is invalid",
"description": "There is more than one challenge setting for a method. Please reconfigure method challenge type settings.",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:11:00.00Z"
}
Getting currency rate info error.
{
"error_code": 200,
"error_reason": "While getting currency rate, error happend",
"description": "An internal error occurred while processing currency information",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:12:00.00Z"
}
Error processing currency information.
{
"error_code": 200,
"error_reason": "Error with payment configurations",
"description": "An internal error occurred while processing currency information",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:13:00.00Z"
}
Error with wallet
{
"error_code": 200,
"error_reason": "Error with wallet",
"description": "An internal error occurred while processing currency information",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:14:00.00Z"
}
Failed to register transaction
{
"error_code": 200,
"error_reason": "Failed to register transaction",
"description": "An internal error occurred while processing currency information",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:15:00.00Z"
}
Failed saving card info
{
"error_code": 200,
"error_reason": "Transaction processing error",
"description": "Failed to save card information",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:16:00.00Z"
}
Transaction processing error
{
"error_code": 200,
"error_reason": "Transaction processing error",
"description": "Failed to register the transaction",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:17:00.00Z"
}
Mid doesn't support challenge type for method (mid or method settings problem)
{
"error_code": 121,
"error_reason": "Route is invalid",
"description": "Mid does not support challenge type [challengeType] for method [method]",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:18:00.00Z"
}
Mid is disabled
{
"error_code": 121,
"error_reason": "Route is invalid",
"description": "Mid is disabled",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:19:00.00Z"
}
Bank doesn't support currency
{
"error_code": 1051,
"error_reason": "Bank doesn't support currency",
"description": "Blocked routing for transaction: Invalid currency",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:20:00.00Z"
}
Bank doesn't support payment method
{
"error_code": 1054,
"error_reason": "Bank doesn't support payment method",
"description": "Blocked routing for transaction: Invalid method: [method]",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:21:00.00Z"
}
Bank does not support transaction: Invalid payment type
{
"error_code": 1050,
"error_reason": "Bank does not support transaction",
"description": "Blocked routing for transaction: Invalid payment type",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:22:00.00Z"
}
Mid request timeout
{
"error_code": 200,
"error_reason": "Mid request timeout",
"request_id": null,
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:24:00.00Z"
}
Communication error
{
"error_code": 200,
"error_reason": "Communication error",
"request_id": "[UUID_ТРАНЗАКЦІЇ]",
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:25:00.00Z"
}
Forbidden
{
"error_code": 5,
"error_reason": "Forbidden",
"timestamp": "2025-10-26T14:33:00.00Z"
}
Some unexpected message
{
"error_code": 5,
"error_reason": "[Some unexpected message]",
"timestamp": "2025-10-26T14:33:00.00Z"
}
Failed to register card transaction
{
"error_code": 200,
"error_reason": "Failed to register card transaction",
"request_id": null,
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:34:00.00Z"
}
Failed to register cascade transaction
{
"error_code": 200,
"error_reason": "Failed to register cascade transaction",
"request_id": null,
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:35:00.00Z"
}
Endpoint type cannot be null or empty
{
"error_code": 200,
"error_reason": "Endpoint type cannot be null or empty",
"request_id": null,
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:36:00.00Z"
}
Data is empty
{
"error_code": 200,
"error_reason": "Value cannot be null. (Parameter 'data')",
"request_id": null,
"reference": "YOUR_REFERENCE",
"timestamp": "2025-10-26T14:36:00.00Z"
}
An unexpected internal error occured
{
"error_code": 200,
"error_reason": "Transaction processing error",
"description": "An unexpected internal error occurred",
"request_id": "YOUR_REFERENCE",
"status": "error",
"timestamp": "2025-10-26T14:38:00.00Z"
}
Handler returned null response
{
"error_code": 210,
"error_reason": "Handler returned null response",
"description": "Handler returned null response",
"request_id": "your_transaction_reference",
"status": "error",
"timestamp": "2025-10-26T12:02:00.000Z"
}
Rate limit exceeded
{
"error_code": 210,
"error_reason": "Rate limit exceeded",
"description": "Rate limit exceeded",
"request_id": "your_transaction_reference",
"status": "error",
"timestamp": "2025-10-26T12:01:00.000Z"
}
Access denied: Invalid or missing access token
{
"error_code": 210,
"error_reason": "Access denied: Invalid or missing access token",
"description": "Access denied: Invalid or missing access token",
"request_id": "your_transaction_reference",
"status": "error",
"timestamp": "2025-10-26T12:00:00.000Z"
}
Request cannot be null
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Request cannot be null",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Flow cache limit exceeded
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Flow cache limit exceeded",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Flow configuration not found for project: {projectId}
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Flow configuration not found for project: {projectId}",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Invalid flow configuration
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Invalid flow configuration",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Flow execution failed
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Flow execution failed:",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Circular reference detected at node: {NodeIdentifier}
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Circular reference detected at node: {NodeIdentifier}",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Node not found: {NodeIdentifier}
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Node not found: {NodeIdentifier}",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Flow execution limit exceeded
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Flow execution limit exceeded",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Flow ended without result
{
"code": 0,
"reason": "",
"error_code": 1,
"error_reason": "Flow ended without result",
"request_id": "",
"reference": "",
"status": "error",
"timestamp": "2025-09-29T11:52:39.25Z",
"description": ""
}
Duplicated reference
{
"error_code": 108,
"error_reason": "Duplicated reference",
"request_id": "3829f5bd-6dcb-41f9-a4ba-3ff8b65a3cfc",
"reference": "",
"timestamp": "2025-11-10T08:47:22.81Z"
}
Successful transaction
{
"identifier": "BAN000442136",
"request_id": "e5a1f870-c248-4d5b-a673-37a784dcecab",
"reference": "AfricaBankTransferH2H#1",
"description": "My order h2h",
"status": {
"name": "created",
"date": "2025-10-13T08:48:13.4928684Z"
},
"created_date": "2025-10-13T08:46:32.096",
"amount": 876,
"billing_amount": 876,
"currency": "NGN",
"challenge": {
"challenge_type": "bank_transfer_africa",
"challenge_bank_transfer_africa": {
"account_name": "54Pay Bank PLC",
"account_number": "8725720385",
"bank_name": "54Pay Bank PLC",
"bank_code": "999999",
"expiration_date": "2025-10-13 10:18:10"
}
},
"timestamp": "2025-10-13T08:48:13.8622162Z",
"error_code": 0,
"error_message": ""
}
Missing Authorization header
{
"error_code": 31,
"error_reason": "Missing Authorization header",
"timestamp": "2025-10-26T16:01:00.00Z"
}
Invalid Authorization header format
{
"error_code": 31,
"error_reason": "Invalid authorization header format",
"timestamp": "2025-10-26T16:03:00.00Z"
}
Invalid signature format
{
"error_code": 31,
"error_reason": "Invalid signature format",
"timestamp": "2025-10-26T16:03:00.00Z"
}
Unsupported algorithm
{
"error_code": 31,
"error_reason": "Unsupported algorithm",
"timestamp": "2025-10-26T16:04:00.00Z"
}
Invalid API key
{
"error_code": 31,
"error_reason": "Invalid API key",
"timestamp": "2025-10-26T16:05:00.00Z"
}
Missing Date header
{
"error_code": 31,
"error_reason": "Missing Date header",
"timestamp": "2025-10-26T16:06:00.00Z"
}
Invalid date format
{
"error_code": 31,
"error_reason": "Invalid date format",
"timestamp": "2025-10-26T16:07:00.00Z"
}
Date is outdated or invalid
{
"error_code": 31,
"error_reason": "Date is outdated or invalid",
"timestamp": "2025-10-26T16:08:00.00Z"
}
Missing Digest header
{
"error_code": 31,
"error_reason": "Missing Digest header",
"timestamp": "2025-10-26T16:09:00.00Z"
}
Invalid digest
{
"error_code": 31,
"error_reason": "Invalid digest",
"timestamp": "2025-10-26T16:10:00.00Z"
}
Request timestamp has already been used
{
"error_code": 31,
"error_reason": "Request timestamp has already been used",
"timestamp": "2025-10-26T16:11:00.00Z"
}
Invalid headers specification
{
"error_code": 31,
"error_reason": "Invalid headers specification",
"timestamp": "2025-10-26T16:12:00.00Z"
}
Invalid signature
{
"error_code": 31,
"error_reason": "Invalid signature",
"timestamp": "2025-10-26T16:13:00.00Z"
}
Processing error:
{
"error_code": 210,
"error_reason": "Processing error:",
"description": "Processing error:",
"request_id": "your_transaction_reference",
"status": "error",
"timestamp": "2025-10-26T12:03:00.000Z"
}
Missing required authentication headers
{
"error_code": 31,
"error_reason": "Missing required authentication headers",
"timestamp": "2025-10-26T14:04:00.00Z"
}
Callback Notifications
The system sends an HTTP callback to the callback_url of your request when a transaction reaches a final state. Always verify the callback signature; see Callback Verification.
Callback Payload
Callback request
{
"identifier": "PM0000000BTRNGN1",
"creation_date": "2025-11-16T11:30:40.150Z",
"request_id": "d4e5f6a7-b8c9-d0e1-f2a3-b4c5d6e7f8a9",
"reference": "ref-btr-ng-h2h-6400334455",
"method": "bank_transfer_africa",
"type": "payment",
"mode": "initial",
"status": "success",
"status_date": "2025-11-16T11:32:50.820Z",
"amount": "50000.00",
"currency": "NGN",
"billing_amount": "50000.00",
"billing_currency": "NGN",
"fee_amount": "100.00",
"fee_currency": "NGN",
"customer": {
"identifier": "cust_ng_686868",
"email": "chioma.okonkwo@example.com",
"phone": "+2348012345678",
"first_name": "Chioma",
"last_name": "Okonkwo",
"country": "NG"
},
"error_code": 0,
"error_reason": null,
"timestamp": "2025-11-16T11:32:51.000Z",
"meta": {
"key": "value"
}
}