Every failure returns the same body, whichever endpoint was called. It carries the same envelope
fields as a successful response, with message in place of data:
Branch on code, not on the message text. The wording may be reworded; the status will not.
transaction_id is present when the call reached the source, so a failed call gives you the same
reference to quote as a successful one. It is null when the request never got that far, such as a
rejected key or a request that failed validation.
Retrying safely
429, 503 and 504 are transient. Retry with exponential backoff.
502 indicates a source-side failure rather than a problem with your request. A retry may work; do
not retry in a tight loop.
- Any other
4xx will not change on retry. Fix the request, or wait for the state to change in the
case of 409.
A penny drop moves one rupee into the account being verified. Retrying it repeats that transfer and
is charged again. Retry it only when you have received no response at all, and never automatically
on a 4xx.
A 200 is not always a yes
Bank verification returns 200 even when the account could not be checked: the transport worked, the
verification did not. In those responses message carries the reason and the fields below it are
absent:
Read message before anything else, and treat a missing account_exists as “not answered” rather
than as “no”. Reasons include an offline beneficiary bank, an unavailable NPCI, a declining source
bank, and an account the method cannot reach, such as an NRE account.
PAN behaves the same way: a status other than valid with a populated remarks, such as Holder is Deceased, arrives on a successful call.