Handling Payment Declines
Learn how to handle payment declines and provide clear feedback to customers
Payment declines occur when a transaction is declined by Payload, an issuing bank, or a card network. Payload may decline transactions for fraud suspicion, duplicate protection, or account limits before reaching the card network. Other declines come from issuing banks or card networks for reasons like insufficient funds, expired cards, or incorrect card details.
Declines are synchronous responses returned immediately when creating a transaction. Payload returns all decline responses with detailed information to help you provide clear feedback. Properly handling declines ensures a smooth customer experience and helps you recover failed payments.
Most card declines can be resolved by the customer updating their payment information or contacting their bank. Providing clear, actionable error messages helps customers quickly resolve issues and complete their purchase.
Payment Method Differences: Not all payment method types support synchronous declines. Card payments return declines immediately during transaction creation. Bank transfer transactions that pass initial validation may be blocked asynchronously days later, resulting in rejects rather than declines. For handling bank transfer rejects, see Bank Rejects.
Prerequisites
Before implementing decline handling, it's helpful to learn about the following topics.
Learn about the Payment API
Understand how to create transactions and process payments through the Payload API.
Learn about payment methods
Understand how payment methods are validated and processed for different card types and bank accounts.
Understanding Payment Declines
When a payment is declined, the transaction status is set to declined and includes a specific
decline code that indicates why the payment failed. The decline code helps you understand the
reason and guide customers toward resolution.
Common decline scenarios
- Card Issues: Expired card, incorrect CVV, invalid card number
- Insufficient Funds: Not enough balance to complete the transaction
- Bank Restrictions: Transaction exceeds spending limits or triggers fraud prevention
- Duplicate Detection: Transaction appears to be a duplicate attempt
- Invalid Information: Billing address or ZIP code doesn't match card on file (see Address Verification)
Decline Codes
When a transaction is declined, the status.code field contains a specific decline code that
indicates why the payment failed. Use these codes to provide appropriate messaging to customers.
Card Decline Codes
| Code | Description | Customer Action |
|---|---|---|
card_expired | The card has expired | Use a different card or contact bank for replacement |
invalid_card_code | The security code (CVV) is invalid | Check the 3 or 4-digit code on the back of the card |
invalid_card_number | The card number is invalid | Verify the card number is entered correctly |
insufficient_bal | Insufficient funds to complete the payment | Use a different payment method or add funds |
exceeded_limit | Transaction exceeds the card's spending limit | Contact bank to increase limit or use different card |
invalid_zip | ZIP code doesn't match the card | Enter the billing ZIP code associated with the card |
invalid_address | Billing address doesn't match the card | Enter the correct billing address |
general_decline | Card declined without specific reason | Contact bank for more information |
suspicious_activity | Flagged as potentially fraudulent | Contact bank to verify legitimate transaction |
too_many_attempts | Too many payment attempts detected | Wait before trying again |
duplicate_attempt | Transaction appears to be duplicate | Verify transaction wasn't already processed |
Bank Account Decline Codes
| Code | Description | Customer Action |
|---|---|---|
insufficient_bal | Insufficient funds for bank debit | Ensure sufficient funds in account |
exceeded_limit | Transaction exceeds account spending limit | Contact bank to increase limit or use different account |
duplicate_attempts | Multiple identical transactions detected | Verify transaction wasn't already processed |
suspicious_activity | Flagged as potentially fraudulent | Contact bank to verify legitimate transaction |
Balance Check Availability: The insufficient_bal decline code for bank transfers only
returns synchronously when balance check is enabled and available for that payment method. If
balance check is not enabled or unavailable, insufficient fund issues will be detected
asynchronously and returned as rejects rather than declines. See Bank
Rejects for handling asynchronous rejections.
Processing Decline Codes
| Code | Description | Resolution |
|---|---|---|
processing_issue | Temporary processing problem | Retry the transaction |
issue_reading_card | Card could not be read (physical terminal) | Try swiping or inserting card again |
not_supported | Payment method or transaction type not supported | Use a different payment method |
Sensitive Information: Never log or store full card numbers or CVV codes when handling declines. Only reference the last 4 digits of the card for customer service purposes.
Handling Declines
Implement proper decline handling based on how you're processing payments.
Handle declines via Payment API
When processing payments through the Transaction API, declines are returned synchronously with an HTTP 400 status code (by default) and include the transaction object with detailed decline information.
This example demonstrates proper decline handling:
- Catch the API error response (HTTP 400 for declines)
- Access the transaction object from the error response
- Check
transaction.status.valueto confirm it's'declined' - Use
transaction.status.codeto determine the specific decline reason - Display
transaction.status.messageto the user or create a custom message based on the code
The error response includes the full transaction object, allowing you to log details for analytics and customer support.
HTTP Status Configuration: By default, declined transactions return HTTP 400. You can configure this to return HTTP 200 in your account settings if you prefer to handle declines without exceptions.
Handle declines in payment forms
When using Payment Forms, decline events are delivered through JavaScript event listeners or React component callbacks.
This example shows decline handling for payment forms:
- Listen for the
declinedevent on the form element (or useonDeclinedcallback in React) - Access the
transactionobject from the event detail - Check
transaction.status.codeto determine the decline reason - Display user-friendly error messages based on the decline code
- Allow the customer to retry with corrected information
The declined event fires immediately when Payload returns a decline, allowing you to provide real-time feedback without page reloads.
User Experience: For payment forms, consider keeping the form data filled in when a decline occurs so customers can easily correct specific fields (like CVV or ZIP code) without re-entering all information.
Handle declines in Checkout Plugin
When using the Checkout Plugin, declined payments are delivered through the onError event
callback with transaction details.
This example shows decline handling for the Checkout Plugin:
- Use the
onErrorcallback when initializing the Checkout Plugin - Check if the error contains a
transactionobject (indicates a payment decline) - Access
transaction.status.codeto determine the specific decline reason - Display user-friendly error messages based on the decline code
- The plugin automatically allows customers to retry with corrected information
When a payment is declined, the Checkout Plugin remains open and displays an error message, allowing customers to update their payment information and retry immediately.
Automatic Retry: The Checkout Plugin handles the retry flow automatically. When a decline occurs, the form remains open with an error message, and customers can update their information and resubmit without needing to reopen the plugin.
Testing Declines
Use test card numbers to trigger specific decline codes in the test environment. These cards allow you to verify your decline handling logic works correctly.
Test Card Numbers
Use these card numbers in test mode to simulate specific declines:
| Decline Code | Test Card Number | Expiry | CVV |
|---|---|---|---|
card_expired | 4111111111119900 | Any | Any |
duplicate_attempt | 4111111111119901 | Any | Any |
exceeded_limit | 4111111111119902 | Any | Any |
general_decline | 4111111111119903 | Any | Any |
insufficient_bal | 4111111111119904 | Any | Any |
invalid_card_code | 4111111111119905 | Any | Any |
invalid_card_number | 4111111111119906 | Any | Any |
invalid_zip | 4111111111119907 | Any | Any |
suspicious_activity | 4111111111119908 | Any | Any |
too_many_attempts | 4111111111119909 | Any | Any |
invalid_address | 4111111111119910 | Any | Any |
Testing Workflow
- Test Each Decline Code: Verify your application handles each decline code appropriately
- Check Error Messages: Ensure user-facing messages are clear and helpful
- Verify Retry Flow: Test that customers can retry after correcting information
- Test Event Handling: Confirm decline events fire correctly in payment forms
- Validate Logging: Ensure decline data is properly logged for analytics
Production Testing: Test card numbers only work in test mode. In production, you can use real cards with small amounts to test your decline handling, but be prepared to issue refunds.
Schema Reference
The following fields are available in the transaction status object when a payment is declined:
Transaction Status
statuscodeapproved, card_expired, duplicate_attempt, exceeded_limit, general_decline, insufficient_bal, invalid_card_code, invalid_card_number, invalid_zip, invalid_address, invalid_account_number, suspicious_activity, too_many_attempts, processing_issue, issue_reading_card, not_supported, general_reject, general_adjustment, payment_stopped"Undocumented"messagevalueprocessing, authorized, processed, declined, rejected, voided, adjustedNext Steps
Enhance your decline handling implementation with additional payment features
Reduce Payment Declines
Implement Payment Method Verification to verify cards before charging, use Address Verification to check billing address details against the card on file, and add Fraud Prevention to detect and prevent fraudulent transactions.
Handle Payment Lifecycle
Monitor transaction status with Payment Processing and Transaction Status, receive real-time updates via Webhook Events, and manage payment reversals with Refunds and Voids.
Improve Recurring Billing Success
Set up Autopay for automatic recurring payments, create payment cycles with Billing Schedules, and implement Dunning Management to recover failed recurring payments.
Related articles
- Address Verification - AVS responses for
invalid_addressandinvalid_zipdeclines - Payment API - Process payments through the API
- Payment Form - Build custom payment forms
- Checkout Plugin - Embedded checkout forms
- Transactions API Reference