PlexySDK DOCS

Auto Rescue

Automatically recover failed payments with intelligent retry logic and optimized timing

Auto Rescue

Auto Rescue automatically retries failed payments using machine learning-optimized strategies to maximize recovery rates. Instead of immediately failing a payment when declined, Auto Rescue analyzes the failure reason and schedules intelligent retries at optimal times.

How Auto Rescue Works

When a payment fails, Auto Rescue evaluates the decline reason and determines the best recovery strategy:

Why Auto Rescue Works

Auto Rescue combines multiple optimization techniques:

TechniqueDescriptionImpact
Optimal timingML-predicted best times to retry+15-25% recovery
Account UpdaterCheck for card updates before retry+5-10% recovery
Network tokensUse network tokens when available+2-5% auth rate
Decline analysisDifferent strategies per decline typeTargeted retries
Issuer intelligenceLearned issuer behaviors and preferencesBetter timing

Enabling Auto Rescue

Per-Payment Basis

Enable Auto Rescue for individual payments:

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "USD",
    "customer": "cus_abc123",
    "payment_method": "pm_card_visa_abc123",
    "off_session": true,
    "auto_rescue": {
      "enabled": true,
      "max_retries": 4,
      "retry_window_days": 14
    },
    "metadata": {
      "subscription_id": "sub_xyz789"
    }
  }'
import { Plexy } from '@plexy/plexy-web';

const plexy = new Plexy({
  apiKey: process.env.PLEXY_SECRET_KEY,
});

const payment = await plexy.payments.create({
  amount: 4999,
  currency: 'USD',
  customer: 'cus_abc123',
  payment_method: 'pm_card_visa_abc123',
  off_session: true,
  auto_rescue: {
    enabled: true,
    max_retries: 4,
    retry_window_days: 14,
  },
  metadata: {
    subscription_id: 'sub_xyz789',
  },
});

if (payment.status === 'requires_rescue') {
  console.log('Payment failed, Auto Rescue initiated');
  console.log('First retry scheduled:', payment.rescue_schedule.next_retry_at);
}
import os
from plexy import Plexy

plexy = Plexy(api_key=os.environ['PLEXY_SECRET_KEY'])

payment = plexy.payments.create(
    amount=4999,
    currency='USD',
    customer='cus_abc123',
    payment_method='pm_card_visa_abc123',
    off_session=True,
    auto_rescue={
        'enabled': True,
        'max_retries': 4,
        'retry_window_days': 14,
    },
    metadata={
        'subscription_id': 'sub_xyz789',
    },
)

if payment.status == 'requires_rescue':
    print('Payment failed, Auto Rescue initiated')
    print(f"First retry scheduled: {payment.rescue_schedule['next_retry_at']}")

Account-Level Default

Enable Auto Rescue for all qualifying payments in Plexy Dashboard:

Go to Settings > Account Management > Auto Rescue.

Toggle Auto Rescue to enabled.

Set default parameters:

  • Maximum retries: 1-8 retry attempts
  • Retry window: 7-30 days
  • Retry schedule: Automatic (ML-optimized) or Custom

Choose which payment types qualify:

  • Subscription payments
  • Off-session payments
  • Payments over threshold amount

Configuration Options

ParameterTypeDefaultDescription
enabledbooleanfalseEnable Auto Rescue for this payment
max_retriesinteger4Maximum number of retry attempts (1-8)
retry_window_daysinteger14Days to continue retrying (7-30)
retry_schedulestring"automatic""automatic" or "custom"
custom_schedule_daysarray-Custom retry days, e.g., [1, 3, 7, 14]
notify_customerbooleantrueSend customer notifications on retry events
check_account_updaterbooleantrueCheck for card updates before each retry

Custom Retry Schedule

Define your own retry timing:

const payment = await plexy.payments.create({
  amount: 4999,
  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, 2, 5, 10, 15], // Retry on days 1, 2, 5, 10, 15
    max_retries: 5,
  },
});

Decline Categories and Handling

Auto Rescue categorizes declines and applies different strategies:

Soft Declines (Retryable)

