Real-Time Account Updater
Automatically check for card updates at the moment of payment to maximize authorization rates
Real-Time Account Updater
Real-Time Account Updater queries card networks for updated credentials at the exact moment you attempt a payment. If the card has been replaced or renewed, Plexy automatically uses the new details, maximizing your chances of a successful authorization.
How It Works
When you submit a payment with Real-Time Account Updater enabled, Plexy checks for card updates before sending the authorization request:
The Real-Time Account Updater query typically adds 50-200ms to payment processing. This small latency increase is usually offset by significantly higher authorization rates.
Enabling Real-Time Updates
Per-Payment Basis
Enable Real-Time Account Updater 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,
"account_updater": {
"enabled": true,
"mode": "realtime"
},
"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,
account_updater: {
enabled: true,
mode: 'realtime',
},
metadata: {
subscription_id: 'sub_xyz789',
},
});
console.log('Payment status:', payment.status);
if (payment.account_updater_result) {
console.log('Card was updated:', payment.account_updater_result.update_type);
}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,
account_updater={
'enabled': True,
'mode': 'realtime',
},
metadata={
'subscription_id': 'sub_xyz789',
},
)
print(f"Payment status: {payment.status}")
if payment.account_updater_result:
print(f"Card was updated: {payment.account_updater_result['update_type']}")Account-Level Default
Enable Real-Time Account Updater for all off-session payments in Plexy Dashboard:
Navigate to Settings > Account Management > Account Updater.
Toggle Real-Time Account Updater to enabled.
Choose when to apply:
- All off-session payments (recommended)
- Subscription payments only
- Payments over threshold amount
API Response Fields
When Real-Time Account Updater runs, the payment response includes additional fields:
Successful Payment with Update
{
"id": "pay_xyz789",
"object": "payment",
"amount": 4999,
"currency": "USD",
"status": "succeeded",
"customer": "cus_abc123",
"payment_method": "pm_card_visa_abc123",
"payment_method_details": {
"type": "card",
"card": {
"brand": "visa",
"last4": "8910",
"exp_month": 6,
"exp_year": 2030
}
},
"account_updater_result": {
"queried": true,
"update_found": true,
"update_type": "new_pan",
"update_applied": true,
"previous_card": {
"last4": "4242",
"exp_month": 12,
"exp_year": 2026
},
"updated_card": {
"last4": "8910",
"exp_month": 6,
"exp_year": 2030
}
},
"created_at": "2026-03-25T10:30:00Z"
}Payment with No Update Needed
{
"id": "pay_abc456",
"object": "payment",
"amount": 4999,
"currency": "USD",
"status": "succeeded",
"customer": "cus_abc123",
"payment_method": "pm_card_visa_abc123",
"payment_method_details": {
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2028
}
},
"account_updater_result": {
"queried": true,
"update_found": false,
"update_type": "no_update"
},
"created_at": "2026-03-25T10:35:00Z"
}Payment Failed - Account Closed
{
"id": "pay_def789",
"object": "payment",
"amount": 4999,
"currency": "USD",
"status": "failed",
"failure_code": "card_not_supported",
"failure_message": "The card account has been closed.",
"customer": "cus_abc123",
"payment_method": "pm_card_visa_abc123",
"account_updater_result": {
"queried": true,
"update_found": true,
"update_type": "account_closed",
"update_applied": false,
"action_required": "contact_cardholder"
},
"created_at": "2026-03-25T10:40:00Z"
}Response Field Reference
| Field | Type | Description |
|---|---|---|
account_updater_result.queried | boolean | Whether Account Updater was checked |
account_updater_result.update_found | boolean | Whether an update was found |
account_updater_result.update_type | string | Type of update: new_pan, new_expiry, account_closed, contact_cardholder, no_update |
account_updater_result.update_applied | boolean | Whether the update was applied to the payment method |
account_updater_result.previous_card | object | Card details before the update |
account_updater_result.updated_card | object | Card details after the update |
account_updater_result.action_required | string | Recommended action if update couldn't be applied |
Handling Update Types
New Card Number (new_pan)
The cardholder received a replacement card with a new number.
if (payment.account_updater_result?.update_type === 'new_pan') {
// Card was automatically updated
// Log the change for your records
await logCardUpdate({
customer: payment.customer,
oldLast4: payment.account_updater_result.previous_card.last4,
newLast4: payment.account_updater_result.updated_card.last4,
reason: 'account_updater_new_pan',
});
// Update any customer-facing displays
await updateCustomerCardDisplay(payment.customer);
}New Expiration Date (new_expiry)
The card was renewed with a new expiration date.
if (payment.account_updater_result?.update_type === 'new_expiry') {
// Card expiry was automatically updated
const { previous_card, updated_card } = payment.account_updater_result;
console.log(
`Card expiry updated from ${previous_card.exp_month}/${previous_card.exp_year} ` +
`to ${updated_card.exp_month}/${updated_card.exp_year}`,
);
}Account Closed
The cardholder's account has been closed. The payment will fail.
if (payment.account_updater_result?.update_type === 'account_closed') {
// Mark the payment method as inactive
await plexy.paymentMethods.update(payment.payment_method, {
active: false,
deactivation_reason: 'account_closed',
});
// Queue customer outreach
await notificationService.send({
type: 'payment_method_expired',
customer: payment.customer,
message:
'Your saved card is no longer valid. Please update your payment method.',
});
}Contact Cardholder
No update was found, but the card may be outdated. The payment may still succeed, but you should follow up with the customer.
if (payment.account_updater_result?.update_type === 'contact_cardholder') {
if (payment.status === 'succeeded') {
// Payment succeeded, but card may need attention soon
await queueFollowUp({
customer: payment.customer,
priority: 'low',
reason: 'card_may_need_update',
});
} else {
// Payment failed, contact customer urgently
await queueFollowUp({
customer: payment.customer,
priority: 'high',
reason: 'payment_failed_update_card',
});
}
}Webhook Notifications
In addition to the API response, Plexy sends webhooks for card updates:
payment_method.updated
Sent when a card is successfully updated during a real-time query.
{
"id": "evt_abc123",
"type": "payment_method.updated",
"created_at": "2026-03-25T10:30:00Z",
"data": {
"payment_method": "pm_card_visa_abc123",
"customer": "cus_abc123",
"update_source": "realtime_account_updater",
"update_type": "new_pan",
"triggered_by_payment": "pay_xyz789",
"changes": {
"last4": {
"old": "4242",
"new": "8910"
},
"exp_month": {
"old": 12,
"new": 6
},
"exp_year": {
"old": 2026,
"new": 2030
}
}
}
}Best Practices
Enable for All Recurring Payments
Real-Time Account Updater is most valuable for recurring and subscription payments:
async function processSubscriptionPayment(subscription) {
const payment = await plexy.payments.create({
amount: subscription.amount,
currency: subscription.currency,
customer: subscription.customer,
payment_method: subscription.payment_method,
off_session: true,
account_updater: {
enabled: true,
mode: 'realtime',
},
metadata: {
subscription_id: subscription.id,
billing_period: subscription.current_period,
},
});
return payment;
}Combine with Auto Rescue
If Real-Time Account Updater reports an account closure or contact recommendation, enable Auto Rescue for fallback retries:
const payment = await plexy.payments.create({
amount: 4999,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
off_session: true,
account_updater: {
enabled: true,
mode: 'realtime',
},
auto_rescue: {
enabled: true,
max_retries: 4,
},
});Log All Updates
Keep a record of all card updates for compliance and customer service:
app.post('/webhooks/plexy', async (req, res) => {
const event = verifyWebhook(req);
if (event.type === 'payment_method.updated') {
await db.cardUpdates.create({
payment_method: event.data.payment_method,
customer: event.data.customer,
update_source: event.data.update_source,
update_type: event.data.update_type,
changes: event.data.changes,
triggered_by: event.data.triggered_by_payment,
timestamp: event.created_at,
});
}
res.status(200).send('OK');
});Latency Considerations
Real-Time Account Updater adds processing time:
| Scenario | Additional Latency |
|---|---|
| No update found | 50-100ms |
| Update found and applied | 100-200ms |
| Network timeout (falls back) | 500ms max |
If the Real-Time Account Updater query times out, Plexy automatically proceeds with the original card details. The payment will still be attempted.
Disabling for Time-Sensitive Payments
For extremely time-sensitive transactions, you can disable Real-Time Account Updater:
const payment = await plexy.payments.create({
amount: 100,
currency: 'USD',
customer: 'cus_abc123',
payment_method: 'pm_card_visa_abc123',
account_updater: {
enabled: false, // Skip real-time check for this payment
},
});Next Steps
- Batch Account Updater - Proactive scheduled updates
- Account Updater Overview - Compare real-time and batch modes
- Auto Rescue - Recover failed payments