Provider errors are distinct from Yuno API errors. A Yuno API error (e.g., 400 INVALID_PARAMETERS) means your request did not reach a payment provider. A provider error means Yuno successfully routed the transaction, but the issuing bank, card network, or payment processor rejected it.
Where provider errors appear
Provider response data is nested inside the payment object under transaction:
{
"id": "pay_01J...",
"status": "DECLINED",
"transaction": {
"id": "txn_01J...",
"status": "DECLINED",
"provider_code": "51",
"provider_message": "Insufficient funds",
"provider_name": "STRIPE"
}
}
The fields to inspect:
| Field | Description |
|---|
transaction.provider_code | The raw decline code returned by the provider or issuing bank |
transaction.provider_message | Human-readable message from the provider (not always present) |
transaction.provider_name | Which downstream provider processed the transaction |
payment.status | Top-level status: DECLINED, ERROR, CANCELLED |
provider_code values are not standardized across providers. A code of 51 from Stripe means something different than 51 from a local acquirer. Always combine provider_code with provider_name when mapping to user-facing messages.
Decline categories and recommended actions
Declines fall into three categories. The appropriate merchant action differs significantly between them.
Do not retry — permanent declines
These declines indicate a definitive rejection from the issuer. Retrying the same transaction will produce the same result and may trigger fraud flags or velocity limits on the issuer’s side.
| Scenario | Typical provider_code | User-facing message | Action |
|---|
| Card reported lost or stolen | 41, 43 | ”Your card cannot be used for this transaction. Please contact your bank.” | Do not retry. Do not prompt for the same card. |
| Card permanently blocked | 36, 38 | ”Your card has been blocked. Please contact your bank or use a different card.” | Do not retry. Offer alternative payment method. |
| Invalid card number | 14 | ”The card number entered is invalid. Please check and try again.” | Do not retry. Prompt user to re-enter card details. |
| Do not honor (generic hard decline) | 05 | ”Your bank declined this payment. Please contact your bank or use a different card.” | Do not retry with same card. |
| Restricted card | 62 | ”This card is not authorized for this type of transaction.” | Offer alternative payment method. |
Retry eligible — temporary declines
These declines are transient and often resolve on a subsequent attempt. Apply exponential backoff and limit retries to avoid triggering velocity controls.
| Scenario | Typical provider_code | User-facing message | Retry strategy |
|---|
| Insufficient funds | 51 | ”Your card was declined due to insufficient funds. Please try a different card.” | Retry once after user confirmation. Do not auto-retry without user action. |
| Temporary bank hold | 57, 58 | ”Your bank temporarily declined this payment. Please try again in a moment.” | Retry after 30–60 seconds, max 2 attempts. |
| Issuer system unavailable | 91, 96 | ”Your bank is temporarily unavailable. Please try again shortly.” | Retry with exponential backoff: 30s, 60s, 120s. |
| Timeout or no response | 68 | ”The payment could not be completed. Please try again.” | Retry once. If using subscriptions, Yuno handles retry logic automatically. |
These declines indicate suspected fraud or excessive retry attempts. Do not retry and consider reviewing the transaction for fraud signals.
| Scenario | Typical provider_code | Action |
|---|
| Transaction flagged as fraud | 59, 63 | Block the session. Do not retry. Flag for review. |
| Velocity limit exceeded | 65 | Pause all retry attempts for this card. Alert your fraud team. |
| Security violation (CVV/3DS failure) | 82, N7 | Do not retry. If 3DS failed due to user error, allow one re-attempt through the full 3DS flow. |
3DS failures
3DS authentication failures appear as payment declines, but the source is the authentication step rather than the issuer’s authorization decision. Common patterns:
Identify the failure point
Check transaction.provider_message for phrases like “Authentication failed”, “Authentication not completed”, or “Cardholder not enrolled”. These indicate the 3DS challenge was not completed successfully.
Determine if the failure is user-driven or system-driven
User-driven: the cardholder cancelled, timed out, or entered the wrong OTP. Allow one retry through the full 3DS flow.System-driven: the ACS (issuer’s authentication server) was unavailable. Retry after 60 seconds. If your integration supports frictionless 3DS, the provider may bypass the challenge on retry.
Do not retry authentication failures as authorization-only
Do not strip 3DS data and attempt an authorization-only flow. This bypasses required regulatory controls and will be declined by the issuer or blocked by the network.
Mapping provider codes to user-facing messages
Do not expose raw provider_code values to end users. Map them to clear, actionable messages that tell the user what to do next.
function getDeclineMessage(providerCode) {
const hardDeclines = {
'05': 'Your bank declined this payment. Please contact your bank or use a different card.',
'14': 'The card number entered is invalid. Please check and try again.',
'36': 'Your card has been blocked. Please contact your bank.',
'38': 'Your card has been blocked. Please contact your bank.',
'41': 'Your card cannot be used for this transaction. Please contact your bank.',
'43': 'Your card cannot be used for this transaction. Please contact your bank.',
'62': 'This card is not authorized for this type of transaction.',
};
const softDeclines = {
'51': 'Your card was declined due to insufficient funds. Please try a different card.',
'57': 'Your bank temporarily declined this payment. Please try again.',
'91': 'Your bank is temporarily unavailable. Please try again shortly.',
'96': 'The payment could not be completed. Please try again.',
};
const fraudDeclines = {
'59': null, // Do not inform user — flag for internal review
'63': null, // Do not inform user — flag for internal review
'65': 'Too many payment attempts. Please try again later.',
};
if (providerCode in hardDeclines) {
return { message: hardDeclines[providerCode], retry: false };
}
if (providerCode in softDeclines) {
return { message: softDeclines[providerCode], retry: true };
}
if (providerCode in fraudDeclines) {
return { message: fraudDeclines[providerCode], retry: false, flag: true };
}
// Default for unmapped codes
return {
message: 'Your payment was declined. Please try a different payment method.',
retry: false,
};
}
Provider error response categories
Use this table as a starting point when building your decline-handling logic. Specific codes vary by provider — validate against your active provider’s documentation.
| Category | Retry? | User prompt | Internal action |
|---|
| Hard decline (card blocked, invalid) | No | Suggest different card or method | Log for analysis |
| Soft decline (funds, temp hold) | Yes (1–2x with backoff) | Explain issue, offer retry | Log retry attempt |
| Fraud / velocity | No | Generic message only | Alert fraud team |
| 3DS failure — user action | Yes (once, full 3DS flow) | Ask user to complete authentication | Log authentication event |
| 3DS failure — system | Yes (after 60s) | Suggest retry | Log as provider issue |
| Issuer unavailable | Yes (exponential backoff) | Suggest retry | Monitor for pattern |
| Provider timeout / error | Yes (with idempotency key) | Suggest retry | Check provider status |
For fraud-flagged declines (provider_code 59, 63), do not surface the specific reason to the user. Use a generic “payment could not be completed” message and route the event to your fraud review queue.