Create Transfer
curl --request POST \
--url https://api.usezentra.com/api/v1/transfers \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"amount_minor": 123,
"recipient_account": "<string>",
"recipient_bank_code": "<string>",
"narration": "<string>",
"reference": "<string>",
"currency": "<string>",
"metadata": {}
}
'import requests
url = "https://api.usezentra.com/api/v1/transfers"
payload = {
"amount_minor": 123,
"recipient_account": "<string>",
"recipient_bank_code": "<string>",
"narration": "<string>",
"reference": "<string>",
"currency": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount_minor: 123,
recipient_account: '<string>',
recipient_bank_code: '<string>',
narration: '<string>',
reference: '<string>',
currency: '<string>',
metadata: {}
})
};
fetch('https://api.usezentra.com/api/v1/transfers', 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://api.usezentra.com/api/v1/transfers",
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([
'amount_minor' => 123,
'recipient_account' => '<string>',
'recipient_bank_code' => '<string>',
'narration' => '<string>',
'reference' => '<string>',
'currency' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://api.usezentra.com/api/v1/transfers"
payload := strings.NewReader("{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.usezentra.com/api/v1/transfers")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usezentra.com/api/v1/transfers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": false,
"error": {
"code": "insufficient_balance",
"message": "Wallet balance insufficient",
"status": 422,
"details": {
"required": 50050,
"available": 30000
}
}
}
{
"success": false,
"error": {
"code": "invalid_account",
"message": "Recipient account not found",
"status": 422
}
}
{
"success": false,
"error": {
"code": "limit_exceeded",
"message": "Daily transfer limit exceeded",
"status": 422,
"details": {
"limit": 1000000,
"used": 950000
}
}
}
Create Transfer
POST /api/v1/transfers - Send money to a bank account
POST
/
api
/
v1
/
transfers
Create Transfer
curl --request POST \
--url https://api.usezentra.com/api/v1/transfers \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"amount_minor": 123,
"recipient_account": "<string>",
"recipient_bank_code": "<string>",
"narration": "<string>",
"reference": "<string>",
"currency": "<string>",
"metadata": {}
}
'import requests
url = "https://api.usezentra.com/api/v1/transfers"
payload = {
"amount_minor": 123,
"recipient_account": "<string>",
"recipient_bank_code": "<string>",
"narration": "<string>",
"reference": "<string>",
"currency": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount_minor: 123,
recipient_account: '<string>',
recipient_bank_code: '<string>',
narration: '<string>',
reference: '<string>',
currency: '<string>',
metadata: {}
})
};
fetch('https://api.usezentra.com/api/v1/transfers', 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://api.usezentra.com/api/v1/transfers",
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([
'amount_minor' => 123,
'recipient_account' => '<string>',
'recipient_bank_code' => '<string>',
'narration' => '<string>',
'reference' => '<string>',
'currency' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://api.usezentra.com/api/v1/transfers"
payload := strings.NewReader("{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.usezentra.com/api/v1/transfers")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usezentra.com/api/v1/transfers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount_minor\": 123,\n \"recipient_account\": \"<string>\",\n \"recipient_bank_code\": \"<string>\",\n \"narration\": \"<string>\",\n \"reference\": \"<string>\",\n \"currency\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": false,
"error": {
"code": "insufficient_balance",
"message": "Wallet balance insufficient",
"status": 422,
"details": {
"required": 50050,
"available": 30000
}
}
}
{
"success": false,
"error": {
"code": "invalid_account",
"message": "Recipient account not found",
"status": 422
}
}
{
"success": false,
"error": {
"code": "limit_exceeded",
"message": "Daily transfer limit exceeded",
"status": 422,
"details": {
"limit": 1000000,
"used": 950000
}
}
}
Initiate a money transfer to any Nigerian bank account.
Endpoint
POST /api/v1/transfers
Request Body
number
required
Amount in kobo (e.g., 10000 = ₦100.00)
string
required
Recipient account number (10 digits)
string
required
Recipient bank code (e.g.,
058 for GTBank)string
required
Transfer description (max 100 characters)
string
Unique reference for this transfer (auto-generated if not provided)
string
default:"NGN"
Currency code (currently only NGN supported)
object
Additional data to store with the transfer
Response
string
Unique transfer ID
number
Transfer amount in kobo
number
Transaction fee in kobo
number
Total amount debited (amount + fee)
string
Recipient account number
string
Recipient account name
string
Recipient bank name
string
Transfer status (
pending, processing, completed, failed)string
Unique reference
string
Transfer description
string
Provider session ID
string
ISO 8601 timestamp
Example Request
const transfer = await client.transfers.create({
amountMinor: 50000, // ₦500.00
recipient_account: '0123456789',
recipient_bank_code: '058',
narration: 'Payment for services',
reference: 'TRF_' + Date.now(),
metadata: {
customer_id: 'cus_123',
invoice_id: 'INV_456'
}
});
console.log(`Transfer ID: ${transfer.id}`);
console.log(`Status: ${transfer.status}`);
transfer = client.transfers.create(
amount_minor=50000, # ₦500.00
recipient_account='0123456789',
recipient_bank_code='058',
narration='Payment for services',
reference=f'TRF_{int(time.time())}',
metadata={
'customer_id': 'cus_123',
'invoice_id': 'INV_456'
}
)
print(f"Transfer ID: {transfer.id}")
print(f"Status: {transfer.status}")
$transfer = $client->transfers->create([
'amount_minor' => 50000, // ₦500.00
'recipient_account' => '0123456789',
'recipient_bank_code' => '058',
'narration' => 'Payment for services',
'reference' => 'TRF_' . time(),
'metadata' => [
'customer_id' => 'cus_123',
'invoice_id' => 'INV_456'
]
]);
echo "Transfer ID: {$transfer->id}\n";
echo "Status: {$transfer->status}";
curl -X POST https://api.usezentra.com/api/v1/transfers \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount_minor": 50000,
"recipient_account": "0123456789",
"recipient_bank_code": "058",
"narration": "Payment for services",
"reference": "TRF_1234567890",
"metadata": {
"customer_id": "cus_123",
"invoice_id": "INV_456"
}
}'
Example Response
{
"success": true,
"data": {
"id": "trn_abc123xyz",
"amount_minor": 50000,
"fee_minor": 50,
"total_minor": 50050,
"recipient_account": "0123456789",
"recipient_name": "John Doe",
"recipient_bank": "Guaranty Trust Bank",
"recipient_bank_code": "058",
"status": "pending",
"reference": "TRF_1234567890",
"narration": "Payment for services",
"session_id": "SES_xyz789",
"currency": "NGN",
"metadata": {
"customer_id": "cus_123",
"invoice_id": "INV_456"
},
"created_at": "2024-01-15T10:30:00Z"
}
}
Transfer Fees
| Amount Range | Fee |
|---|---|
| ₦0 - ₦5,000 | ₦10 |
| ₦5,001 - ₦50,000 | ₦25 |
| Above ₦50,000 | ₦50 |
Fees are automatically deducted from your wallet balance.
Processing Time
- Instant: Most transfers complete within seconds
- Same Day: Some banks may take up to 24 hours
- Webhook: You’ll receive a webhook when the transfer completes
Error Responses
{
"success": false,
"error": {
"code": "insufficient_balance",
"message": "Wallet balance insufficient",
"status": 422,
"details": {
"required": 50050,
"available": 30000
}
}
}
{
"success": false,
"error": {
"code": "invalid_account",
"message": "Recipient account not found",
"status": 422
}
}
{
"success": false,
"error": {
"code": "limit_exceeded",
"message": "Daily transfer limit exceeded",
"status": 422,
"details": {
"limit": 1000000,
"used": 950000
}
}
}
Idempotency
Use thereference parameter to prevent duplicate transfers:
// This will only create one transfer, even if called multiple times
const transfer = await client.transfers.create({
amountMinor: 50000,
destinationAccountNumber: '0123456789',
destinationBankCode: '058',
narration: 'Payment',
reference: 'UNIQUE_REF_123' // Use same reference
});
Next Steps
Get Transfer
Check transfer status
List Transfers
View all transfers
Resolve Account
Verify account before sending
Webhooks
Handle transfer events
Was this page helpful?