Temporary issues that often resolve with time.

Decline CodeDescriptionStrategy
insufficient_fundsNot enough balanceRetry after payday (1-3 days)
try_again_laterIssuer requests retryRetry in 24-48 hours
exceeds_limitOver daily/weekly limitRetry after limit reset
issuer_unavailableIssuer system downImmediate retry
processing_errorGeneric processing issueRetry in 24 hours

Technical Errors (Immediate Retry)

Infrastructure issues that may resolve quickly.

Error CodeDescriptionStrategy
network_timeoutConnection timeoutImmediate retry
gateway_errorPayment gateway issueImmediate retry
system_errorPlexy system issueImmediate retry

Hard Declines (No Retry)

Permanent issues requiring customer action.

Decline CodeDescriptionAction
stolen_cardCard reported stolenStop, notify merchant
lost_cardCard reported lostStop, notify merchant
fraud_suspectedIssuer suspects fraudStop, contact customer
card_not_supportedCard type not acceptedStop, request new card
account_closedAccount permanently closedStop, request new card

Hard declines are never retried. Attempting to retry these can damage your relationship with issuers and increase your fraud rate.

Payment Status During Rescue

StatusDescription
requires_rescueInitial payment failed, retries scheduled
rescue_in_progressCurrently attempting a retry
succeededPayment recovered successfully
failedAll retries exhausted, payment failed permanently
rescue_cancelledAuto Rescue was manually cancelled

API Response with Auto Rescue

Initial Payment Failure

{
  "id": "pay_xyz789",
  "object": "payment",
  "amount": 4999,
  "currency": "USD",
  "status": "requires_rescue",
  "customer": "cus_abc123",
  "payment_method": "pm_card_visa_abc123",
  "failure_code": "insufficient_funds",
  "failure_message": "The card has insufficient funds.",
  "auto_rescue": {
    "enabled": true,
    "status": "active",
    "attempts_made": 1,
    "max_retries": 4,
    "retry_window_ends_at": "2026-04-08T10:30:00Z"
  },
  "rescue_schedule": {
    "next_retry_at": "2026-03-26T10:30:00Z",
    "retry_number": 1,
    "scheduled_retries": [
      { "retry_number": 1, "scheduled_at": "2026-03-26T10:30:00Z" },
      { "retry_number": 2, "scheduled_at": "2026-03-28T14:00:00Z" },
      { "retry_number": 3, "scheduled_at": "2026-04-01T10:30:00Z" },
      { "retry_number": 4, "scheduled_at": "2026-04-08T10:30:00Z" }
    ]
  },
  "created_at": "2026-03-25T10:30:00Z"
}

Successful Recovery

{
  "id": "pay_xyz789",
  "object": "payment",
  "amount": 4999,
  "currency": "USD",
  "status": "succeeded",
  "customer": "cus_abc123",
  "payment_method": "pm_card_visa_abc123",
  "auto_rescue": {
    "enabled": true,
    "status": "recovered",
    "attempts_made": 3,
    "max_retries": 4,
    "recovered_at": "2026-04-01T10:35:00Z"
  },
  "rescue_history": [
    {
      "attempt": 1,
      "attempted_at": "2026-03-25T10:30:00Z",
      "result": "failed",
      "failure_code": "insufficient_funds"
    },
    {
      "attempt": 2,
      "attempted_at": "2026-03-26T10:30:00Z",
      "result": "failed",
      "failure_code": "insufficient_funds"
    },
    {
      "attempt": 3,
      "attempted_at": "2026-04-01T10:35:00Z",
      "result": "succeeded"
    }
  ],
  "created_at": "2026-03-25T10:30:00Z"
}

Webhook Events

payment.rescue_started

Sent when Auto Rescue begins for a failed payment.

{
  "id": "evt_abc123",
  "type": "payment.rescue_started",
  "created_at": "2026-03-25T10:30:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "USD",
    "failure_code": "insufficient_funds",
    "rescue_schedule": {
      "max_retries": 4,
      "first_retry_at": "2026-03-26T10:30:00Z",
      "final_retry_at": "2026-04-08T10:30:00Z"
    }
  }
}

