PlexySDK DOCS

Auto Rescue for SEPA

Intelligent retry strategies for SEPA Direct Debit payment failures and R-transactions

Auto Rescue for SEPA

Auto Rescue for SEPA automatically handles failed SEPA Direct Debit payments, including R-transactions (returns, refusals, and reversals). SEPA Direct Debit has unique timing requirements and failure modes that require specialized retry strategies.

SEPA Direct Debit Lifecycle

Understanding the SEPA payment lifecycle is essential for effective recovery:

R-Transaction Types

SEPA returns (R-transactions) have specific codes and meanings:

Return Codes (Most Common)

CodeNameDescriptionRetryable
AC01Incorrect Account NumberIBAN is wrongNo
AC04Closed AccountAccount has been closedNo
AC06Blocked AccountAccount is blockedMaybe
AG01Transaction ForbiddenNot authorized for DDNo
AG02Invalid Bank Operation CodeTechnical errorYes
AM04Insufficient FundsNot enough balanceYes
AM05Duplicate CollectionAlready debitedNo
BE05Unknown Creditor IDCreditor not recognizedNo
FF01Invalid File FormatTechnical errorYes
MD01No MandateMandate not found/cancelledNo
MD06Refund RequestCustomer requested refundNo
MS02Reason Not SpecifiedCustomer refusedMaybe
MS03Reason Not SpecifiedAgent refusedMaybe
RC01Bank Identifier IncorrectBIC is wrongNo
SL01Service Not AllowedDD not permittedNo

R-transactions typically arrive 2-5 business days after the debit date. Plexy automatically monitors for returns and initiates Auto Rescue when appropriate.

How Auto Rescue Handles SEPA

Enabling Auto Rescue for SEPA

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "payment_method_options": {
      "sepa_debit": {
        "mandate": "md_abc123"
      }
    },
    "auto_rescue": {
      "enabled": true,
      "max_retries": 3,
      "retry_window_days": 21
    },
    "metadata": {
      "subscription_id": "sub_monthly_123"
    }
  }'

SEPA-Specific Configuration

Retry Timing

SEPA has minimum timing requirements:

ConstraintRequirement
Minimum retry delay2 business days after R-transaction
Due date lead timeD-2 for Core, D-1 for B2B
Pre-notification14 days before first debit, unless agreed otherwise
Settlement time2-5 business days

Configure timing accordingly:

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "auto_rescue": {
      "enabled": true,
      "sepa_options": {
        "min_retry_interval_days": 5,
        "send_prenotification": true,
        "prenotification_days": 5
      },
      "max_retries": 3
    }
  }'

R-Code Strategies

Configure different strategies based on R-transaction codes:

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "auto_rescue": {
      "enabled": true,
      "r_code_strategies": {
        "AM04": {
          "retry": true,
          "schedule_days": [5, 12, 20],
          "notify_customer": true
        },
        "AC06": {
          "retry": true,
          "max_retries": 1,
          "schedule_days": [7],
          "escalate_on_failure": true
        },
        "MD01": {
          "retry": false,
          "action": "contact_customer",
          "deactivate_mandate": true
        },
        "MD06": {
          "retry": false,
          "action": "process_refund"
        }
      }
    }
  }'

Webhook Events

payment.sepa_return_received

Sent when an R-transaction is received.

{
  "id": "evt_abc123",
  "type": "payment.sepa_return_received",
  "created_at": "2026-03-28T09:15:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "EUR",
    "mandate": "md_abc123",
    "r_transaction": {
      "code": "AM04",
      "reason": "Insufficient Funds",
      "received_at": "2026-03-28T09:15:00Z",
      "original_debit_date": "2026-03-25"
    },
    "auto_rescue": {
      "enabled": true,
      "will_retry": true,
      "next_retry_at": "2026-04-02T10:00:00Z"
    }
  }
}

payment.rescue_retry (SEPA)

Sent when a SEPA retry is being attempted.

{
  "id": "evt_def456",
  "type": "payment.rescue_retry",
  "created_at": "2026-04-02T10:00:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "payment_method_type": "sepa_debit",
    "retry_number": 1,
    "previous_r_code": "AM04",
    "debit_date": "2026-04-07",
    "prenotification_sent": true,
    "retry_strategy": {
      "r_code_category": "insufficient_funds",
      "timing_reason": "payday_alignment"
    }
  }
}

payment.rescue_succeeded (SEPA)

Sent when a SEPA payment is successfully recovered.

{
  "id": "evt_ghi789",
  "type": "payment.rescue_succeeded",
  "created_at": "2026-04-10T14:30:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "EUR",
    "retry_number": 1,
    "total_attempts": 2,
    "days_to_recover": 15,
    "settlement_date": "2026-04-10"
  }
}

sepa_mandate.requires_attention

Sent when a mandate issue is detected.

