curl --request POST \
--url https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"channel": "BANK_ACCOUNT",
"accountName": "<string>",
"accountNumber": "<string>",
"countryCode": "NG",
"institution": {},
"amount": {
"value": "15000",
"currencyCode": "NGN"
}
}
'import requests
url = "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients"
payload = {
"channel": "BANK_ACCOUNT",
"accountName": "<string>",
"accountNumber": "<string>",
"countryCode": "NG",
"institution": {},
"amount": {
"value": "15000",
"currencyCode": "NGN"
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channel: 'BANK_ACCOUNT',
accountName: '<string>',
accountNumber: '<string>',
countryCode: 'NG',
institution: {},
amount: {value: '15000', currencyCode: 'NGN'}
})
};
fetch('https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channel' => 'BANK_ACCOUNT',
'accountName' => '<string>',
'accountNumber' => '<string>',
'countryCode' => 'NG',
'institution' => [
],
'amount' => [
'value' => '15000',
'currencyCode' => 'NGN'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients"
payload := strings.NewReader("{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"paymentMethodId": "<string>",
"recipientId": "<string>",
"channel": "<string>",
"countryCode": "<string>",
"accountName": "<string>",
"accountNumber": "<string>",
"institution": {},
"amount": {}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}Add Recipient to Batch
Requires the PAYMENT_METHOD.CREATE key permission.
curl --request POST \
--url https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"channel": "BANK_ACCOUNT",
"accountName": "<string>",
"accountNumber": "<string>",
"countryCode": "NG",
"institution": {},
"amount": {
"value": "15000",
"currencyCode": "NGN"
}
}
'import requests
url = "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients"
payload = {
"channel": "BANK_ACCOUNT",
"accountName": "<string>",
"accountNumber": "<string>",
"countryCode": "NG",
"institution": {},
"amount": {
"value": "15000",
"currencyCode": "NGN"
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channel: 'BANK_ACCOUNT',
accountName: '<string>',
accountNumber: '<string>',
countryCode: 'NG',
institution: {},
amount: {value: '15000', currencyCode: 'NGN'}
})
};
fetch('https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channel' => 'BANK_ACCOUNT',
'accountName' => '<string>',
'accountNumber' => '<string>',
'countryCode' => 'NG',
'institution' => [
],
'amount' => [
'value' => '15000',
'currencyCode' => 'NGN'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients"
payload := strings.NewReader("{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.afriex.com/api/v1/payment-batch/{batchId}/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channel\": \"BANK_ACCOUNT\",\n \"accountName\": \"<string>\",\n \"accountNumber\": \"<string>\",\n \"countryCode\": \"NG\",\n \"institution\": {},\n \"amount\": {\n \"value\": \"15000\",\n \"currencyCode\": \"NGN\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"paymentMethodId": "<string>",
"recipientId": "<string>",
"channel": "<string>",
"countryCode": "<string>",
"accountName": "<string>",
"accountNumber": "<string>",
"institution": {},
"amount": {}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}{
"code": "<string>",
"error": "<string>",
"details": {
"errorMessage": "<string>",
"friendlyMessage": "<string>",
"data": {
"customerId": "<string>"
}
}
}PAYMENT_METHOD.CREATE key permission.Authorizations
Static business API key issued from the dashboard. A business can
provision multiple API keys, each scoped to a configurable set of
permissions (e.g. read transactions, create deposits, etc). Permissions are chosen per key at creation time in the
dashboard and may be revoked by deleting the key. Requests made with a
key that does not include the permission required by the target
endpoint is rejected with a 401 Unauthorized response, the same
response an unrecognised, malformed, revoked or disabled key returns. The API
does not distinguish the two cases on the wire.
Manage your keys and their permissions under Developer → API keys
in the dashboard.
The permission each endpoint requires is below. Where several are listed, any one of them is enough. Keys created before permissions existed carry none and keep access to every endpoint.
| Endpoint | Permission |
|---|---|
GET /customer, GET /customer/{customerId} | CUSTOMER.READ |
POST /customer | CUSTOMER.CREATE |
PATCH /customer/{customerId}, PATCH /customer/{customerId}/kyc, POST /customer/{customerId}/verify | CUSTOMER.UPDATE |
DELETE /customer/{customerId} | CUSTOMER.DELETE |
GET /payment-method, GET /payment-method/{paymentMethodId}, GET /payment-method/institution, GET /payment-method/institution/codes, GET /payment-method/resolve, GET /payment-method/virtual-account, GET /payment-method/pool-account | PAYMENT_METHOD.READ |
POST /payment-method, DELETE /payment-method/{paymentMethodId}, POST /payment-method/virtual-account, GET /payment-method/crypto-wallet | PAYMENT_METHOD.CREATE |
POST /transaction | TRANSACTION.DEPOSIT.CREATE, TRANSACTION.WITHDRAW.CREATE or TRANSACTION.SWAP.CREATE |
POST /transaction/{transactionId}/authorize, POST /transaction/pool-account | TRANSACTION.DEPOSIT.CREATE |
GET /transaction, GET /transaction/{transactionId}, GET /transaction/{transactionId}/advice | TRANSACTION.HISTORY.READ |
GET /org/balance, GET /org/rates | WALLET.BALANCES.READ |
POST /media/url | PAYMENT_METHOD.CREATE |
POST /sme-registration | COMPLIANCE.KYB.SUBMIT |
GET /sme-registration/status | COMPLIANCE.KYB.READ |
POST /checkout-session | CHECKOUT_LINK.CREATE |
GET /payment-batch, GET /payment-batch/{batchId}, GET /payment-batch/{batchId}/recipients | PAYMENT_METHOD.READ |
POST /payment-batch, PATCH /payment-batch/{batchId}, DELETE /payment-batch/{batchId}, POST /payment-batch/{batchId}/recipients, POST /payment-batch/{batchId}/recipients/bulk, PATCH /payment-batch/{batchId}/recipients/{recipientId}, DELETE /payment-batch/{batchId}/recipients/{recipientId} | PAYMENT_METHOD.CREATE |
POST /payment-batch/{batchId}/withdraw | TRANSACTION.WITHDRAW.CREATE |
GET /payment-batch/{batchId}/sessions | TRANSACTION.HISTORY.READ |
POST /org/balance/topup, POST /webhooks/trigger | None; any valid key |
Headers
API version in ISO 8601 format. The only supported version is 2026-05-18, which is also the default when the header is omitted. Any other value is rejected with a 400 Bad Request.
Signature of the request payload, used for request authentication where payload signing is enabled for your business.
Path Parameters
Id of a batch belonging to the calling business.
Body
The account to pay, in the same shape POST /api/v1/payment-method accepts, plus the amount to pay it in this batch.
Response
The created recipient
One payout in a batch. The response includes the channel, country, institution, account name and number, the per-run amount, and the batch and recipient ids. Fields not listed on this schema are not returned.
Show child attributes
Show child attributes
