Mobile top-up
Prepaid credit, postpaid bills and offers for Mobilis, Djezzy and Ooredoo.
Plans
GET /v3/mobile/plans lists what you can send. There are three kinds of plan per operator:
| Plan code | What it does | Needs |
|---|---|---|
PREPAID_MOBILIS, PREPAID_DJEZZY, PREPAID_OOREDOO | Adds credit to a prepaid line. | amount between min_amount and max_amount |
FACTURE_MOBILIS, FACTURE_DJEZZY, FACTURE_OOREDOO | Pays a postpaid bill. | amount between min_amount and max_amount |
INTERNATIONAL_MOBILIS | Adds Mobilis international credit. Mobilis only. | amount between min_amount and max_amount |
OFFER_MOBILIS, OFFER_DJEZZY, OFFER_OOREDOO | Activates an operator offer or package. | offer_id from GET /v3/mobile/offers |
Plans with isEnabled: false cannot be sent right now. You can cache the plan list for a few minutes.
{
"dynamicPlans": [
{ "code": "PREPAID_DJEZZY", "name": "Djezzy prepaid credit", "operator": "Djezzy", "type": "topup", "isEnabled": true, "min_amount": 100, "max_amount": 50000 }
],
"fixedPlans": [],
"offerPlans": [
{ "code": "OFFER_DJEZZY", "name": "Djezzy offers and packages", "operator": "Djezzy", "type": "offer", "isEnabled": true, "requires": "offer_id" }
]
}Phone numbers
MSSIDN is a 10-digit Algerian mobile number with the leading 0. No spaces and no +213. Send the plan of the number's operator.
| Prefix | Operator | Plans |
|---|---|---|
05… | Ooredoo | *_OOREDOO |
06… | Mobilis | *_MOBILIS |
07… | Djezzy | *_DJEZZY |
01… | Ooredoo Enterprise (business lines) | *_OOREDOO only; any other plan is refused with ERR_PHONE |
Sending credit or a bill
curl -X POST "$API_URL/v3/mobile/send" \
-H "X-Access-Token: $API_KEY" -H "Content-Type: application/json" \
-d '{"plan_code":"PREPAID_MOBILIS","MSSIDN":"0600000009","amount":1000,"ref":"order-2001"}'The answer comes back at once with topupId and topupRef. It means the top-up was accepted, not delivered. Read the result with check-id or check-ref.
Sending an offer
Offers depend on the number, so ask the operator first:
curl "$API_URL/v3/mobile/offers?operator=mobilis&MSSIDN=0600000009" -H "X-Access-Token: $API_KEY"{
"MSSIDN": "0600000009",
"operator": "Mobilis",
"plan_code": "OFFER_MOBILIS",
"expires_at": "2026-11-15T11:00:00.000Z",
"offers": [
{ "offer_id": "eyJ2IjoxLCJ1Ijoi…", "name": "Mix 500", "amount": 500, "debt_amount": 0, "total_amount": 500, "category": "regular" },
{ "offer_id": "eyJ2IjoxLCJ1Ijoi…", "name": "Internet 1 Go", "amount": 300, "debt_amount": 0, "total_amount": 300, "category": "internet" }
]
}Then send the chosen offer_id with the matching OFFER_* plan:
curl -X POST "$API_URL/v3/mobile/send" \
-H "X-Access-Token: $API_KEY" -H "Content-Type: application/json" \
-d '{"plan_code":"OFFER_MOBILIS","MSSIDN":"0600000009","offer_id":"eyJ2IjoxLCJ1Ijoi…","ref":"order-2002"}'An offer_id is signed, valid for 30 minutes, and only works for the same number and operator. The offers call asks the operator in real time and can take a few seconds.
Djezzy Tranquilo debt
Some Djezzy lines owe a Tranquilo debt. Activating an offer pays that debt too, so each offer shows:
amount: the offer price.debt_amount: the debt paid with it (0when there is none).total_amount: what your balance pays,amount + debt_amount.
Show total_amount to your customer before they confirm. If your balance is below total_amount, the send is refused with INSUFFICIENT_BALANCE and nothing is charged.
Statuses
| Status | Meaning | Final | Charged |
|---|---|---|---|
| PENDING | Accepted and queued. | No | No |
| HANDLING | Being sent to the operator. | No | No |
| DEBT_PENDING | The line has an unpaid debt. Waiting for your decision: see Line debt. | No, act on it | No |
| COMPLETED | Delivered. | Yes | Yes |
| REFUNDED | Failed. refund_message says why. | Yes | No |
| UNKNOWN_ERROR | The operator did not confirm the result. Our team checks it. | Yes, for polling | Maybe |
Your balance is checked when you send, and charged only when the top-up is delivered. balance_amount shows what was taken from your balance.
UNKNOWN_ERROR is not a failure
Do not refund your customer on UNKNOWN_ERROR. The credit may have arrived. Our team settles these to COMPLETED or REFUNDED, usually within a few hours. Re-check them from a background job, for example every hour.
Line debt (SABBAQLI)
Some lines owe the operator an unpaid advance (SABBAQLI). Before topping them up, the operator asks whether to pay that debt. This mostly happens on Ooredoo lines. The top-up then stops as DEBT_PENDING:
{
"_id": "F00012345",
"ref": "order-2001",
"status": "DEBT_PENDING",
"plan_code": "PREPAID_OOREDOO",
"MSSIDN": "0500000004",
"topup_amount": 500,
"balance_amount": 0,
"debt_amount": 100,
"debt_message": "Le client dispose d'un emprunt non-remboursé de 100 DA de service SABBAQLI. Voulez-vous le payer ?",
"debt_options": [
{ "choice": "PAY_ALL", "amount": 600, "available": true },
{ "choice": "PAY_OPERATION_ONLY", "amount": 500, "available": true },
{ "choice": "PAY_DEBT_ONLY", "amount": 100, "available": true },
{ "choice": "CANCEL", "amount": 0, "available": true }
],
"debt_expires_at": "2026-11-15T11:00:00.000Z"
}Stop polling, ask your customer (or apply your own rule), and answer:
curl -X POST "$API_URL/v3/mobile/resolve-debt" \
-H "X-Access-Token: $API_KEY" -H "Content-Type: application/json" \
-d '{"ref":"order-2001","choice":"PAY_ALL"}'| Choice | What happens | Your balance pays |
|---|---|---|
PAY_ALL | The top-up is sent and the debt is paid. | top-up + debt |
PAY_OPERATION_ONLY | The top-up is sent; the debt stays on the line. | top-up |
PAY_DEBT_ONLY | Only the debt is paid (a top-up equal to the debt). | debt |
CANCEL | Nothing is sent. The top-up ends REFUNDED. | nothing |
debt_options[].amount is the exact price of each choice, and available: false marks a choice you can't use (for example when the operator did not say how much is owed). The answer returns the top-up, now PENDING. Keep polling it as usual until it is final.
- Unanswered: a
DEBT_PENDINGtop-up is cancelled atdebt_expires_at(30 minutes) and endsREFUNDED. Nothing is charged. - Never pause: send
"on_debt": "CANCEL"with the top-up and a debt question cancels it at once (REFUNDED). The default is"WAIT". - Answering twice, or answering a top-up that is not
DEBT_PENDING, returns409 NOT_DEBT_PENDING.
Example result
{
"success": true,
"data": {
"_id": "F00012345",
"ref": "order-2001",
"status": "COMPLETED",
"plan_code": "PREPAID_MOBILIS",
"MSSIDN": "0600000009",
"topup_amount": 1000,
"balance_amount": 1000,
"created_at": "2026-11-15T10:30:00.000Z"
},
"meta": { "timestamp": "2026-11-15T10:30:12.000Z" },
"requestId": "req_8fK2mQx7Lp0aZ3nV1cWb"
}Listing top-ups
GET /v3/mobile/list?page=1&pageSize=20 returns top-ups sent with your API keys, newest first. Filter a period with from and to (ISO 8601, both together).