POSTUPI Cash Withdrawal Status
Poll the final outcome of a UPI cash withdrawal by `tid` — hand over cash only when `tx_status` is "0".
- Read-only: Changes nothing; only returns data.
https://staging.eko.in/ekoapi/v3 return an error response. Test it in Production.Returns the final outcome of a UPI cash withdrawal started with
Generate UPI QR for Cash Withdrawal. The customer's
payment settles asynchronously, so poll this with the tid on the schedule the
initiate response returned:
- First call after
status_check_start_inseconds. - Then every
status_check_gapseconds. - Up to
status_check_attemptstimes.
Reading the outcome
data.tx_status is a numeric code returned as a string, not a word.
data.txstatus_desc carries the matching human-readable word. The envelope and
data.tx_status always agree, so you may branch on either:
| Outcome | tx_status | response_status_id | response_type_id | status | Terminal? | What the retailer must do |
|---|---|---|---|---|---|---|
| Paid | "0" | 0 | 99013 | 0 | Yes | Money has moved and the wallet is credited. Dispense the cash. bank_ref_num holds the UPI RRN — store it. |
| Failed | "1" | 1 | 99018 | 1 | Yes | Nothing was debited or credited. Do not dispense. Start a fresh transaction if the customer still wants the cash. |
| Pending | "2" | 2 | 99019 | 0 | No | Do not dispense. Keep polling on the schedule — see below. |
Only tx_status == "0" authorises handing over cash. Anything else —
"1", "2", an unrecognised value, a timeout, or a connection error — means
you must assume no money moved. Build this as a hard rule in your retailer app,
not a message the operator can dismiss.
Compare on the string "0", and treat any value you do not recognise as not
paid. Do not compare against the words SUCCESS, FAILED or PENDING — this
API does not return them.
All three responses carry the same fields. bank_ref_num is populated only once
the payment has succeeded.
Still pending after the last scheduled poll
- Stop polling on the published schedule and treat the transaction as not paid.
- Re-query once after a few minutes. Almost all pending transactions resolve by then, either from the acquirer's confirmation or from Eko's reconciliation sweep.
- If it is still pending after roughly 30 minutes, raise it with Eko support
quoting the
tid. A small number of cases — for example a payment received for an amount different from the one requested — are held deliberately for manual review and will not auto-resolve. Nothing is credited while a transaction is held. - Never re-initiate against the same
tid, and never show the same QR twice. Each QR is single-use and amount-specific.
A failed payment's reason arrives in txstatus_desc. See
why an initiation fails for
the common reasons.
- UPI Cash Withdrawal — Generate a single-use UPI QR for the withdrawal amount, show it to the customer, then poll the status API on the returned schedule — hand over cash only when `tx_status` is "0".
Request
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
initiator_id | string | required | Registered mobile number of the API user (see Platform Credentials).e.g. 9962981729 |
user_code | string | required | Code of the retailer the withdrawal was run for.e.g. 34127001 |
tid | string | required | The `tid` returned by Generate UPI QR for Cash Withdrawal.e.g. 123456789 |
initiator_idstringRequiredRegistered mobile number of the API user (see Platform Credentials).
example: 9962981729
user_codestringRequiredCode of the retailer the withdrawal was run for.
example: 34127001
tidstringRequiredThe `tid` returned by Generate UPI QR for Cash Withdrawal.
example: 123456789
These headers authenticate and sign every request. See How Auth Works for details.
| Field | Type | Required | Description |
|---|---|---|---|
developer_key | string | required | Static API key issued to your account after KYC. |
secret-key | string | required | Dynamic per-request signature: base64(HMAC-SHA256(timestamp, base64(access_key))). |
secret-key-timestamp | string | required | Current time in milliseconds since UNIX epoch, used to compute secret-key. Must match server time. |
content-type | string | required | application/jsone.g. application/json |
developer_keystringRequiredStatic API key issued to your account after KYC.
secret-keystringRequiredDynamic per-request signature: base64(HMAC-SHA256(timestamp, base64(access_key))).
secret-key-timestampstringRequiredCurrent time in milliseconds since UNIX epoch, used to compute secret-key. Must match server time.
content-typestringRequiredapplication/json
example: application/json
Response types
| response_type_id | Meaning | Next step |
|---|---|---|
99013 | Paid (`tx_status` "0") — wallet credited; dispense the cash and store `bank_ref_num` | — |
99018 | Failed (`tx_status` "1") — nothing debited or credited; do not dispense | — |
99019 | Pending (`tx_status` "2") — do not dispense; poll again on the schedule, then re-query once after a few minutes; escalate to Eko support with `tid` after ~30 minutes | — |
Responses
99013Paid (`tx_status` "0") — wallet credited; dispense the cash and store `bank_ref_num`
statusnumberPrimary success indicator (0 = success).
messagestringHuman-readable response / error message.
response_status_idnumberUI display hint only (-1/0 success, 1 failure, 2 initiated, 3 refund initiated, 4 refunded). Never branch on it — use `status` (and `tx_status` for financial APIs), or `response_type_id` where documented.
response_type_idnumberA unique id for every possible response shape (success or error) — useful for client logic branching and analytics.
dataobjectAPI-specific response payload.
tx_statusstringPayment outcome as a numeric string: `"0"` paid — dispense cash; `"1"` failed — do not dispense; `"2"` pending — do not dispense. Treat any other value as not paid.
txstatus_descstringThe same outcome in words: `Success` / `Failed` / `Pending`. Safe to display; branch on `tx_status`.
tidstringEko transaction id.
amountstringWithdrawal amount (₹).
bank_ref_numstringUPI RRN. Populated only once `tx_status` is `"0"` — store it.
commissionstringRetailer commission (₹).
tdsstringTDS (₹) deducted from the commission.