Accepting payments
USSD push, Wave redirect, OTP by SMS and OTP by USSD.
Mobile Money payment flows
The flow depends on the country, operator and provider. Do not hard-code it from the brand name: load /countries, call /collect, and react to the response.
| Flow | Initial response | Customer action |
|---|---|---|
| USSD push | 202, status: "pending" | Approve the prompt on the phone |
| Redirect (Wave) | 202, flow: "wave", wave_url | Open wave_url and approve |
| OTP by SMS | 400, error: "otp_required", reference | Read the SMS code, re-send with otp |
| OTP by USSD | 400, error: "otp_required", reference, ussd_code | Dial ussd_code, enter the code, re-send with otp |
In every case the payment remains pending until confirmed.
1. USSD push
Call /collect → 202 pending. Show a "waiting for approval" screen. Receive the webhook (or poll).
2. Wave and redirects
json
1{2 "status": "pending",3 "flow": "wave",4 "wave_url": "https://pay.wave.com/c/…",5 "transaction_id": "…",6 "reference": "PLK-…"7}Open wave_url exactly as returned (do not build it yourself), then wait for the webhook.
3. OTP
First request — same body as a normal collect:
json
1{2 "error": "otp_required",3 "message": "OTP required. Dial the code shown to get your OTP, then retry with 'otp' and 'reference'.",4 "reference": "PLK-7XK2M9QPLA",5 "ussd_code": "#144*82#"6}Display ussd_code (when present) to the customer. After they enter the OTP, re-send the same request with:
reference= thereferencefrom theotp_requiredresponse (replaces your order reference),otp= the code the customer received.
bash
1curl -X POST https://paylinky.vercel.app/api/v1/collect \2 -H "Authorization: Bearer $PAYLINKY_KEY" \3 -H "Content-Type: application/json" \4 -d '{5 "amount": 5000,6 "currency": "XOF",7 "country_code": "CI",8 "operator": "Orange Money",9 "phone": "+2250XXXXXXXX",10 "reference": "PLK-7XK2M9QPLA",11 "otp": "123456"12 }'If the OTP session expired you receive 400 otp_expired/invalid_reference — start a new collection with a new reference.
Handling responses
| Code | Meaning | What to do |
|---|---|---|
202 | Accepted, pending | Wait for webhook / poll |
200 | Final result immediately (sandbox) or idempotent replay | Read status |
400 otp_required | Needs OTP | Show OTP form, retry |
400 invalid_otp | Wrong OTP | Ask again |
409 reference_conflict | Reference reused with different data | Use a unique reference |