Skip to content

Requests and responses

The gateway speaks JSON over HTTPS. Every request and response uses application/json unless explicitly noted (the only exception today is /payments/card/3ds-callback, which also accepts application/x-www-form-urlencoded because Mastercard posts that way).

POST /api/v1/payments/collect HTTP/1.1
Host: app.api.gtwy.pdirect.com
Authorization: Bearer sess_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789
Content-Type: application/json
Accept: application/json
Accept-Language: en
Idempotency-Key: 8d3f0e2b-5c7d-4e9f-aab2-2e4f3d8c0b6e
X-Device-Fingerprint: 9f8e7d6c5b4a3928176054321aabbccdd11ee
{ "payment_method": "wallet", "user_info": "full", ... }
HeaderWhen
Authorization: Bearer …Every authenticated request. <key_id>:<merchant_secret> for /internal/sessions/create, <session_token> for everything else.
Content-Type: application/jsonRequired on every POST body.
Accept: application/jsonImplied; safe to send anyway.
Accept-LanguageOptional. Drives translated message fields in errors. Default fr.
Idempotency-KeyOptional but recommended on every POST. UUID v4. See Idempotency.
X-Device-FingerprintOptional. SHA-256 of stable device attributes. The Flutter SDK attaches this automatically.

Successful responses return 200, 201, or 202 with a JSON body whose top-level shape varies per endpoint. See the API reference for exact schemas.

Pattern: most response objects have a success: true field, a status string, and a transaction_id you can use for follow-up queries. Status codes:

StatusMeaning
200 OKSync success or sync failure (check the body’s success field for hosted-session card flows).
201 CreatedReturned only by /internal/sessions/create — emphasises that a new session row was created.
202 AcceptedCard payment is in flight (3DS challenge). The body contains a redirect_url you must navigate the customer to.
4xx / 5xxError envelope — see Errors.
  • Strings are UTF-8.
  • Amounts are decimal strings ("12.50", not 12.50 or 1250). The session binds the exact string — "1.00" and "1" are not equivalent at rebind time.
  • Currencies are lowercase ISO 4217 (usd, cdf, xof).
  • Phone numbers are E.164 ("+243998857000").
  • Dates and timestamps are ISO 8601 / RFC 3339 ("2026-05-05T10:15:00Z").
  • UUIDs are lowercase, hyphenated.

Decimal arithmetic in IEEE 754 floats has rounding edge cases that matter at the cent level. The gateway uses Decimal throughout and serialises to a string to avoid 12.50 → 12.5 lossy round-trips through JSON parsers. Treat amounts as opaque strings; do not parse them into floats unless you’re displaying.

Every error response follows the same envelope:

{
"error": true,
"error_code": "1101",
"message": "Invalid payment amount",
"timestamp": "2026-05-05T10:15:00Z",
"request_id": "req_8f3a4c2e9b1d7a6f",
"retryable": false
}

Branch on error_code. See Errors for the groups, the full table, and SDK-level mapping.

Send Accept-Language: en (or fr, es, ru, zh, ln) and the gateway will translate message fields in error responses. error_code values are not localised — they are stable identifiers, not display text.

The SDKs accept acceptLanguage per checkout and propagate it to every request. See Localization and currencies.