API reference
Payout batches
Create, submit, follow and cancel batches of payments.
List payout batches
GET/api/v1/payout-batchesscope
payouts.readYour batches, newest first, without their items.
Query
statusstring | Draft, PendingApproval, Approved, Rejected, Processing, PartiallySuccessful, Successful, Failed or Cancelled. |
pageinteger | Page number, starting at 1. Default 1. |
pageSizeinteger | Items per page, 1 to 100. Default 20. |
GET /api/v1/payout-batches · test
curl -X GET "https://api.tranzaq.com/api/v1/payout-batches" \
-H "Authorization: Bearer $TOKEN"const response = await fetch("https://api.tranzaq.com/api/v1/payout-batches", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/payout-batches");
request.Headers.Authorization = new("Bearer", token);
var response = await http.SendAsync(request); // http.BaseAddress = "https://api.tranzaq.com"
Console.WriteLine(await response.Content.ReadAsStringAsync());import uuid, requests
response = requests.get(
"https://api.tranzaq.com/api/v1/payout-batches",
headers={"Authorization": f"Bearer {token}"},
)
print(response.json())Answer · 200
Response · test
{
"success": true,
"message": "Operation completed",
"code": 200,
"result": { "items": [ … ], "total": 22, "page": 1, "pageSize": 20 }
}Errors
- 401Missing, invalid or expired token.
- 403The token does not have the payouts.read scope.
Get a payout batch
GET/api/v1/payout-batches/{id}scope
payouts.readOne batch with every payment, its status and failure reason, and the approval steps. Poll this, or use webhooks.
Path
iduuidrequired | The batch id. |
GET /api/v1/payout-batches/{id} · test
curl -X GET "https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID" \
-H "Authorization: Bearer $TOKEN"const response = await fetch("https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/payout-batches/PASTE_ID");
request.Headers.Authorization = new("Bearer", token);
var response = await http.SendAsync(request); // http.BaseAddress = "https://api.tranzaq.com"
Console.WriteLine(await response.Content.ReadAsStringAsync());import uuid, requests
response = requests.get(
"https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID",
headers={"Authorization": f"Bearer {token}"},
)
print(response.json())Answer · 200
Response · test
{
"success": true,
"message": "Operation completed",
"code": 200,
"result": {
"id": "3f9c1c9e-6b1a-4d6f-9a77-0f6f3f3c2a10",
"batchReference": "PB-20261018-0007",
"batchName": "October salaries",
"status": "Draft",
"speed": "Instant",
"currency": "GHS",
"totalAmount": 1850.00,
"totalFees": 9.25,
"itemCount": 1,
"createdBy": "Tranzaq API",
"createdAt": "2026-10-18T10:15:00+00:00",
"submittedAt": null,
"approvedAt": null,
"completedAt": null,
"items": [
{
"id": "b3c5f0a2-3d1e-4a71-8f0e-1c2d3e4f5a6b",
"reference": "SAL-1",
"amount": 1850.00,
"feeAmount": 9.25,
"currency": "GHS",
"destinationType": "MobileMoney",
"maskedAccountNumber": "024****567",
"accountName": "Ama Owusu",
"network": "MTN",
"status": "Pending",
"failureCode": null,
"failureReason": null
}
],
"approvals": []
}
}Errors
- 404No such batch in your business.
Create a payout batch
POST/api/v1/payout-batchesscope
payouts.writeneeds Idempotency-KeySave a draft batch of payments. Nothing is sent yet: submit the draft when you are ready. Sending the same Idempotency-Key again returns the same batch.
Body (JSON)
namestringrequired | A name for the batch, up to 200 characters. |
speedstring | Instant (default), SameDay, NextDay or ManualReview. |
itemsarrayrequired | The payments. Up to 1,000 per batch. |
items[].beneficiaryIduuidrequired | A person you added. |
items[].amountnumberrequired | In cedis, at most 2 decimal places. |
items[].destinationIduuid | Which of the person's accounts. Leave out to use their default. |
items[].referencestring | Your own note or id for this payment, up to 100 characters. |
POST /api/v1/payout-batches · test
curl -X POST "https://api.tranzaq.com/api/v1/payout-batches" \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: a-new-guid-for-each-request" \
-H "Content-Type: application/json" \
-d '{ "name": "October salaries", "speed": "Instant", "items": [ { "beneficiaryId": "8d2f6f40-5e7a-4b0e-b1a1-2f4c9d7e1a33", "amount": 1850.00, "reference": "SAL-1" } ] }'const response = await fetch("https://api.tranzaq.com/api/v1/payout-batches", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "October salaries",
"speed": "Instant",
"items": [
{ "beneficiaryId": "8d2f6f40-5e7a-4b0e-b1a1-2f4c9d7e1a33", "amount": 1850.00, "reference": "SAL-1" }
]
}),
});
console.log(await response.json());var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/payout-batches");
request.Headers.Authorization = new("Bearer", token);
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent(@"{
""name"": ""October salaries"",
""speed"": ""Instant"",
""items"": [
{ ""beneficiaryId"": ""8d2f6f40-5e7a-4b0e-b1a1-2f4c9d7e1a33"", ""amount"": 1850.00, ""reference"": ""SAL-1"" }
]
}", Encoding.UTF8, "application/json");
var response = await http.SendAsync(request); // http.BaseAddress = "https://api.tranzaq.com"
Console.WriteLine(await response.Content.ReadAsStringAsync());import uuid, requests
response = requests.post(
"https://api.tranzaq.com/api/v1/payout-batches",
headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
json={
"name": "October salaries",
"speed": "Instant",
"items": [
{ "beneficiaryId": "8d2f6f40-5e7a-4b0e-b1a1-2f4c9d7e1a33", "amount": 1850.00, "reference": "SAL-1" }
]
},
)
print(response.json())Answer · 201
Response · test
{
"success": true,
"message": "Draft saved",
"code": 201,
"result": {
"id": "3f9c1c9e-6b1a-4d6f-9a77-0f6f3f3c2a10",
"batchReference": "PB-20261018-0007",
"batchName": "October salaries",
"status": "Draft",
"speed": "Instant",
"currency": "GHS",
"totalAmount": 1850.00,
"totalFees": 9.25,
"itemCount": 1,
"createdBy": "Tranzaq API",
"createdAt": "2026-10-18T10:15:00+00:00",
"submittedAt": null,
"approvedAt": null,
"completedAt": null,
"items": [
{
"id": "b3c5f0a2-3d1e-4a71-8f0e-1c2d3e4f5a6b",
"reference": "SAL-1",
"amount": 1850.00,
"feeAmount": 9.25,
"currency": "GHS",
"destinationType": "MobileMoney",
"maskedAccountNumber": "024****567",
"accountName": "Ama Owusu",
"network": "MTN",
"status": "Pending",
"failureCode": null,
"failureReason": null
}
],
"approvals": []
}
}Errors
- 400A row is wrong (the message says which: “Row 3: …”), or the Idempotency-Key header is missing.
- 403The business has not been approved for live payouts yet. Test mode is not affected.
Submit a batch
POST/api/v1/payout-batches/{id}/submitscope
payouts.writeSend a draft for approval. The money is reserved once the required people have approved it on the website. Submitting is safe to repeat: a batch that is no longer a draft answers 409.
Path
iduuidrequired | The batch id. |
POST /api/v1/payout-batches/{id}/submit · test
curl -X POST "https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/submit" \
-H "Authorization: Bearer $TOKEN"const response = await fetch("https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/submit", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/payout-batches/PASTE_ID/submit");
request.Headers.Authorization = new("Bearer", token);
var response = await http.SendAsync(request); // http.BaseAddress = "https://api.tranzaq.com"
Console.WriteLine(await response.Content.ReadAsStringAsync());import uuid, requests
response = requests.post(
"https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/submit",
headers={"Authorization": f"Bearer {token}"},
)
print(response.json())Answer · 200
Response · test
{
"success": true,
"message": "Submitted",
"code": 200,
"result": {
"id": "3f9c1c9e-6b1a-4d6f-9a77-0f6f3f3c2a10",
"batchReference": "PB-20261018-0007",
"batchName": "October salaries",
"status": "PendingApproval",
"speed": "Instant",
"currency": "GHS",
"totalAmount": 1850.00,
"totalFees": 9.25,
"itemCount": 1,
"createdBy": "Tranzaq API",
"createdAt": "2026-10-18T10:15:00+00:00",
"submittedAt": null,
"approvedAt": null,
"completedAt": null,
"items": [
{
"id": "b3c5f0a2-3d1e-4a71-8f0e-1c2d3e4f5a6b",
"reference": "SAL-1",
"amount": 1850.00,
"feeAmount": 9.25,
"currency": "GHS",
"destinationType": "MobileMoney",
"maskedAccountNumber": "024****567",
"accountName": "Ama Owusu",
"network": "MTN",
"status": "Pending",
"failureCode": null,
"failureReason": null
}
],
"approvals": []
}
}Errors
- 404No such batch.
- 409Only a draft can be submitted.
- 400A batch needs at least one payment.
- 403The business is not active.
Cancel a batch
POST/api/v1/payout-batches/{id}/cancelscope
payouts.writeCancel a batch that has not been sent yet. Reserved money returns to your available balance.
Path
iduuidrequired | The batch id. |
POST /api/v1/payout-batches/{id}/cancel · test
curl -X POST "https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/cancel" \
-H "Authorization: Bearer $TOKEN"const response = await fetch("https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/cancel", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/payout-batches/PASTE_ID/cancel");
request.Headers.Authorization = new("Bearer", token);
var response = await http.SendAsync(request); // http.BaseAddress = "https://api.tranzaq.com"
Console.WriteLine(await response.Content.ReadAsStringAsync());import uuid, requests
response = requests.post(
"https://api.tranzaq.com/api/v1/payout-batches/PASTE_ID/cancel",
headers={"Authorization": f"Bearer {token}"},
)
print(response.json())Answer · 200
Response · test
{
"success": true,
"message": "Batch cancelled",
"code": 200,
"result": {
"id": "3f9c1c9e-6b1a-4d6f-9a77-0f6f3f3c2a10",
"batchReference": "PB-20261018-0007",
"batchName": "October salaries",
"status": "Cancelled",
"speed": "Instant",
"currency": "GHS",
"totalAmount": 1850.00,
"totalFees": 9.25,
"itemCount": 1,
"createdBy": "Tranzaq API",
"createdAt": "2026-10-18T10:15:00+00:00",
"submittedAt": null,
"approvedAt": null,
"completedAt": null,
"items": [
{
"id": "b3c5f0a2-3d1e-4a71-8f0e-1c2d3e4f5a6b",
"reference": "SAL-1",
"amount": 1850.00,
"feeAmount": 9.25,
"currency": "GHS",
"destinationType": "MobileMoney",
"maskedAccountNumber": "024****567",
"accountName": "Ama Owusu",
"network": "MTN",
"status": "Pending",
"failureCode": null,
"failureReason": null
}
],
"approvals": []
}
}Errors
- 404No such batch.
- 409A batch that is already processing or finished can no longer be cancelled.