Decline codes
When a payment, refund or payout fails, the object in the webhook event carries a failure field with a stable dpay code. The code is shared by all payment methods, so one piece of logic handles a BLIK, card or bank transfer decline. The original provider code comes alongside, for diagnostics.
Error codes are API responses to an invalid request, returned immediately. Decline codes describe why a payment, refund or payout did not go through - they arrive in the payment.failed, refund.failed and payout.failed events.
The failure object
"failure": {
"code": "insufficient_funds",
"message": "Insufficient funds",
"category": "customer",
"retryable": true,
"provider_code": "INSUFFICIENT_FUNDS"
}
| Field | Description |
|---|---|
code | dpay decline code from the table below. Base your logic on it. |
message | A short description in English - for logs and your team. Show the customer your own message. |
category | Who can remove the cause: customer, merchant, risk or system. |
retryable | true when retrying the same payment may succeed. |
provider_code | The provider code (BLIK, card processor, bank) or null. For diagnostics only - the list of provider codes changes. |
In events that are not declines, failure is null.
Categories
| Category | Meaning | What to do |
|---|---|---|
customer | The cause is on the customer's side: funds, limit, code, bank, card. | Tell the customer and offer a retry or another payment method. |
merchant | The cause is on your side: the request, recurring payment terms, the refund deadline or amount. | Fix the request or the data - a retry alone will not help. |
risk | Declined for security reasons. | Do not retry automatically and do not give the customer details. |
system | A temporary error at the bank, the provider or dpay. | Retry later. |
Retry (retryable)
retryable: true means that the same payment may succeed on another attempt - e.g. when the customer tops up the account, enters a new BLIK code or confirms the payment in time. With false, a retry without a change (another card, another method, a corrected request) will not succeed.
For recurring payment charges, retry automatically only declines with retryable: true and with a reasonable interval. Declines with retryable: false require contacting the customer.
Code table
| Code | Category | Retry | Meaning |
|---|---|---|---|
insufficient_funds | customer | yes | Insufficient funds on the account or card. |
limit_exceeded | customer | yes | The customer's limit was exceeded - amount or number of transactions. |
customer_declined | customer | yes | The customer declined the payment, e.g. in the banking app. |
customer_timeout | customer | yes | The customer did not confirm the payment in time. |
invalid_code | customer | yes | Invalid, expired or already used code (e.g. BLIK). |
expired | customer | yes | The payment was not paid within 7 days. |
app_update_required | customer | yes | The customer needs to update the banking app. |
issuer_declined | customer | no | Declined by the bank or card issuer, also for a closed or blocked account. |
card_invalid | customer | no | Invalid or expired card. |
authentication_required | customer | no | Strong customer authentication (3-D Secure) failed. |
alias_invalid | customer | no | The saved payment alias (BLIK OneClick, recurring payment) is no longer valid. |
unsupported_by_bank | customer | no | The customer's bank does not support this type of payment. |
generic_decline | customer | no | Declined without a more specific reason. Every new or unknown provider code also gets it - you will see that code in provider_code. |
security_declined | risk | no | Declined for security reasons, e.g. by an anti-fraud system or because the card was reported lost. |
blocked | risk | no | Code payments temporarily blocked after a series of invalid codes. |
recurring_conditions_not_met | merchant | no | The charge does not meet the recurring payment terms, e.g. the amount exceeds the limit. |
invalid_request | merchant | no | Invalid request, e.g. the alias already exists, a wrong account number or recurring payments not enabled for the service. |
refund_window_expired | merchant | no | The refund period has expired. |
refund_amount_exceeded | merchant | no | The refund exceeds the refundable amount. |
payout_failed | merchant | no | The payout could not be completed (see Payouts). |
refund_failed | system | no | The refund could not be completed. |
processing_error | system | yes | A temporary processing error at the bank, the provider or dpay. |
The list of codes may grow. Handle an unknown code based on category and retryable, the same way as generic_decline.
Provider code mapping
provider_code carries the original provider code. Below are the codes we translate into dpay codes. A code outside these tables (also from other providers, e.g. for online bank transfers) results in generic_decline with that code in provider_code.
BLIK
| dpay code | BLIK codes |
|---|---|
insufficient_funds | INSUFFICIENT_FUNDS |
limit_exceeded | LIMIT_EXCEEDED, LOW_LIMIT, LIMIT_LOCKED |
customer_declined | USER_DECLINED |
customer_timeout | TIMEOUT, USER_TIMEOUT, AM_TIMEOUT, LONG_TIMEOUT |
invalid_code | BAD_PIN, ER_WRONG_TICKET, ER_TIC_EXPIRED, ER_TIC_USED |
app_update_required | OLD_APK_VERSION |
issuer_declined | ISSUER_DECLINED, ACCOUNT_CLOSED, ACCOUNT_DISABLED, BLIKL_DECLINED, LIMIT_NOT_APPROVED, LIMIT_IN_OTHER_BANK, LIMIT_ALREADY_ACTIVE, TFR_REJECTED |
alias_invalid | ALIAS_DECLINED, ALIAS_NOT_FOUND, ALIAS_APP_NOT_FOUND, ALIAS_EXPIRED, ALIAS_NOT_AVAILABLE |
unsupported_by_bank | OFFUS_NOT_ALLOWED, TXTYPE_USR_UNHANDLED, BLIK-L_NOTSUPPORTED, SPLITPAYMENT_UNHANDL |
security_declined | SEC_DECLINED, TAS_DECLINED, SENDER_BLOCKED, SENDER_UNKNOWN, WRONG_DEVLOC_DATA, PEP_VERIFICATION, PESEL_RESTRICTED |
blocked | TOO_MANY_TRIES |
recurring_conditions_not_met | AUTOCONF_REQ_NOT_MET, AMOUNT_LIMIT_EXCEEDED |
invalid_request | ALIAS_ALR_EXISTS, BAD_IBAN, RECURRING_NOT_ENABLED, ALIAS_APP_AMBIGUOUS |
refund_window_expired | RET_LATE, TFR_LATE |
refund_amount_exceeded | RET_AMT_EXCEEDED |
processing_error | SYSTEM_ERROR, GENERAL_ERROR, ISS_OUTOFSERVICE, PESEL_SERVICE_FAILED, TX_NOTFOUND, TFR_NOT_POSSIBLE, INTERNAL_ERROR |
Cards (ISO 8583)
| Card code | Meaning | dpay code |
|---|---|---|
51 | Insufficient funds | insufficient_funds |
61 | Amount limit exceeded | limit_exceeded |
65 | Transaction count limit exceeded | limit_exceeded |
05 | Do not honor | issuer_declined |
46 | Closed account | issuer_declined |
57 | Transaction not permitted to cardholder | issuer_declined |
62 | Restricted card | issuer_declined |
14 | Invalid card number | card_invalid |
54 | Expired card | card_invalid |
04 | Pick up card | security_declined |
41 | Lost card | security_declined |
43 | Stolen card | security_declined |
59 | Suspected fraud | security_declined |
03 | Invalid merchant | invalid_request |
12 | Invalid transaction | invalid_request |
13 | Invalid amount | invalid_request |
30 | Format error | invalid_request |
58 | Transaction not permitted to terminal | invalid_request |
91 | Issuer unavailable | processing_error |
96 | System malfunction | processing_error |
dpay codes
| Code | Meaning | dpay code |
|---|---|---|
SCA_REJECTED | Strong customer authentication (3-D Secure) rejected | authentication_required |
WRONG_TICKET_BLOCKED | BLIK code payments temporarily blocked after a series of invalid codes | blocked |
Payouts
A rejected payout (payout.failed) always has the payout_failed code, and provider_code tells what happened to the funds:
provider_code | Meaning |
|---|---|
refunded_to_dpay | The funds went back to the account balance at dpay. |
refunded_to_nrb | The funds were returned to the bank account. |
frozen | The funds are frozen. |
blocked | The funds are blocked. |
null | No additional information. |
Contact dpay support for the details of a rejected payout.