data.error, with a stable code and a fixed public message. Use the code for branching. Don’t match or parse the message. Look up any code in the error code tables.
The error object
failure_categoryidentifies the broad event family.error.codegives the known cause.- Unknown causes stay generic. A generic decline never implies insufficient funds.
- Successful and readiness events have
error: null. - Mandate lifecycle notifications (
mandate.paused,mandate.resumed,mandate.cancelled,mandate.expired) also haveerror: null. They describe local state, not a payment failure. See the event catalog.
Which error each event carries
Handle errors safely
- Older retained events can omit
errorandfailure_stage. Handle absent fields and unknown future codes safely. - Retries and replays keep the original event ID and bytes. They don’t add a reason discovered later.
- A later operation outcome produces a new event, with a new resource version where applicable. It doesn’t edit an old event.
- A new payment attempt can have a different resource ID.
- A webhook replay retries delivery, not the underlying operation.
- Always use
statusto determine the lifecycle.
Coverage boundaries
Some outcomes have limited or no webhook coverage.Before credentials are issued
A definite failure recorded by Prava can emitpayment.failed with failure_stage: credential_issuance and outcome_source: prava_observed. Supported cases include those marked Yes:
For credential-fetch rejections, see Confirmed credential-fetch rejections.
Result API compatibility
The same recorded failure uses the same publicerror.code in the detailed payment-result or enrollment status API and in its webhook. You can reuse one error handler.
- For payment attempts and full-enrollment results, the safe mapping is shared with the corresponding result projections.
failure_stage,outcome_sourceandfailure_categoryadd context independently of the code.
Code names and messages
- Existing codes are preserved, including previously exposed names that mention a card network. This release doesn’t rename, remove or collapse them.
- Historical codes that include a card-network name remain documented for compatibility, because existing integrations already receive them.
- Any future public-code rename, including for those historical codes, needs an explicitly versioned API release. There’s no calendar cutover or automatic switch.
- Messages come from fixed safe copy. Raw provider text is excluded.
- Unknown codes use the family’s generic fallback.
- Branch on codes, tolerate future codes and absent additive fields, and don’t parse messages.
Shopper reports and legacy claims
PAYMENT_DECLINED,USER_CANCELLED,AUTH_CANCELLEDandAUTH_INCOMPLETEremain distinct.- Session-user reports can describe authentication or cancellation, or a generic
PAYMENT_FAILED. - A browser-supplied issuer reason is never returned as an attested financial result. It never creates
payment.failedand never supplies an issuer reason in any event. - Legacy financial claims with caller-controlled diagnostic metadata are also generic.
- Known non-issuer legacy setup/provisioning aliases stay compatible. Stored diagnostics are unchanged.
Enrollment status
- Cancelled enrollment status responses keep
error: nullfor compatibility. Usestatus: cancelled. - The corresponding cancellation webhook provides
SESSION_CANCELLED, with its unchanged nullfailure_category. - Enrollment expiry has the safe
SESSION_EXPIREDreason. - Successful enrollment clears the error.
- Intermediate enrollment errors retain
retryable. Terminal errors useretryable: false. - No previous retryable error is reused as a terminal reason.
Where the shared contract applies
This shared contract applies to detailed outcome responses and newly created events. The hosted checkout request and the merchant payment-result API both keep their existing contracts:- Other operation wrappers/admission errors without a recorded outcome remain synchronous API errors.
- Retained events and replay bytes are never rewritten.
- Definite credential-issuance events describe failure to obtain credentials, not a merchant charge or final settlement result.
Confirmed credential-fetch rejections
FETCH_AGENTIC_CREDS_ERROR remains the same public code in the detailed API outcome and the webhook.
- The event reports failure to obtain credentials. It doesn’t claim an issuer decline or a completed merchant charge.
- Older failures aren’t backfilled.
- The evidence Prava uses to tell these cases apart isn’t included in the payload.
Charge response messages
In Charge a Mandate responses:
Unknown codes use the safe family fallback.
Error codes
Each table lists codes with their fixed messages. Keep these limits in mind:- A code is emitted only when its reason was actually persisted or returned at the supported request boundary.
- These tables also cover detailed API errors. A code being listed doesn’t by itself make an outcome eligible for a webhook.
- A listed code doesn’t mean every upstream processor can supply it.
- Raw processor diagnostics and customer data are excluded.