payment.rescue_retry

Sent before each retry attempt.

{
  "id": "evt_def456",
  "type": "payment.rescue_retry",
  "created_at": "2026-03-26T10:30:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "retry_number": 1,
    "attempts_remaining": 3,
    "account_updater_checked": true,
    "card_was_updated": false
  }
}

payment.rescue_succeeded

Sent when a payment is successfully recovered.

{
  "id": "evt_ghi789",
  "type": "payment.rescue_succeeded",
  "created_at": "2026-04-01T10:35:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "USD",
    "retry_number": 3,
    "total_attempts": 3,
    "days_to_recover": 7
  }
}

payment.rescue_failed

Sent when all retry attempts are exhausted.

{
  "id": "evt_jkl012",
  "type": "payment.rescue_failed",
  "created_at": "2026-04-08T10:35:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "USD",
    "total_attempts": 5,
    "final_failure_code": "insufficient_funds",
    "recommendation": "Contact customer to update payment method"
  }
}

Managing Active Rescues

List Payments in Rescue

curl "https://api.plexypay.com/v2/payments?status=requires_rescue" \
  -H "x-api-key: Bearer YOUR_API_KEY"
const payments = await plexy.payments.list({
  status: 'requires_rescue',
});

for (const payment of payments.data) {
  console.log(`Payment ${payment.id}: next retry ${payment.rescue_schedule.next_retry_at}`);
}
payments = plexy.payments.list(status='requires_rescue')

for payment in payments.data:
    print(f"Payment {payment.id}: next retry {payment.rescue_schedule['next_retry_at']}")

Cancel Auto Rescue

Stop retrying a specific payment:

curl -X POST https://api.plexypay.com/v2/payments/pay_xyz789/cancel_rescue \
  -H "x-api-key: Bearer YOUR_API_KEY"
const payment = await plexy.payments.cancelRescue('pay_xyz789');

console.log('Rescue cancelled:', payment.auto_rescue.status);
payment = plexy.payments.cancel_rescue('pay_xyz789')

print(f"Rescue cancelled: {payment.auto_rescue['status']}")

Trigger Immediate Retry

Force an immediate retry attempt:

curl -X POST https://api.plexypay.com/v2/payments/pay_xyz789/retry_now \
  -H "x-api-key: Bearer YOUR_API_KEY"

Best Practices

Combine with Customer Communication

Use webhooks to coordinate Auto Rescue with customer notifications:

app.post('/webhooks/plexy', async (req, res) => {
  const event = verifyWebhook(req);

  switch (event.type) {
    case 'payment.rescue_started':
      // Send initial notification
      await sendEmail(event.data.customer, 'payment_failed_retrying', {
        amount: formatCurrency(event.data.amount, event.data.currency),
        next_retry: event.data.rescue_schedule.first_retry_at,
      });
      break;

    case 'payment.rescue_failed':
      // All retries failed - urgent action needed
      await sendEmail(event.data.customer, 'payment_failed_final', {
        amount: formatCurrency(event.data.amount, event.data.currency),
        update_url: `https://yoursite.com/update-payment`,
      });
      break;

    case 'payment.rescue_succeeded':
      // Payment recovered - send confirmation
      await sendEmail(event.data.customer, 'payment_recovered', {
        amount: formatCurrency(event.data.amount, event.data.currency),
      });
      break;
  }

  res.status(200).send('OK');
});

Monitor Recovery Metrics

Track Auto Rescue performance in Plexy Dashboard:

MetricDescriptionTarget
Recovery rate% of failed payments recovered> 30%
Average recovery timeDays to successful retry< 7 days
Retry success by attemptWhich retry number succeeds mostOptimize schedule
Recovery by decline typeSuccess rate per decline reasonIdentify patterns

Set Appropriate Retry Windows

Match your retry window to your billing cycle:

Billing CycleRecommended WindowRationale
Weekly7 daysCapture next week's billing
Monthly14-21 daysAllow for payday cycles
Annual30 daysMaximum recovery opportunity

Next Steps

На этой странице