Hosted checkout
Create a payment
One resource, one call. You name the offer and where to come back; PayLumia returns the checkout URL.
POST/v1/payments
Request
Headers: Authorization: Bearer … and Idempotency-Key (required, 8–255 characters, 24-hour replay window).
modeenumrequired- Always
HOSTEDfor the hosted checkout. offerUidstringrequired- The offer to sell, as configured in your application. Price, currency, period and trial come from the offer.
returnUrlurirequired- Where the browser goes when checkout ends. For the customer’s comfort only, never as proof of payment.
presentationenumredirect(default) for a full-page checkout,embeddedto mount it in your page.prefill.msisdnE.164 string- Pre-fills the mobile number on the checkout.
prefill.msisdnEditableboolean- Defaults to
true. Setfalseto lock the number;prefill.msisdnis then required. operatorstring- Hint when you already know it, for example
ORANGE_TN. It cannot select an operator the offer is not available on. metadataobject ≤ 20 keys- Your correlation data (order id, user id). Echoed on reads and webhooks.
Not allowed in hosted mode
amount—not allowed- Prices are fixed on the offer in v1.
msisdn—not allowed- Use
prefill.msisdn. A number alone is never consent. productUid—not allowed- Derived from the offer and returned in the response.
notifyUrl—not allowed- Webhooks go to the URL configured on your environment.
curl https://api.sandbox.paylumia.com/v1/payments \
-H "Authorization: Bearer $PAYLUMIA_TOKEN" \
-H "Idempotency-Key: order-8891" \
-H "Content-Type: application/json" \
-d '{
"mode": "HOSTED",
"offerUid": "premium_daily",
"returnUrl": "https://app.example.tn/return",
"presentation": "redirect",
"prefill": { "msisdn": "+21620123456", "msisdnEditable": true },
"metadata": { "orderRef": "order-8891" }
}'Response
A payment in REQUIRES_ACTION, with the checkoutUrl to open.
{
"success": true,
"data": {
"object": "payment",
"paymentUid": "pay_4mK9pQeRw2Ns6TfXb1Zy0a",
"mode": "HOSTED",
"status": "REQUIRES_ACTION",
"checkoutUrl": "https://pay.sandbox.paylumia.com/c/pay_4mK9pQeRw2Ns6TfXb1Zy0a",
"productUid": "premium",
"offerUid": "premium_daily",
"expiresAt": "2026-09-20T15:30:00Z",
"metadata": { "orderRef": "order-8891" }
}
}| Field | Notes |
|---|---|
paymentUid | Opaque id of this payment session. Keep it with your order. |
checkoutUrl | Hosted checkout for this environment: {checkout-host}/c/{paymentUid} (sandbox pay.sandbox…, production pay.paylumia.com). |
status | REQUIRES_ACTION until the customer acts. See the lifecycle. |
productUid | The entitlement the offer grants. Use it to unlock access. |
expiresAt | After this time an untouched session expires. |
orderId | Appears once money has moved. |
subscriberUid | Appears once the customer is identified. Scoped to your application; never the phone number. |
What the offer decides

| Offer type | What a payment does | subscriptionUid |
|---|---|---|
SUBSCRIPTION | Consent, then a subscription with renewals run by PayLumia | Yes |
CONSUMABLE | One charge. Repeatable: coin packs, passes, credits | No |
NON_CONSUMABLE | One charge. Permanent unlock | No |
Changing plans
Offer changes are not a payment. Don’t start a second payment to switch a subscriber from one plan to another.