Overview
Discovery is the read half of Bill Payment: you ask a biller what an account currently owes, and you get back a list of payable bills. Nothing is charged, and nothing is committed. It happens in two parts.POST /v3/bills/discover accepts the request and gives you a transactionId. The bills themselves arrive on that transaction a moment later, when its status becomes READY.
Building the request
Three fields, all required.Choosing a ref
ref is what makes a discovery safe to retry. If the response is lost, you look the ref up instead of sending a second discovery — so a ref you cannot reconstruct from your own data is a transaction you cannot recover.
A workable recipe: a fixed prefix, your own order or invoice identifier, and nothing else.
A
ref is unique per biller, not globally. disc-inv-2026-0042 for ADE and the same string for SONELGAZ are two different references. Passing partner when you look one up removes any ambiguity.Sending the discovery
Polling to READY
Read the transaction until its status leaves PENDING. A discovery normally settles in a few seconds.
Reading bills[]
A READY transaction carries the bills that are payable right now.
Show the customer
amount + fee. That sum is what will be debited, and it is returned as total on the transaction once a bill is selected.
bills[] is present only while status is READY. Once a payment starts, the transaction carries selectedBill instead. Read the bills while you have them.When bills[] is empty
An empty array is a normal, successful outcome — not an error.
- the account owes nothing, or
- everything the account owes is below the 200 DZD discovery floor.
Recovering a lost response
If the discovery request fails in a way you cannot explain — a timeout, a crash, a redeploy — ask what theref became. Never send a second discovery.
403 DUPLICATED_REF. That error means the discovery already exists; it is never a reason to retry with a different ref, which would start a second discovery for the same account.
Errors you will meet
A
FAILED discovery carries its reason in error.code: INVALID_ACCOUNT, PARTNER_UNAVAILABLE, BILL_ALREADY_PAID or PAYMENT_DECLINED.
Every code, with example bodies →
Best practices
Derive the ref
Build it from your own order identifier so you can always reconstruct it after a failure.
Poll, never resend
A slow discovery is not a lost one. Read the transaction instead of sending another request.
Cache nothing about bills
A discovery is a snapshot. If the customer waits, discover again rather than paying against stale figures.
Say payable, not owed
An empty
bills[] means nothing is payable. It does not mean the account owes nothing.Next step
Step 3: Paying bills
Choose a bill, confirm the total, and submit the payment safely
Related pages
Discover Bills
The endpoint reference
Get Transaction by ID
The transaction object in full
Get Transaction by Reference
The recovery path
Partners and Accounts
Identifier rules per biller

