curl --request POST \
--url https://api.jenzy.com/v1/payouts/momo \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"amount_mwk": 250000,
"institution_id": 112400,
"mobile_number": "265991234567",
"beneficiary_name": "<string>"
}
'import requests
url = "https://api.jenzy.com/v1/payouts/momo"
payload = {
"amount_mwk": 250000,
"institution_id": 112400,
"mobile_number": "265991234567",
"beneficiary_name": "<string>"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount_mwk: 250000,
institution_id: 112400,
mobile_number: '265991234567',
beneficiary_name: '<string>'
})
};
fetch('https://api.jenzy.com/v1/payouts/momo', 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.jenzy.com/v1/payouts/momo",
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_mwk' => 250000,
'institution_id' => 112400,
'mobile_number' => '265991234567',
'beneficiary_name' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-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://api.jenzy.com/v1/payouts/momo"
payload := strings.NewReader("{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
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.jenzy.com/v1/payouts/momo")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jenzy.com/v1/payouts/momo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"amount_mwk": "250000.00",
"fee": "2710.00",
"rail": "bank",
"status": "succeeded",
"destination": {
"institution_id": 123,
"account_number": "<string>",
"beneficiary_name": "<string>"
},
"failure": {
"code": "recipient_account_invalid",
"message": "<string>"
},
"created_at": "2023-11-07T05:31:56Z",
"terminal_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}Create a mobile money payout
Hold funds and queue a payout to a mobile money number. The endpoint is the rail — there is no rail field in the body. Requires an Idempotency-Key.
curl --request POST \
--url https://api.jenzy.com/v1/payouts/momo \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"amount_mwk": 250000,
"institution_id": 112400,
"mobile_number": "265991234567",
"beneficiary_name": "<string>"
}
'import requests
url = "https://api.jenzy.com/v1/payouts/momo"
payload = {
"amount_mwk": 250000,
"institution_id": 112400,
"mobile_number": "265991234567",
"beneficiary_name": "<string>"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount_mwk: 250000,
institution_id: 112400,
mobile_number: '265991234567',
beneficiary_name: '<string>'
})
};
fetch('https://api.jenzy.com/v1/payouts/momo', 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.jenzy.com/v1/payouts/momo",
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_mwk' => 250000,
'institution_id' => 112400,
'mobile_number' => '265991234567',
'beneficiary_name' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-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://api.jenzy.com/v1/payouts/momo"
payload := strings.NewReader("{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
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.jenzy.com/v1/payouts/momo")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jenzy.com/v1/payouts/momo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount_mwk\": 250000,\n \"institution_id\": 112400,\n \"mobile_number\": \"265991234567\",\n \"beneficiary_name\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"amount_mwk": "250000.00",
"fee": "2710.00",
"rail": "bank",
"status": "succeeded",
"destination": {
"institution_id": 123,
"account_number": "<string>",
"beneficiary_name": "<string>"
},
"failure": {
"code": "recipient_account_invalid",
"message": "<string>"
},
"created_at": "2023-11-07T05:31:56Z",
"terminal_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}{
"error": {
"code": "validation_error",
"message": "<string>"
}
}Authorizations
Your Jenzy API key: Authorization: Bearer jz_live_…
Headers
Required. A key you mint per payout intent (a UUID works). Replays of the same key + body return the original response byte-for-byte; the same key with a different body is a 409.
Body
Amount in MWK. Either a JSON integer of whole kwacha, or an exact decimal string with up to 2 decimal places ("100000.05"). Fractional JSON numbers are rejected — send a string. More than 2 decimal places is rejected: the tambala is the atom.
250000
From GET /institutions — one whose rail is momo.
112400
The wallet number in full international form: 265 then 9 (Airtel Money) or 8 (TNM Mpamba) then 8 digits. Sent to the provider exactly as given — a number missing the country code is rejected, never corrected.
1^265[89][0-9]{8}$"265991234567"
Who the money is for — required, and sent to the provider as given.
1Response
Accepted: funds are held and the payout is queued for submission. Track it via webhooks or GET /payouts/{id}.
Payout id — your handle for polling and support.
The amount instructed — exact decimal string at 2 decimal places.
"250000.00"
What the provider charged for this payout, passed through to you at cost — an exact decimal string at two decimal places (fees are not whole kwacha), so parse it with a decimal library and never a float.
null means the fee is not known — usually because the payout is still in flight, but a terminal payout can also read null when the provider reported no fee for it. It never means free, so do not treat null as zero, and do not treat it as proof the payout is still moving — status is what tells you that.
A failed payout reads "0.00" — fees apply to successful transfers only — and a reversed payout keeps the fee it was charged, because it did succeed before it was clawed back.
Use POST /fees/quote to know the cost BEFORE you send: this field cannot tell you in advance, and your balance must cover the amount plus the fee.
"2710.00"
bank, momo Lifecycle: received → validated → held → submitted → pending → succeeded | failed. succeeded, failed and reversed are terminal. reversed means the payout succeeded and the provider then clawed the transfer back — it is not a failure and carries no failure object.
received, validated, held, submitted, pending, succeeded, failed, reversed "succeeded"
The destination snapshot as validated at accept — shape follows rail.
- Option 1
- Option 2
Show child attributes
Show child attributes
Set exactly when status is failed; null otherwise.
Show child attributes
Show child attributes
When the payout first reached a terminal state. A payout that is later reversed keeps the timestamp of its original settlement — this never moves once set.