{
  "id": "evt_jkl012",
  "type": "sepa_mandate.requires_attention",
  "created_at": "2026-03-28T09:20:00Z",
  "data": {
    "mandate": "md_abc123",
    "customer": "cus_abc123",
    "issue": "mandate_cancelled",
    "r_code": "MD01",
    "triggered_by_payment": "pay_xyz789",
    "recommendation": "Contact customer to set up a new mandate"
  }
}

Handling R-Transaction Types

Insufficient Funds (AM04)

The most common return reason, often resolved with proper timing.

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "auto_rescue": {
      "enabled": true,
      "r_code_strategies": {
        "AM04": {
          "retry": true,
          "schedule_days": [5, 16, 26],
          "max_retries": 3,
          "notify_customer_after_attempt": 1
        }
      }
    }
  }'

Account Closed (AC04) or Incorrect (AC01)

Permanent issues requiring new account details.

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

  if (event.type === 'payment.sepa_return_received') {
    const { r_transaction, customer } = event.data;

    if (['AC01', 'AC04'].includes(r_transaction.code)) {
      // Deactivate the payment method
      await plexy.paymentMethods.update(event.data.payment_method, {
        active: false,
        deactivation_reason: r_transaction.reason,
      });

      // Contact customer for new account details
      await sendEmail(customer, 'sepa_account_invalid', {
        reason: r_transaction.reason,
        update_url: 'https://yoursite.com/update-payment',
      });
    }
  }

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

Mandate Issues (MD01, MD06)

Mandate-related returns require special handling.

When you receive an MD01 return, cancel the mandate via PATCH https://api.plexypay.com/v2/mandates/{mandate_id} and notify the customer to set up a new one. When you receive an MD06 return, issue a refund via POST https://api.plexypay.com/v2/refunds:

curl -X POST https://api.plexypay.com/v2/refunds \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payment": "pay_xyz789",
    "reason": "customer_request_via_bank"
  }'

SEPA Core vs B2B

Auto Rescue handles both SEPA schemes:

AspectSEPA CoreSEPA B2B
Refund right8 weeks (no questions)None
Mandate verificationOptionalRequired
Minimum lead timeD-2D-1
Retry approachMore conservativeCan be more aggressive

Configure by Scheme

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "payment_method_options": {
      "sepa_debit": {
        "mandate": "md_abc123",
        "scheme": "b2b"
      }
    },
    "auto_rescue": {
      "enabled": true,
      "sepa_options": {
        "scheme_specific": {
          "core": {
            "max_retries": 2,
            "retry_window_days": 14
          },
          "b2b": {
            "max_retries": 3,
            "retry_window_days": 21
          }
        }
      }
    }
  }'

Pre-Notification Management

SEPA requires customer notification before debits:

curl -X POST https://api.plexypay.com/v2/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "EUR",
    "customer": "cus_abc123",
    "payment_method": "pm_sepa_debit_xyz789",
    "auto_rescue": {
      "enabled": true,
      "sepa_options": {
        "send_prenotification": true,
        "prenotification_days": 5,
        "prenotification_template": "retry_notification"
      }
    }
  }'

Pre-Notification Webhook

{
  "id": "evt_mno345",
  "type": "sepa_prenotification.sent",
  "created_at": "2026-03-27T10:00:00Z",
  "data": {
    "payment": "pay_xyz789",
    "customer": "cus_abc123",
    "amount": 4999,
    "currency": "EUR",
    "debit_date": "2026-04-01",
    "is_retry": true,
    "retry_number": 1,
    "notification_type": "email"
  }
}

Best Practices

Timing Around Paydays

In Europe, common paydays include:

  • End of month (25th-31st)
  • Mid-month (15th)
  • Beginning of month (1st-5th)
// Optimal retry schedule for EU paydays
auto_rescue: {
  enabled: true,
  sepa_options: {
    // Schedule debits for 2-3 days after typical paydays
    preferred_debit_days: [3, 17, 28],
  },
}

Monitor Mandate Health

Track mandate-related returns:

// Fetch mandate analytics
const mandateHealth = await plexy.analytics.getMandateHealth({
  start_date: '2026-01-01',
  end_date: '2026-03-31',
});

// Response includes:
// {
//   "total_mandates": 5234,
//   "active": 5012,
//   "cancelled_by_customer": 89,
//   "cancelled_by_r_transaction": 133,
//   "r_transaction_breakdown": {
//     "MD01": 98,
//     "MD06": 35
//   }
// }

Respect Customer Requests

When you receive MD06 (refund request by customer), consider:

  1. Processing the refund promptly
  2. Reviewing the customer's subscription status
  3. Reaching out to understand the reason
  4. Potentially pausing future debits
if (r_code === 'MD06') {
  // Customer went to their bank for a refund - take it seriously
  await pauseSubscription(customer);
  await sendEmail(customer, 'subscription_paused', {
    reason: 'bank_refund_request',
    contact_us: true,
  });
}

Know When to Stop

Unlike cards, SEPA retries should be more conservative:

FactorRecommendation
Max retries2-3 (not 4-5 like cards)
Window14-21 days
After MD01/MD06Never retry
Multiple AM04sConsider contacting customer

Next Steps

On this page