API reference
API reference
A JSON API over HTTPS. Every amount is an integer in cents of South African rand, and every country is a two-letter ISO code.
Overview
| Base URL | https://hlawula.co.za |
| Format | JSON in and out, camelCase field names |
| Money | Integer cents, ZAR. 99900 is R 999.00 |
| Errors | 4xx with { "error": "code", "message": "..." } |
| Auth | None in the demo. Secret keys per merchant are planned. |
{ "error": "card_invalid", "message": "Enter a valid card number." }Checkout sessions
Create a session
POST/api/checkout/sessions
planIdstring, required
plan_starter, plan_pro or plan_scale.
emailstring
Buyer email. Shown on the invoice.
countrystring
Buyer country. Decides the tax line. Defaults to ZA.
{
"id": "cs_live_0015a4a0ff9d",
"status": "open",
"email": "thandi@example.co.za",
"country": "ZA",
"plan": { "id": "plan_pro", "name": "Pro", "priceCents": 99900, "interval": "month", "trialDays": 14 },
"subtotalCents": 99900,
"taxLines": [
{ "label": "VAT — 15%", "jurisdiction": "South Africa — SARS", "rate": 0.15, "amountCents": 14985, "collectedAndRemitted": true }
],
"totalCents": 114885,
"currency": "ZAR",
"seller": { "legalName": "Hlawula MoR (Pty) Ltd", "registrationNumber": "2026/184220/07", "vatNumber": "4910263842" }
}Errors: 400 unknown_plan.
Retrieve a session
GET/api/checkout/sessions/{id}
Returns the session in the same shape. 404 session_not_found if it doesn't exist.
Update a session
PUT/api/checkout/sessions/{id}
countrystring
New buyer country. Tax is recalculated.
emailstring
New buyer email.
Errors: 404 session_not_found, 400 already_paid.
Pay a session
POST/api/checkout/sessions/{id}/pay
methodstring
apple_pay, google_pay, samsung_pay, card, capitec_pay, absa_pay, nedbank_direct_eft or pay_by_bank. Defaults to card.
walletTokenstring
Wallets only. The encrypted token from the device.
cardNumber, expiry, cvc, namestring
Card only. Expiry as MM/YY.
mobilestring
Capitec Pay and Absa Pay. South African cellphone number.
bankstring
Pay by bank. One of Absa, Capitec, Discovery Bank, FNB, Investec, Nedbank, Standard Bank, TymeBank.
{
"outcome": "paid",
"paymentMethod": { "id": "apple_pay", "name": "Apple Pay", "label": "apple pay" },
"receipt": {
"id": "txn_1061", "country": "ZA", "amountCents": 99900, "taxCents": 14985,
"status": "succeeded", "method": "apple pay", "createdAt": "2026-11-09T11:50:36Z"
},
"invoice": {
"number": "INV-2026-0341",
"seller": "Hlawula MoR (Pty) Ltd",
"vatNumber": "4910263842",
"buyerEmail": "thandi@example.co.za",
"buyerCountry": "ZA",
"planName": "Pro",
"subtotalCents": 99900,
"lines": [ { "label": "VAT — 15%", "amountCents": 14985 } ],
"totalCents": 114885,
"issuedAt": "2026-11-09T11:50:36Z"
}
}Errors: 404 session_not_found, 400 already_paid, plus the payment method errors listed under Payment methods.
Payment methods
List payment methods
GET/api/payment-methods
countryquery string
Optional. Sets available on each method for this buyer country.
[
{ "id": "apple_pay", "name": "Apple Pay", "kind": "wallet", "settlement": "Instant", "countries": null, "available": true },
{ "id": "capitec_pay", "name": "Capitec Pay", "kind": "bank_app", "settlement": "Instant", "countries": ["ZA"], "available": false }
]kind is wallet, card, bank_app or bank_transfer. countries: null means available everywhere.
Subscriptions
List subscriptions
GET/api/subscriptions
All subscriptions, latest billing date first. See Subscriptions and dunning for the fields.
Retry a failed renewal
POST/api/subscriptions/{id}/retry
{ "outcome": "recovered", "message": "Payment recovered via aggregator retry.", "subscription": { "id": "sub_1002", "status": "active" } }outcome is recovered or failed. Errors: 404 subscription_not_found.
List plans
GET/api/plans
The plans buyers can subscribe to, with priceCents excluding tax.
Tax
Quote tax
GET/api/tax/quote
countryquery string, required
Buyer country.
amountquery integer, required
Amount in cents, zero or more.
Returns subtotalCents, taxLines and totalCents. Errors: 400 amount_invalid.
Payouts
List payouts
GET/api/payouts
All payouts, newest first, with gross, each deduction, net, status and bank reference.
Run a payout
POST/api/payouts/run
Pays out everything settled since the last payout. Errors: 400 nothing_to_settle.
Reporting
Dashboard summary
GET/api/summary
MRR, 30-day gross volume, active and past-due subscription counts, the next payout estimate and a 14-day revenue series.
Recent transactions
GET/api/transactions
The latest 25 payments with customer, country, amount, tax, method and status.
Seller details
GET/api/config
Hlawula's legal name, registration number, VAT number, settlement bank and aggregator.
Health check
GET/api/health
{ "status": "ok", "service": "hlawula-mor", "time": "2026-11-09T12:00:00Z" }Planned