Every product in MarzPay runs on one REST API. Once you can authenticate and parse the money envelope, the rest of the endpoints follow the same pattern.

Authentication

Build the value from your API key and secret, joined by a colon:
A 401 almost always means the base64 value is stale, was double encoded, or contains a trailing newline. Recompute it in the same environment that sends the request.

Request conventions

string
required
Market code: UG, KE, RW, CD, ZM, CM, BJ, CI, GA, CG, SN, or SL. This decides the wallet and the payout rail. Congo-Brazzaville is CG, the DRC is CD.
string
Optional everywhere except the DRC, where you must send CDF (default) or USD. For every other market the currency follows the country: UGX, KES, RWF, ZMW, XAF, XOF, SLE.
string
required
A UUID v4 that you generate, unique per business across all API transactions, maximum 50 characters. Reuse returns DUPLICATE_REFERENCE. This is the key we echo on callbacks, so treat it as your idempotency key.
string
E.164 with the country code, for example +256700000000 or +254710000000. Required for mobile money, omitted for card collections.
number
Major currency units, not cents. 1000 is UGX 1,000. Uganda collections accept 500 to 10,000,000.
array
Up to 10 objects, each with one field and value, plus optional isPII: true. Echoed on the create response and at the top level of callbacks.
string
Per-transaction webhook target, maximum 255 characters, must be https. Final statuses only, both success and failure.

The money envelope

Every amount in a response is an object, never a bare number:
What the customer paid, or what the recipient was sent. Unchanged from what you requested.
The MarzPay fee, in the same shape. Zero when no fee applies, for example airtime at cost.
amount minus charge: what is credited to your merchant wallet. Present on collection payloads.
Render formatted in a UI. Do arithmetic with raw, and read currency from the same object instead of assuming the market currency.

Response shapes

Create calls return status, a human message, and a data object:
Errors use status: "error" with a stable error_code and, for field validation, an errors map:
Transaction detail responses reuse the webhook envelope (event_type, transaction, plus a collection or disbursement object). Build one parser and use it for both paths.

Statuses

Callbacks fire only for final statuses. A create call that returns processing still needs a webhook or a poll.

Errors you will actually hit

Pagination

List endpoints accept page and per_page and return a pagination block:
per_page is capped at 100. Filters vary by product: type, status, provider, start_date, end_date, reference, and msisdn.

Permissions and limits

IP whitelist

Balance, send money, bank transfer, and airtime endpoints require your server IP on the API whitelist. Add it in dashboard settings before you deploy.

Subscriptions

Every provider product is subscribed per market in the marketplace. GET /collect-money/services shows what your business can currently accept.

Amount limits

Uganda collections accept 500 to 10,000,000 UGX. Other markets use your business limits, which you can read from the product services endpoints.

One transfer at a time

Bank transfers allow a single pending or processing transfer per business. Wait for the outcome before creating the next.

Next: sandbox mode

Exercise all of this without moving real money.