Introduction
Bill Payment lets you pay Algerian utility and telecom bills on behalf of your own customers. You ask a biller what an account owes, you pay one of the bills that comes back, you follow it to a final state, and you keep the receipt. The whole product is five calls. This page is the map; each step below links to a guide with working code in cURL, Node.js, Python and PHP.Bill Payment lives on
https://billapi.oneclickdz.com — a different base URL from the rest of the platform. The authentication header is the same one you already use: X-Access-Token.How it works
The five steps
1
Check the biller is available
Read the availability map and hide any biller that is
UNAVAILABLE before your customer starts filling in a form.→ Step 1: Partners and accounts2
Discover what is owed
Send the partner, the account identifier and your own
ref. You get a transactionId back; the bills arrive on that transaction a moment later.→ Step 2: Discovering bills3
Pay one bill
Pick a
billId from bills[], show your customer amount + fee, and submit the payment with a new ref.→ Step 3: Paying bills4
Poll until the status is final
SUCCESS, FAILED or REFUNDED. UNKNOWN means keep polling — never refund your customer and never retry the payment while it lasts.→ Step 4: Status polling5
Store the receipt and reconcile
Download the receipt, store it with
operationId, and reconcile daily against your own ledger.→ Step 5: Receipts and reconciliationWhat you need to know
Everything is asynchronous
POST /v3/bills/discover and POST /v3/bills/pay both answer 200 immediately. That 200 means accepted, not done.
The billers and their identifiers
Five billers, each with one identifier field. Send the field that belongs to the partner; the API returns the same field back on every transaction.SEAAL and AADL are currently UNAVAILABLE in both sandbox and production. Read the availability map rather than hard-coding this.
→ Identifier rules, formats and examples
The seven statuses
→ The full state machine and a production-grade poller
Fees and the 200 DZD floor
Every bill carries its own money fields:-
amount— what the biller is owed, in DZD. -
fee— the OneClickDz service fee, a percentage of the amount clamped between a minimum and a maximum, set per biller:In practice most bills pay the minimum: 0.5% only exceeds 30 DZD above a 6,000 DZD bill. These rates are configuration and can be adjusted, so readfeefrom the response rather than recomputing it. -
total—amount + fee, the figure debited from your balance.
bills[]. A READY transaction with an empty bills[] therefore means either “nothing is due” or “everything due is below the floor” — the API does not distinguish. Tell your customer “no bills are payable right now”, not “you owe nothing”.
Your reference is your safety net
ref is required on both discover and pay, is at most 100 characters, and must be unique among your live transactions for that biller. Reusing one answers 403 DUPLICATED_REF.
Derive it from something you already store, so that after a timeout you can always ask what that ref became instead of sending the request again.
Use a different
ref for the discovery and for the payment. The transaction keeps its original discovery ref, and that is the one by-ref looks up.Sandbox
Sandbox uses the same host, the same routes, the same envelope and the same lifecycle. The only difference is that a sandbox key never reaches a biller and never moves money. The outcome you get is chosen by the account identifier you send, so you can reproduce a decline, a refund and an unconfirmed payment on demand. Every key is bound to one environment. Call Validate API Key and readkey.type to prove which one you are holding.
→ Every sandbox scenario, and a go-live checklist
Key points
200 is an acknowledgement, not an outcome
200 is an acknowledgement, not an outcome
Both write endpoints accept the work and answer immediately. The result lives in the transaction’s
status.→ Step 4: Status pollingNever retry a payment on UNKNOWN
Never retry a payment on UNKNOWN
UNKNOWN means the outcome is not confirmed yet. Keep polling — it resolves to SUCCESS or REFUNDED. Refunding your own customer or resending the payment while it lasts is how money is lost twice.→ Handling UNKNOWNLook up, do not resend
Look up, do not resend
Every timeout, every
DUPLICATED_REF, every unexplained failure is answered by looking the ref up. A second write is never the right recovery.→ Step 2: Discovering billsRead fee and total from the response
Read fee and total from the response
Fees are configured per partner and can change. Charge your customer the
total the API returned, never a figure you calculated.→ Step 3: Paying billsA foreign transaction is a 404
A foreign transaction is a 404
A transaction that is not yours — or that belongs to the other environment — returns
404, never 403. The API never confirms that someone else’s transaction exists.→ Get Transaction by IDAPI Reference
Validate API Key
GET /v3/validate
List Partners
GET /v3/partners
Discover Bills
POST /v3/bills/discover
Pay a Bill
POST /v3/bills/pay
Get Transaction by ID
GET /v3/bills/transactions/id
Get Transaction by Reference
GET /v3/bills/transactions/by-ref
List Transactions
GET /v3/bills/transactions
Download Receipt
GET /v3/bills/transactions/id/receipt
Start integrating
Begin with Step 1: Partners and accounts
Check availability and learn the identifier rules for each biller
Additional resources
Authentication
Keys, headers and environments
Response Format
The envelope every endpoint returns
Error Handling
Every error code and what to do about it
Polling Strategies
Intervals, backoff and ceilings
Security Best Practices
Protect your keys and your customers
Contact Support
Get help from our team

