Transaction Retry enables merchants to automatically retry declined transactions on a backup gateway. This improves the chance that a transaction is ultimately successful, increases merchant revenue, and builds system resilience.
Transaction Retry will only retry transactions classified as soft declines and may be accepted at another gateway.
Note: Transaction Retry is in beta today. If you have interest in Transaction Retry please contact your account manager or reach out to success@spreedly.com. We are gathering more data about the authorization lift and adding more supported gateways before going with a broader market launch.
Error Code Classification
When a transaction is declined, a gateway returns an error code that maps to a decline reason.
Error codes are specific to each payment service provider and are available in the gateway documentation.
Spreedly defines error codes in the following two ways:
- Hard error codes: Unlikely to be successful if retried on another gateway. This includes error codes tied to fraud suspicion, an incorrect card number, or a lost/stolen card.
- Soft error code: This may be successful if retried on another gateway. This includes general error codes like do not honor, card or currency not supported, and when a gateway is down.
How Transaction Retry Works
Spreedly customers can pass up to two retry gateways in the initial purchase or authorize requests to transact with the primary gateway. If the primary gateway responds with a success message or hard decline, transaction retry will not send a request to the retry gateway(s).
If the primary gateway responds with a soft decline or gateway outage error code, transaction retry will subsequently trigger a second attempt using the same transaction details on the first retry gateway. If the retry attempt fails on the first retry gateway for any reason, the transaction will try the transaction again on the second retry gateway.
How to Use Transaction Retry
Before using Transaction Retry, you must have a minimum of two active gateways in your environment. To add a gateway to your environment, refer to the Add a Gateway guide. There are two options to use retry: add the retry object in the API request or use Routing Rules.
Option 1: Add Retry Object in the API Request
When sending a purchase or an authorize request to your primary gateway, add the backup retry gateway token(s) in the transaction body in the new “gateway_tokens” element nested within the “retry” element. The array can store up to two retry gateway tokens. Example:
POST /v1/gateways/<primary_gateway_token>/purchase.<format>HTTPS/1.1
1 {
2 "transaction": {
3 "payment_method_token": "<payment_method_token>",
4 "amount": 100,
5 "currency_code": "USD",
6 “order_id”: 123,
7 “retry” {
8 "gateway_tokens": ["first_retry_gateway_token, second_retry_gateway_token"]
9. “mode”: “standard | outage_only”
10 }
11 }
12 }
Both the primary gateway and retry gateway(s) must be production gateways in the same Spreedly environment. To see all active gateways in your Spreedly environment, go to your Spreedly Dashboard and filter on the environment or use a List to see all created gateways in your environment.
Including a valid retry gateway token in the transaction body of the POST request will notify Spreedly that you would like to use Transaction Retry for a Payment. If the retry gateway token is invalid, the response will return an error and the request will not execute.
The optional "mode" field under the "retry" element defaults to "standard" if excluded. If the mode is set to "outage-only", the service will ignore soft declines and only retry in the case of outages. If the mode is set to "standard" or excluded, the service will retry both soft declines and outages.
Note: We recommend that you send us “order_id” in the request, as shown in the example above, for easier reporting in custom analytics. Order ID is defined by the merchant and can be used to tie a customer order number to a series of transaction attempts.
Option 2: Use Routing Rules
Routing Rules allow merchants to set up business logic, including retry logic, through a user interface. Retry logic will be coupled with a business rule so that the merchant can control when to retry transactions based on transaction conditions like Card Brand and Amount.
During the beta, you will need to contact your account manager or reach out to success@spreedly.com to gain access to Routing Rules.
How to Send Gateway-Specific Fields
Gateway-specific fields are contained within a top-level gateway_specific_fields attribute, and can be sent for transactions against certain gateways.
When using Transactions Retry, you should send all gateway-specific fields for both the primary gateway and all retry gateways. Here is an example of how to send gateway-specific fields for transaction retry.
Supported Gateways
For Standard Retry mode, the primary gateway must be one of the following:
- Adyen
- Braintree
- Conekta
- CyberSource
- Orbital
- NMI
- Stripe
- Stripe Payment Intents
The retry gateway(s) can be any one of Spreedly’s 120+ supported gateways. This includes the first retry gateway and the secondary retry gateway.
Outage-only Retry does not have gateways restrictions; the primary gateway can be any one of Spreedly’s supported gateways.
Response Structure
Transaction Retry will include a transcript of the last token attempted in the response and a reference to prior tokens attempted. Transaction Retry can respond in one of four ways:
- Succeed at Primary Gateway
- Succeed at Retry Gateway - Primary gateway returned a soft error or gateway outage code, transaction succeeded on a Retry Gateway
- Stop at Primary Gateway - Primary gateway returned a hard error code that prevented a retry on Retry Gateway
- Fail at Retry Gateway - Primary gateway returned a soft error or gateway outage code, but the transaction failed on a Retry Gateway
Sample Response for Payments that did not proceed to a retry gateway (1 and 3). Note attempts = 1.
"transaction": {
"token": "transaction_token_1",
"gateway_token": "primary_gateway_token",
"state": "succeeded" | "gateway_processing_failed",
...
"payment_snapshot": {
"token": "payment_token"
"gateways": ["primary_gateway_token", "first_retry_gateway_token"],
"attempts": 1,
"previous_transactions": []
"mode": "standard"
}
}
}
Sample Response for Payments that proceed to the first (2 and 4). Note attempts = 2.
{
"transaction": {
"token": "first_retry_transaction_token",
"gateway_token": "first_retry_gateway_token",
"state": "succeeded" | "gateway_processing_failed",
...
"payment_snapshot": {
"token": "payment_token"
"gateways": ["primary_gateway_token", "first_retry_gateway_token"],
"attempts": 2,
"previous_transactions": ["transaction_token_1"]
"mode": "standard"
}
}
}
Sample Response for Payments that proceed to the second retry gateway (2 and 4). Note attempts = 3.
{
"transaction": {
"token": "second_retry_token",
"gateway_token": "second_retry_gateway_token",
"state": "succeeded" | "gateway_processing_failed",
...
"payment_snapshot": {
"token": "payment_token"
"gateways": ["primary_gateway_token", "first_retry_gateway_token", "second_retry_gateway_token"],
"attempts": 2,
"previous_transactions": ["transaction_token_1"]
"mode": "standard"
}
}
}
Transaction details for each gateway token will be returned under the ‘payment_snapshot’ element. The absence of a retry gateway token body means that the retry gateway was not attempted. Whether the payment ultimately succeeds or fails is included in the "state" of the response.
If the primary gateway token is not supported by Standard Retry, Transaction Retry will return an error. Only the last transaction token attempted includes the full transcript on the response, you may look up the "previous_transaction" transaction token in your Spreedly dashboard or by using a show call.
How to Test Transaction Retry using Test Gateways
Spreedly test gateways support the ability to trigger specific failure cases which can be used to simulate various transaction failures and the corresponding Transaction Retry behaviors.
Users can trigger a simulated hard decline, soft decline, or gateway outage on a Spreedly Test Gateway by including the `simulate_decline` gateway-specific field and one of the following values: `hard_decline`, `soft_decline`, or `outage`, in their transaction request. If the request is sent to a non-Spreedly Test gateway, the ‘simulate_decline’ gateway-specific field will be ignored.
A sample transaction request body might look as follows:
POST Request to `/v1/gateways/{{test_gateway_token}}/purchase.json`
When `simulate_decline` is included with a valid value (as noted above) the transaction will automatically fail. The mode specified by the value in `simulate_decline` will correspond to the error code returned by the failed transaction, and thus the action that will be taken by the Retry decision engine.
`simulate_decline` value |
Error Code |
Retry Action Taken |
`hard_decline` |
`insufficient_funds` |
Not Retried |
`soft_decline` |
`generic_decline` |
Retried - Only with `standard` Retry Mode |
`outage` |
`circuit_breaker_open` |
Retried - For both ‘standard’ and ‘outage_only’ mode |
Note: You must have an active gateway account and a valid testing payment method with a payment service provider to test transaction retry outside of Spreedly’s test gateway. Refer to our testing guide for more information.
Custom Error Code
If you wish to retry additional error codes that Spreedly initially classified as hard or unable to retry, you may specify in the purchase request the error codes or messages you would like to retry using the optional "custom_errors" object. When included, these values will also be considered in your retry logic as soft codes, alongside Spreedly’s global error configurations.
The name of the "custom_error" field depends on how the gateway sends back its response. Follow the below sample for an example of an added custom error field for each primary gateway supported today.
"retry": {
"gateway_tokens": ["gateway_token"],
"custom_errors": {
"braintree": {"error_codes": ["2015", "2047"]},
"cyber_source": {"error_codes": ["231", "237"]},
"orbital": {"messages": ["Pickup"]},
"adyen": {"messages": ["Refused | 82 : Policy"]},
"nmi":{"messages": ["Pick up card"]},
"conekta": {"messages": ["Tarjeta de prueba invalida"]},
"stripe": {"additional_data": ["lost_card", "fraudulent"], "error_codes": ["invalid_number"]},
"stripe_payment_intents": {"additional_data": ["lost_card", "fraudulent"], "error_codes": ["invalid_number"]},
"test": {"error_codes": ["hard_decline"]}
}
}
The name of the gateway custom_error key depends on where the gateway sends the response. As you can see in the sample above, Braintree and Cybersource both use the "error_code" field in the response to communicate, thus "error_codes" should be the key name. Orbital, Adyen, NMI, and Conekta use the "message" field to respond, thus "messages" should be used.
The logic for Stripe is a little more complex. Stripe uses "error_code" to respond to some errors. For these errors, "error_codes" should be used similarly to Braintree and Cyber Source. In other cases, Stripe sends a decline code back as a gateway-specific field. In the case that you would like to add a decline code, you can specify using the "additional_data" element.
All key values are case-sensitive, so make sure to double-check that they are spelled and capitalized correctly to match a gateway's response. If a custom error code is used to trigger a retry on a retry gateway, the payment response in the "payment_snapshot" will include "custom_error_used" which is set to true.
"payment_snapshot": {
....
"custom_error_used": true,
"attempts": 2
}
FAQs
Is there an extra cost to use Transaction Retry?
In Beta, there will be no additional charge for using Transaction Retry.
Once generally available, each retry will incur an additional billable API call. For example, if a purchase transaction fails on the primary gateway and goes to the first retry gateway this is counted as 2 billable API calls. Transaction Retry will not incur an additional API call for instances where a transaction is not retried due to a success or a hard error code.
Can I see which gateway error codes are classified as hard and soft?
Error codes are changing over time as gateways make updates. Please reach out to your account manager for the most recent mapping.
My desired primary gateway is not supported, can I still use Transaction Retry?
You can use Outage-only Retry for all gateways that Spreedly supports, but this will not work for gateway specific outage codes.
For our Standard Retry, the primary gateway must be on the list of supported gateways. If your desire primary gateway is not supported, you can either integrate with a supported gateway or contact your account manager or product@spreedly.com to request to add support for your primary gateway.
How do I turn on Transaction Retry?
Refer to How to Use Transaction Retry to get started today.
How can I view a report of which transactions were retried?
Go to the ‘Smart Routing’ tab in your dashboard to run a report on which transactions were retried.
Can I use Transaction Retry for transactions that have 3DS2 SCA requirements?
Yes, transaction retry works for 3DS2 Global-supported gateways. However, both the primary and retry gateway must support Spreedly 3DS2 Global. Gateways that support Spreedly 3DS2 Gateway Specific will not be supported at this time.
Can I use Transaction Retry with Stored Credentials?
Yes, as you can send stored_credential_ initiator and stored_credential_reason_type in the Transaction Retry request as described in the Stored Credential Guide. If the primary or retry gateway supports Stored Credentials, then the gateway will use Stored Credentials to supplement transaction decisions. If the gateway doesn’t support stored credentials, the Stored Credentials will be ignored and the transaction will proceed as usual.
Can I use Transaction Retry with Alternative Payment Methods?
At this time, transaction retry only works with credit and debit cards.
Does Transaction Retry Impact Cardholders?
For the vast majority of transactions, there is no impact on cardholders. For the portion of transactions that are retried on another gateway, there will be a slight added latency. We are tracking this latency during the beta period and will communicate the latency range when available.
In rare instances when a gateway sends us a soft error code but accepts an authorization and declines a capture, if the second gateway accepts the authorization the cardholder may see duplicate authorizations on their credit card statement. This is cosmetic and shouldn’t have an impact on settlement or money movement.