Auto Rescue for Cards
Intelligent retry strategies optimized for card payment failures
Auto Rescue for Cards
Auto Rescue for Cards applies specialized recovery strategies for failed card payments. By analyzing decline codes and issuer behavior, Plexy determines the optimal retry timing and approach to maximize recovery rates.
Card Decline Categories
Card declines fall into three categories, each with different recovery strategies:
Soft Declines
Temporary issues that often resolve with time or after card updates.
| Decline Code | Description | Recovery Strategy |
|---|---|---|
insufficient_funds | Card has insufficient balance | Retry after typical payday (1-3 days) |
exceeds_limit | Over daily/monthly spending limit | Retry after limit reset (1-7 days) |
try_again_later | Issuer requests retry | Retry in 24-48 hours |
do_not_honor | Generic soft decline | Retry with Account Updater check |
card_velocity_exceeded | Too many transactions | Retry after 24-72 hours |
processing_error | Temporary processing issue | Retry in 1-4 hours |
Technical Errors
Infrastructure issues requiring immediate retry.
| Error Code | Description | Recovery Strategy |
|---|---|---|
network_timeout | Connection timed out | Immediate retry (3x) |
gateway_error | Payment gateway issue | Immediate retry |
issuer_unavailable | Issuer system down | Retry every 15-30 minutes |
system_error | Plexy system issue | Automatic failover |
Hard Declines
Permanent issues that should not be retried.
| Decline Code | Description | Action |
|---|---|---|
stolen_card | Card reported stolen | Stop, deactivate payment method |
lost_card | Card reported lost | Stop, deactivate payment method |
fraudulent | Suspected fraud | Stop, flag for review |
pickup_card | Issuer requests card retrieval | Stop, deactivate payment method |
invalid_account | Account doesn't exist | Stop, contact customer |
expired_card | Card has expired | Check Account Updater, then stop if no update |
restricted_card | Card is restricted | Stop, contact customer |
Never retry hard declines. Doing so can damage your relationship with issuers, increase your fraud rate, and may violate card network rules.
Retry Schedules
Default ML-Optimized Schedule
Plexy's machine learning model optimizes retry timing based on:
- Historical recovery patterns
- Decline code analysis
- Issuer-specific behavior
- Day of week and time of month patterns
Typical ML-optimized schedule for insufficient_funds:
| Retry | Timing | Rationale |
|---|---|---|
| 1 | Day 1-2 | Quick follow-up |
| 2 | Day 3-5 | After initial payday window |
| 3 | Day 7-10 | Mid-month window |
| 4 | Day 14-15 | Second payday window |
Custom Schedule Configuration
Override the default schedule for specific needs:
curl -X POST https://api.plexypay.com/v2/payments \
-H "x-api-key: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 9900,
"currency": "USD",
"customer": "cus_abc123",
"payment_method": "pm_card_visa_abc123",
"off_session": true,
"auto_rescue": {
"enabled": true,
"retry_schedule": "custom",
"custom_schedule_days": [1, 3, 7, 14],
"max_retries": 4,
"retry_window_days": 14
}
}'const payment = await plexy.payments.create({
amount: 9900,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
auto_rescue: {
enabled: true,
retry_schedule: 'custom',
custom_schedule_days: [1, 3, 7, 14],
max_retries: 4,
retry_window_days: 14,
},
});payment = plexy.payments.create(
amount=9900,
currency='USD',
customer='cus_abc123',
payment_method='pm_card_visa_abc123',
off_session=True,
auto_rescue={
'enabled': True,
'retry_schedule': 'custom',
'custom_schedule_days': [1, 3, 7, 14],
'max_retries': 4,
'retry_window_days': 14,
},
)Decline-Specific Schedules
Configure different schedules based on decline type:
const payment = await plexy.payments.create({
amount: 9900,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
auto_rescue: {
enabled: true,
decline_strategies: {
insufficient_funds: {
schedule_days: [1, 3, 7, 15], // Align with paydays
max_retries: 4,
},
try_again_later: {
schedule_hours: [4, 12, 24], // Shorter intervals
max_retries: 3,
},
do_not_honor: {
schedule_days: [1, 3], // Limited retries
max_retries: 2,
check_account_updater: true, // Always check for updates
},
},
},
});Integration with Account Updater
Auto Rescue automatically checks Account Updater before each retry attempt:
Response with Account Updater
{
"id": "pay_xyz789",
"status": "succeeded",
"auto_rescue": {
"status": "recovered",
"attempts_made": 2,
"recovered_at": "2026-03-27T10:30:00Z"
},
"rescue_history": [
{
"attempt": 1,
"attempted_at": "2026-03-25T10:30:00Z",
"result": "failed",
"failure_code": "expired_card",
"account_updater_checked": true,
"card_was_updated": false
},
{
"attempt": 2,
"attempted_at": "2026-03-27T10:30:00Z",
"result": "succeeded",
"account_updater_checked": true,
"card_was_updated": true,
"update_type": "new_expiry"
}
]
}Network Token Priority
When a card has an active network token, Auto Rescue uses it for retries:
| Scenario | Behavior |
|---|---|
| Network token active | Use network token for all retries |
| Network token updated | Use updated token credentials |
| Network token inactive | Fall back to stored PAN |
{
"rescue_history": [
{
"attempt": 2,
"result": "succeeded",
"network_token_used": true,
"network_token_status": "active"
}
]
}Webhook Events
payment.rescue_retry (Cards)
{
"id": "evt_abc123",
"type": "payment.rescue_retry",
"created_at": "2026-03-26T10:30:00Z",
"data": {
"payment": "pay_xyz789",
"customer": "cus_abc123",
"payment_method": "pm_card_visa_abc123",
"retry_number": 1,
"previous_decline_code": "insufficient_funds",
"account_updater_checked": true,
"card_was_updated": false,
"network_token_used": true,
"retry_strategy": {
"decline_category": "soft_decline",
"timing_reason": "payday_alignment"
}
}
}payment.rescue_succeeded (Cards)
{
"id": "evt_def456",
"type": "payment.rescue_succeeded",
"created_at": "2026-03-28T14:15:00Z",
"data": {
"payment": "pay_xyz789",
"customer": "cus_abc123",
"amount": 9900,
"currency": "USD",
"retry_number": 2,
"total_attempts": 3,
"days_to_recover": 3,
"recovery_factors": {
"card_was_updated": true,
"update_type": "new_expiry",
"network_token_used": true
}
}
}Handling Specific Decline Codes
Insufficient Funds
The most common soft decline, often recovering after payday.
// Configure payday-optimized retries
const payment = await plexy.payments.create({
amount: 9900,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
auto_rescue: {
enabled: true,
decline_strategies: {
insufficient_funds: {
// Retry around typical paydays (1st, 15th, Fridays)
schedule_days: [1, 3, 7, 15, 16],
max_retries: 5,
notify_customer_after_attempt: 2, // Email after 2nd failure
},
},
},
});Expired Card
First check Account Updater, then contact customer if no update found.
app.post('/webhooks/plexy', async (req, res) => {
const event = verifyWebhook(req);
if (event.type === 'payment.rescue_retry') {
const { previous_decline_code, card_was_updated } = event.data;
if (previous_decline_code === 'expired_card' && !card_was_updated) {
// No update found for expired card - contact customer
await sendEmail(event.data.customer, 'card_expired_update_needed', {
update_url: 'https://yoursite.com/update-payment',
});
}
}
res.status(200).send('OK');
});Do Not Honor
A catch-all decline that may indicate various issues.
// Limited retries for "do not honor" - may be semi-hard decline
const payment = await plexy.payments.create({
amount: 9900,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
auto_rescue: {
enabled: true,
decline_strategies: {
do_not_honor: {
schedule_days: [1, 3],
max_retries: 2,
check_account_updater: true, // May be outdated card
try_alternate_payment_method: true, // Try backup if available
},
},
},
});Card Brand-Specific Behavior
Different card networks have unique characteristics:
| Network | Notes |
|---|---|
| Visa | Most predictable retry behavior |
| Mastercard | Strong Account Updater support |
| American Express | May require shorter retry windows |
| Discover | Limited Account Updater coverage |
Configure by Card Brand
const payment = await plexy.payments.create({
amount: 9900,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
auto_rescue: {
enabled: true,
card_brand_strategies: {
visa: {
max_retries: 4,
schedule_days: [1, 3, 7, 14],
},
mastercard: {
max_retries: 4,
schedule_days: [1, 3, 7, 14],
},
amex: {
max_retries: 3,
schedule_days: [1, 3, 7], // Shorter window for Amex
},
},
},
});Best Practices
Monitor by Decline Code
Track recovery rates by decline code to optimize your strategy:
// Fetch Auto Rescue analytics
const analytics = await plexy.autoRescue.getAnalytics({
start_date: '2026-03-01',
end_date: '2026-03-31',
group_by: 'decline_code',
});
// Example response
// {
// "insufficient_funds": { "attempts": 1234, "recovered": 456, "rate": 0.37 },
// "do_not_honor": { "attempts": 567, "recovered": 89, "rate": 0.16 },
// "expired_card": { "attempts": 234, "recovered": 167, "rate": 0.71 }
// }Combine with Dunning
Coordinate Auto Rescue with customer communications:
| Retry Attempt | Customer Communication |
|---|---|
| Initial failure | Optional: "Payment failed, we'll retry" |
| After 2nd failure | "Payment still failing, please check card" |
| After 3rd failure | "Urgent: Update payment method" |
| Final failure | "Service will be suspended" |
Avoid Over-Retrying
Too many retries can:
- Annoy customers
- Damage issuer relationships
- Increase fraud flags
Recommended limits:
| Payment Type | Max Retries | Window |
|---|---|---|
| Subscription (< $50) | 4 | 14 days |
| Subscription (> $50) | 3 | 10 days |
| One-time purchase | 2 | 7 days |
Next Steps
- Auto Rescue for SEPA - SEPA Direct Debit retries
- Auto Rescue Overview - General Auto Rescue concepts
- Account Updater - Keep cards current