Make Payment
POST
Plaintext request body — EcoCash example (before encryption)
Terminal window
Creates and processes a transaction for a specific payment method in one call. This is the core request in the seamless flow — your UI collects the method’s required fields and submits them directly, without redirecting to a Pesepay-hosted page.
| Environment | URL |
|---|---|
| Production | https://api.pesepay.com/api/payments-engine/v2/payments/make-payment |
| Sandbox | https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment |
How it fits
Section titled “How it fits”- Pick a payment method and its required fields.
- Build and encrypt the request body.
- POST it with your integration key in the
authorizationheader. - Decrypt the response, store the
referenceNumber, and wait for the result callback or pollpollUrl— the customer still has to approve the payment on their side.
Headers
Section titled “Headers”| Parameter | Type | Required | Description |
|---|---|---|---|
authorization | string | Yes | Your application’s integration key |
content-type | string | Yes | Must be application/json |
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
amountDetails | object | Yes | { amount: number, currencyCode: string } |
paymentMethodCode | string | Yes | e.g. PZW211 for EcoCash, PZW212 for InnBucks — see Payment Method Codes |
paymentMethodRequiredFields | object | Yes | The chosen method’s required fields as key/value pairs. Send {} for methods that need none (InnBucks, PayGo). Keys come from the method’s Payment Methods page or from Get Payment Methods by Currency |
reasonForPayment | string | Yes | A short summary of the transaction |
resultUrl | string | Yes | Where Pesepay posts the final result — see The Result Callback |
returnUrl | string | No | Where the customer is sent after the payment. Defaults to resultUrl if omitted |
merchantReference | string | No | Your own order/invoice reference, echoed back on the transaction |
customer | object | No | { email, phoneNumber, name } |
paymentMetadata | object | No | String key/value pairs carried on the transaction and returned as transactionMetadata on the result. Required on an application with split payments, which must carry beneficiaryMerchantEmail |
{ "amountDetails": { "amount": 10.00, "currencyCode": "USD" }, "merchantReference": "ORDER-1042", "reasonForPayment": "Order #1042 — running shoes", "resultUrl": "https://example.com/payments/result", "returnUrl": "https://example.com/payments/return", "paymentMethodCode": "PZW211", "customer": { "email": "customer@example.com", "phoneNumber": "0777777777", "name": "Jane Customer" }, "paymentMethodRequiredFields": { "customerPhoneNumber": "0777777777" }}Code examples
Section titled “Code examples”# Encrypt your JSON body first (see the Encryption Guide), then:curl -X POST https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment \ -H "authorization: YOUR_INTEGRATION_KEY" \ -H "content-type: application/json" \ -d '{"payload": "ENCRYPTED_BASE64_STRING"}'const body = { amountDetails: { amount: 10.0, currencyCode: 'USD' }, merchantReference: 'ORDER-1042', reasonForPayment: 'Order #1042 — running shoes', resultUrl: 'https://example.com/payments/result', returnUrl: 'https://example.com/payments/return', paymentMethodCode: 'PZW211', customer: { email: 'customer@example.com', phoneNumber: '0777777777', name: 'Jane Customer', }, paymentMethodRequiredFields: { customerPhoneNumber: '0777777777' },};
const response = await fetch( 'https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment', { method: 'POST', headers: { authorization: 'YOUR_INTEGRATION_KEY', 'content-type': 'application/json', }, body: JSON.stringify({ payload: encrypt(body, ENCRYPTION_KEY) }), });
const { payload } = await response.json();const transaction = decrypt(payload, ENCRYPTION_KEY);import requests
body = { "amountDetails": {"amount": 10.00, "currencyCode": "USD"}, "merchantReference": "ORDER-1042", "reasonForPayment": "Order #1042 — running shoes", "resultUrl": "https://example.com/payments/result", "returnUrl": "https://example.com/payments/return", "paymentMethodCode": "PZW211", "customer": { "email": "customer@example.com", "phoneNumber": "0777777777", "name": "Jane Customer", }, "paymentMethodRequiredFields": {"customerPhoneNumber": "0777777777"},}
response = requests.post( "https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment", json={"payload": encrypt(body, ENCRYPTION_KEY)}, headers={ "authorization": "YOUR_INTEGRATION_KEY", "content-type": "application/json", },)
transaction = decrypt(response.json()["payload"], ENCRYPTION_KEY)<?php$body = [ 'amountDetails' => ['amount' => 10.00, 'currencyCode' => 'USD'], 'merchantReference' => 'ORDER-1042', 'reasonForPayment' => 'Order #1042 — running shoes', 'resultUrl' => 'https://example.com/payments/result', 'returnUrl' => 'https://example.com/payments/return', 'paymentMethodCode' => 'PZW211', 'customer' => [ 'email' => 'customer@example.com', 'phoneNumber' => '0777777777', 'name' => 'Jane Customer', ], 'paymentMethodRequiredFields' => ['customerPhoneNumber' => '0777777777'],];
$ch = curl_init('https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment');curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'payload' => encrypt($body, $encryptionKey),]));curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'authorization: YOUR_INTEGRATION_KEY', 'content-type: application/json',]);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);curl_close($ch);
$transaction = decrypt($response['payload'], $encryptionKey);String bodyJson = """ {"amountDetails":{"amount":10.00,"currencyCode":"USD"}, "merchantReference":"ORDER-1042", "reasonForPayment":"Order #1042 — running shoes", "resultUrl":"https://example.com/payments/result", "returnUrl":"https://example.com/payments/return", "paymentMethodCode":"PZW211", "customer":{"email":"customer@example.com","phoneNumber":"0777777777","name":"Jane Customer"}, "paymentMethodRequiredFields":{"customerPhoneNumber":"0777777777"}}""";
String encryptedPayload = encrypt(bodyJson, encryptionKey);
HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.test.sandbox.pesepay.com/payments-engine/v2/payments/make-payment")) .header("authorization", "YOUR_INTEGRATION_KEY") .header("content-type", "application/json") .POST(HttpRequest.BodyPublishers.ofString( "{\"payload\":\"" + encryptedPayload + "\"}" )) .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());String transactionJson = decrypt(extractPayload(response.body()), encryptionKey);Response
Section titled “Response”Decrypt the payload to get the transaction result. It is the same
object you get from Check Payment Status and
in the result callback — the
result callback page has the complete
field list and the amountDetails breakdown. There is no redirectUrl on
it.
| Field | Type | Description |
|---|---|---|
referenceNumber | string | Store this — used to track status and match result callbacks |
pollUrl | string | A ready-made Check Payment Status URL for this transaction |
transactionStatus | string | See Transaction statuses |
transactionStatusCode | number | Numeric equivalent of transactionStatus |
transactionStatusDescription | string | Human-readable description of the status |
amountDetails | object | Amounts and fees applied to the transaction |
transactionMetadata | object | String key/value pairs carried on the transaction |