PAYMENTS

Stripe: Payment Infrastructure at Scale

A deep technical guide to building payment systems with Stripe. Covers Payment Intents, Checkout, subscriptions, webhook handling, Connect for multi-party payments, payouts, multi-currency localization, PCI compliance, Stripe Radar fraud prevention, customer portal, payment methods (cards/SEPA/iDEAL/Boleto), disputes/chargebacks, and testing strategies with test clocks.

1. Payment Intents and Checkout

Payment Intents

Payment Intents are the core of Stripe's payment API. A PaymentIntent tracks the lifecycle of a payment from creation to completion. It handles authentication (3D Secure), retries, and multi-step payment flows.

  • Lifecycle: requires_payment_method -> requires_confirmation -> requires_action (3DS) -> processing -> succeeded/canceled
  • Idempotency: Use idempotency keys on creation to prevent duplicate charges. Critical for retry logic and unreliable networks
  • Capture later: Create with capture_method: 'manual' to authorize without capturing. Capture within 7 days. Use for hold-then-charge flows (bookings, pre-orders)
  • Metadata: Attach up to 50 key-value pairs (500 char per value). Use for internal IDs (orderId, userId, bookingId) that link Stripe objects to your database
  • Payment methods: Cards, bank transfers, wallets (Apple Pay, Google Pay), SEPA, Boleto, OXXO. Each has different confirmation and settlement flows
// Create a Payment Intent (server-side)
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

const paymentIntent = await stripe.paymentIntents.create({
  amount: 2500,                    // $25.00 in cents
  currency: 'usd',
  customer: customerId,
  payment_method_types: ['card'],
  capture_method: 'automatic',     // or 'manual' for auth-only
  metadata: {
    bookingId: '789',
    userId: '42',
    gymId: 'gym_santiago_01'
  },
  receipt_email: 'user@example.com',
  statement_descriptor: 'ACME FITNESS',      // Max 22 chars, shown on card statement
  statement_descriptor_suffix: 'CROSSFIT'    // Max 22 chars, appended
}, {
  idempotencyKey: `booking_789_${Date.now()}`  // Prevent duplicate charges
});

Stripe Checkout

Checkout is a Stripe-hosted payment page. It handles the entire payment UI, 3D Secure authentication, and local payment methods. Fewer integration bugs, higher conversion rates, and automatic support for new payment methods.

  • Session-based: Create a Checkout Session server-side, redirect customer to Stripe-hosted page. Return to your success/cancel URLs
  • Modes: payment (one-time), subscription (recurring), setup (save card for later). Each mode has different session configuration
  • Embedded mode: Mount Checkout inside your page as an iframe. Same security as hosted, but matches your site design
  • Price table: No-code pricing display that creates Checkout Sessions automatically. Good for simple SaaS pricing pages
  • Custom fields: Add custom form fields (text, dropdown, numeric) to collect additional information during checkout

2. Subscriptions and Billing

Stripe Billing manages recurring payments with automatic invoicing, proration, trials, and dunning (failed payment recovery). It handles the complexity of subscription lifecycle that most teams underestimate.

  • Products and Prices: Products are what you sell (e.g., "Monthly Plan"). Prices define how much (e.g., $29/month, $290/year). One product can have multiple prices for different intervals and currencies
  • Subscription statuses: active, past_due (payment failed, retrying), canceled, unpaid, trialing, incomplete (initial payment pending). Handle each status in your app
  • Trials: Free trials with trial_period_days or trial_end timestamp. Collect payment method upfront or at trial end. Use trial_settings to decide behavior when trial ends
  • Proration: Automatic credit/charge when upgrading/downgrading mid-cycle. proration_behavior: 'create_prorations' (default) creates invoice line items for the difference
  • Dunning: Smart Retries automatically retry failed payments at optimal times. Configure retry schedule (up to 4 retries over 3-4 weeks). Send email notifications to customers
  • Metered billing: Report usage during billing period. Invoice at end of period based on actual usage. Use for API calls, storage, messages, etc.
// Create a subscription with trial
const subscription = await stripe.subscriptions.create({
  customer: customerId,
  items: [{ price: 'price_monthly_29' }],
  trial_period_days: 14,
  payment_settings: {
    payment_method_types: ['card'],
    save_default_payment_method: 'on_subscription'
  },
  metadata: { gymId: 'gym_santiago_01', planType: 'premium' },
  expand: ['latest_invoice.payment_intent']
});

// Upgrade subscription (with proration)
await stripe.subscriptions.update(subscriptionId, {
  items: [{
    id: subscription.items.data[0].id,
    price: 'price_annual_290'
  }],
  proration_behavior: 'create_prorations'
});

3. Webhooks and Event Handling

Webhooks are Stripe's way of notifying your server about events (payment succeeded, subscription canceled, dispute created). They are the source of truth for payment state—never rely solely on client-side callbacks.

  • Signature verification: Every webhook has a Stripe-Signature header. Always verify signatures to prevent spoofed events. Use the raw request body (not parsed JSON)
  • Critical events: payment_intent.succeeded, payment_intent.payment_failed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed, charge.dispute.created
  • Idempotency: Stripe may send the same event multiple times. Store processed event IDs and skip duplicates. Your webhook handler must be idempotent
  • Respond quickly: Return 200 within 20 seconds. Do heavy processing asynchronously (queue the event, process in a worker). Stripe retries on 4xx/5xx for up to 3 days
  • Event ordering: Events may arrive out of order. Always fetch the current state from Stripe API instead of relying on the event data alone
  • Webhook endpoints: Create separate endpoints for different event types. Use webhook endpoint secret (not your API key) for signature verification
// Express webhook handler with signature verification
import express from 'express';
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

app.post('/webhooks/stripe',
  express.raw({ type: 'application/json' }),  // MUST use raw body
  async (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;

    try {
      event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
    } catch (err) {
      console.error('Webhook signature verification failed:', err.message);
      return res.status(400).send(`Webhook Error: ${err.message}`);
    }

    // Check for duplicate processing
    const processed = await redis.get(`stripe:event:${event.id}`);
    if (processed) return res.json({ received: true });

    // Queue for async processing (respond quickly)
    await webhookQueue.add(event.type, {
      eventId: event.id,
      type: event.type,
      data: event.data.object
    });

    // Mark as processed
    await redis.set(`stripe:event:${event.id}`, '1', 'EX', 604800);  // 7 days

    res.json({ received: true });
  }
);

// Worker processes webhook events
const worker = new Worker('stripe-webhooks', async (job) => {
  const { eventId, type, data } = job.data;

  switch (type) {
    case 'payment_intent.succeeded':
      await confirmBooking(data.metadata.bookingId);
      break;
    case 'payment_intent.payment_failed':
      await handleFailedPayment(data.metadata.bookingId, data.last_payment_error);
      break;
    case 'customer.subscription.deleted':
      await deactivateSubscription(data.metadata.gymId, data.customer);
      break;
    case 'charge.dispute.created':
      await handleDispute(data);
      await notifyTeam('dispute', data);
      break;
  }
});
Never trust the client. A payment is only confirmed when your webhook handler processes payment_intent.succeeded. The client-side redirect to your success URL is not proof of payment—the user could forge the redirect.

4. Connect: Multi-Party Payments

Stripe Connect enables marketplace and platform payments where money flows between multiple parties. Your platform charges customers and distributes funds to connected accounts (sellers, service providers, gyms).

  • Account types: Standard (Stripe-hosted onboarding, full Stripe dashboard), Express (Stripe-hosted onboarding, limited dashboard), Custom (you build everything). Express is recommended for most platforms
  • Charge types: Direct charges (customer pays connected account directly), Destination charges (platform charges, transfers to connected), Separate charges and transfers (most flexible)
  • Application fees: Your platform's revenue. Set application_fee_amount on charges. The fee is automatically deducted and held in your platform account
  • Onboarding: Create Account Links for connected accounts to complete identity verification. Handle account.updated webhooks to track verification status
  • Requirements: Connected accounts must complete KYC (Know Your Customer). Stripe handles ID verification, address verification, and bank account verification
// Destination charge: customer pays platform, funds go to connected account
const paymentIntent = await stripe.paymentIntents.create({
  amount: 5000,                         // $50.00
  currency: 'usd',
  customer: customerId,
  payment_method_types: ['card'],
  application_fee_amount: 750,          // Platform keeps $7.50 (15%)
  transfer_data: {
    destination: 'acct_connected_gym_01' // Connected account receives $42.50
  },
  metadata: { bookingId: '789', gymId: 'gym_santiago_01' }
});

// Create connected account (Express)
const account = await stripe.accounts.create({
  type: 'express',
  country: 'CL',                        // Chile
  email: 'gym@example.cl',
  capabilities: {
    card_payments: { requested: true },
    transfers: { requested: true }
  },
  business_type: 'company',
  metadata: { gymId: 'gym_santiago_01' }
});

// Generate onboarding link
const accountLink = await stripe.accountLinks.create({
  account: account.id,
  refresh_url: 'https://app.example.com/connect/retry',
  return_url: 'https://app.example.com/connect/complete',
  type: 'account_onboarding'
});

5. Payouts and Transfers

  • Automatic payouts: Stripe automatically pays out your balance on a schedule (daily, weekly, monthly). Default: 2-day rolling for most countries. Configure per connected account
  • Manual payouts: Disable automatic payouts and trigger manually via API. Use when you need to control exactly when connected accounts get paid
  • Transfers: Move funds from platform to connected accounts. Can be linked to a specific charge (for accurate reporting) or standalone
  • Reversals: Reverse a transfer back from a connected account. Use for refunds, disputes, or corrections. Limited by connected account's available balance
  • Payout speed: Standard (2-7 business days depending on country), Instant (available in US, UK, EU—additional fee). Chile: typically T+7 for standard payouts
  • Balance transactions: Track every movement in your Stripe balance. Charges, refunds, fees, transfers, payouts. Use for reconciliation with your accounting system
// Manual transfer to connected account
const transfer = await stripe.transfers.create({
  amount: 4250,                          // $42.50
  currency: 'usd',
  destination: 'acct_connected_gym_01',
  source_transaction: chargeId,          // Link to original charge
  metadata: { bookingId: '789', period: '2026-03' }
});

// Trigger manual payout for connected account
const payout = await stripe.payouts.create({
  amount: 100000,                        // $1000.00
  currency: 'usd'
}, {
  stripeAccount: 'acct_connected_gym_01'
});

6. Multi-Currency and Localization

Operating across multiple countries requires handling different currencies, tax regulations, and payment methods. Stripe provides tools for multi-currency support, but the application layer must be carefully designed.

  • Presentment currency: Charge customers in their local currency. Chilean customers pay in CLP, Mexican in MXN. Reduces cart abandonment and eliminates foreign transaction fees for customers
  • Settlement currency: Stripe converts and pays you in your platform's settlement currency. Exchange rate applies at time of charge. Track with balance_transaction.exchange_rate
  • Zero-decimal currencies: JPY, KRW, CLP use integer amounts directly (no cents). $10,000 CLP = amount: 10000. Other currencies use smallest unit (USD $25.00 = amount: 2500)
  • Stripe Tax: Automatic tax calculation for 40+ countries. Handles VAT, GST, sales tax. Register tax IDs for each country. Creates proper tax invoices
  • Local payment methods: Enable Boleto (Brazil), OXXO (Mexico), bank transfers, etc. via PaymentIntent or Checkout. Increases conversion in Latin America significantly
  • Invoicing: Multi-language invoices with proper currency formatting. Stripe generates PDF invoices with correct tax line items. Configurable per customer locale
  • Chile SII compliance: Chile's Servicio de Impuestos Internos requires electronic invoicing (DTE). Stripe Tax calculates IVA (19%), but you need a certified DTE provider (e.g., Bsale, Nubox) to issue boletas and facturas electrónicas that comply with SII regulations. Map Stripe invoices to DTE documents
  • Mexico SAT compliance: Mexico's SAT requires CFDI (Comprobante Fiscal Digital por Internet) for every transaction. Use a PAC (Proveedor Autorizado de Certificación) to stamp invoices. Stripe Tax handles IVA (16%), but CFDI generation must be done separately. Include RFC (tax ID) on all invoices
// Multi-currency charge with tax
const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  customer: customerId,
  line_items: [{
    price_data: {
      currency: 'clp',                    // Chilean Peso (zero-decimal)
      product_data: { name: 'CrossFit Class Pack - 10 sessions' },
      unit_amount: 45000                   // CLP $45,000
    },
    quantity: 1
  }],
  automatic_tax: { enabled: true },        // Stripe Tax handles IVA (19% in Chile)
  payment_method_types: ['card'],
  success_url: 'https://app.example.com/success?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://app.example.com/cancel',
  metadata: { country: 'CL', gymId: 'gym_santiago_01' }
});
When operating in Latin America, always offer local currency pricing. A $50 USD charge to a Chilean customer converts to ~CLP 47,000 with a foreign transaction fee. Charging CLP 45,000 directly is cheaper for the customer and your conversion rate improves.

7. PCI Compliance

PCI DSS (Payment Card Industry Data Security Standard) compliance is mandatory for any business handling card payments. Stripe minimizes your compliance burden by handling card data on their servers.

  • SAQ A: Simplest PCI compliance level. Achieved when using Stripe Checkout, Stripe Elements, or Payment Links. Card data never touches your servers. Most Stripe integrations qualify
  • Stripe Elements: Pre-built UI components (card input, IBAN, etc.) that collect sensitive data directly to Stripe. Your server receives a PaymentMethod token, never the card number
  • Never log card data: Do not log full card numbers, CVV, or expiration dates. Stripe provides last4, brand, and exp_month/exp_year for display purposes
  • HTTPS everywhere: All pages that include Stripe.js must be served over HTTPS. Use HSTS headers. No mixed content
  • Tokenization: Card data is replaced with a token (PaymentMethod or SetupIntent) that can only be used with your Stripe account. Tokens are useless if intercepted
  • API key security: Never expose your secret key (sk_*) client-side. Only the publishable key (pk_*) goes in the browser. Rotate keys periodically. Use restricted keys for specific permissions
Never, under any circumstances, send raw card numbers through your server. Always use Stripe Elements or Checkout to collect card data. Handling raw card data requires SAQ D compliance, which involves hundreds of security controls and annual on-site audits.

8. Testing with Test Clocks

Stripe provides a comprehensive test mode with test card numbers, test clocks for time-based flows, and webhook testing. Every feature works in test mode without real money.

  • Test cards: 4242 4242 4242 4242 (succeeds), 4000 0000 0000 0002 (declines), 4000 0025 0000 3155 (requires 3DS). Full list in Stripe docs
  • Test clocks: Simulate time passing for subscription testing. Create a test clock, attach customers to it, advance time to trigger billing cycles, trials ending, dunning flows
  • Webhook testing: Use Stripe CLI (stripe listen --forward-to localhost:3000/webhooks/stripe) to forward test events locally. Or trigger specific events with stripe trigger payment_intent.succeeded
  • Test mode keys: All test mode resources are separate from live. Test mode charges never process real payments. Switch between modes by using pk_test_*/sk_test_* vs pk_live_*/sk_live_*
  • Integration tests: Hit Stripe's test API in your CI/CD pipeline. Test the full flow: create customer, add payment method, create charge, verify webhook, check database state
  • Error simulation: Trigger specific error codes with special token values. Test how your app handles declines, network errors, rate limits, and authentication failures
// Test clock for subscription lifecycle testing
const testClock = await stripe.testHelpers.testClocks.create({
  frozen_time: Math.floor(Date.now() / 1000),
  name: 'Subscription lifecycle test'
});

// Create customer attached to test clock
const customer = await stripe.customers.create({
  email: 'test@example.com',
  test_clock: testClock.id
});

// Create subscription with 14-day trial
const subscription = await stripe.subscriptions.create({
  customer: customer.id,
  items: [{ price: 'price_monthly_29' }],
  trial_period_days: 14
});

// Advance time to end of trial (triggers first payment)
await stripe.testHelpers.testClocks.advance(testClock.id, {
  frozen_time: Math.floor(Date.now() / 1000) + (14 * 86400)
});

// Advance another month (triggers renewal)
await stripe.testHelpers.testClocks.advance(testClock.id, {
  frozen_time: Math.floor(Date.now() / 1000) + (44 * 86400)
});

9. Stripe Radar: Fraud Prevention

Stripe Radar uses machine learning trained on data from millions of businesses worldwide to detect and block fraudulent payments. It scores every transaction with a risk level and applies configurable rules.

  • Risk scoring: Every payment gets a risk score (0–99) and a risk level (normal, elevated, highest). Radar blocks payments with highest risk by default. You can customize thresholds per business need
  • Radar rules: Create custom rules using Stripe's rule language. Block or review payments based on metadata, amount, country, card type, velocity, and more. Example: :risk_score: > 65 AND :amount_in_usd: > 500
  • 3D Secure dynamic: Radar can request 3DS authentication only when risk is elevated, reducing friction for low-risk payments while protecting against fraud. Use request_three_d_secure: 'automatic'
  • Allow and block lists: Maintain lists of trusted or blocked emails, card fingerprints, IP addresses, and countries. Override machine learning decisions for known customers or known bad actors
  • Radar for Fraud Teams: Premium tier with manual review queues, custom rules with regex, and advanced analytics. Adds human review for edge cases that automation cannot resolve confidently
  • Early fraud warning: Receive radar.early_fraud_warning.created webhooks when card networks report suspicious activity. Proactively refund before a formal dispute is filed to avoid chargeback fees
// PaymentIntent with Radar risk evaluation
const paymentIntent = await stripe.paymentIntents.create({
  amount: 15000,
  currency: 'usd',
  customer: customerId,
  payment_method_types: ['card'],
  payment_method_options: {
    card: {
      request_three_d_secure: 'automatic'  // Radar decides when to trigger 3DS
    }
  },
  metadata: { orderId: '456', riskContext: 'new_customer' }
});

// After charge, inspect Radar outcome
const charge = await stripe.charges.retrieve(chargeId);
console.log(charge.outcome.risk_level);   // 'normal', 'elevated', 'highest'
console.log(charge.outcome.risk_score);   // 0-99
console.log(charge.outcome.type);         // 'authorized', 'blocked', 'manual_review'

10. Customer Portal

The Stripe Customer Portal is a Stripe-hosted page where customers can manage their subscriptions, payment methods, and billing details without you building any UI. Reduces support tickets and development time significantly.

  • Self-service: Customers can update payment methods, view invoice history, download PDF invoices, and manage subscriptions (upgrade, downgrade, cancel) from a single page
  • Configuration: Control what customers can do via the Portal configuration in your Stripe Dashboard. Allow or restrict cancellation, plan switching, payment method updates. Set cancellation policies (immediate vs end of period)
  • Session-based access: Create a portal session server-side with the customer ID. Redirect the customer to the session URL. Sessions expire after use, ensuring security
  • Branding: Customize colors, logo, and business info in the portal settings. The portal matches your brand while being fully hosted by Stripe
  • Webhooks: Portal actions trigger standard webhooks (customer.subscription.updated, payment_method.attached). Your existing webhook handlers process portal changes automatically
// Create a Customer Portal session
const portalSession = await stripe.billingPortal.sessions.create({
  customer: customerId,
  return_url: 'https://app.example.com/account',
});

// Redirect customer to: portalSession.url

// Configure portal (done once, or via Dashboard)
const config = await stripe.billingPortal.configurations.create({
  business_profile: {
    headline: 'Manage your subscription'
  },
  features: {
    subscription_cancel: { enabled: true, mode: 'at_period_end' },
    subscription_update: {
      enabled: true,
      default_allowed_updates: ['price', 'quantity'],
      proration_behavior: 'create_prorations',
      products: [{ product: 'prod_gym_membership', prices: ['price_monthly', 'price_annual'] }]
    },
    payment_method_update: { enabled: true },
    invoice_history: { enabled: true }
  }
});

11. Payment Methods

Stripe supports dozens of payment methods globally. Each has different authorization flows, settlement timelines, and geographic availability. Offering the right methods per region dramatically improves conversion rates.

Cards (Visa, Mastercard, Amex)

  • Global coverage, instant confirmation
  • 3D Secure 2 for SCA compliance (EU)
  • Supports authorization holds and manual capture
  • Card brand detection and BIN-level metadata

SEPA Direct Debit

  • EUR bank-to-bank payments across 36 SEPA countries
  • Requires mandate acceptance (digital or paper)
  • Settlement in 5–14 business days; dispute window of 8 weeks (13 months for unauthorized)
  • Lower fees than cards; ideal for recurring EUR payments

iDEAL (Netherlands)

  • Dutch bank redirect payment; covers ~60% of Dutch e-commerce
  • Instant confirmation via bank authentication
  • Converts to SEPA Direct Debit for recurring payments
  • No chargebacks; funds guaranteed once confirmed

Boleto (Brazil)

  • Cash voucher payment at banks, ATMs, or convenience stores
  • Expires after a configurable number of days (default 3)
  • Payment confirmation delayed 1–2 business days after cash payment
  • Essential for reaching unbanked customers in Brazil
// PaymentIntent with multiple payment methods
const paymentIntent = await stripe.paymentIntents.create({
  amount: 3000,
  currency: 'eur',
  customer: customerId,
  payment_method_types: ['card', 'sepa_debit', 'ideal'],
  metadata: { orderId: '123' }
});

// SEPA mandate for recurring payments
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2900,
  currency: 'eur',
  customer: customerId,
  payment_method_types: ['sepa_debit'],
  payment_method_options: {
    sepa_debit: { mandate_options: { } }
  },
  mandate_data: {
    customer_acceptance: {
      type: 'online',
      online: {
        ip_address: req.ip,
        user_agent: req.headers['user-agent']
      }
    }
  }
});

12. Disputes and Chargebacks

Disputes (chargebacks) occur when a cardholder contests a charge with their bank. Each dispute costs a non-refundable fee ($15 USD) regardless of outcome. Prevention is far cheaper than fighting disputes.

  • Dispute lifecycle: charge.dispute.created (funds withdrawn) → you submit evidence → bank reviews (60–90 days) → charge.dispute.closed (won or lost). Respond within the evidence deadline or the dispute is automatically lost
  • Evidence submission: Provide compelling evidence via the API or Dashboard: delivery confirmation, signed contracts, customer communication logs, IP address logs, usage data. Tailor evidence to the dispute reason code (fraudulent, product not received, duplicate, etc.)
  • Prevention with Radar: Block high-risk payments before they become disputes. Enable 3DS for elevated risk to shift liability to the card issuer. Use Radar early fraud warnings to proactively refund suspicious charges
  • Clear descriptors: Set recognizable statement_descriptor values. Unrecognized charges are the leading cause of "friendly fraud" disputes. Include business name and service type
  • Refund policies: Make cancellation and refund policies clearly visible. Proactive refunds before disputes save the $15 fee and protect your dispute rate. Keep your dispute rate below 0.75% to avoid monitoring programs
  • Dispute rate monitoring: Card networks (Visa, Mastercard) place businesses in monitoring programs if dispute rates exceed thresholds. Visa: 0.9% triggers VDMP. Mastercard: 1.0% triggers ECP. Excessive disputes can lead to account termination
// Submit dispute evidence via API
await stripe.disputes.update(disputeId, {
  evidence: {
    customer_name: 'Maria Garcia',
    customer_email_address: 'maria@example.cl',
    product_description: 'CrossFit monthly membership - January 2026',
    service_date: '2026-01-01',
    access_activity_log: 'Customer checked in 12 times in January 2026: Jan 3, 5, 7, 10...',
    customer_signature: 'file_upload_id_contract',       // Upload via File API
    receipt: 'file_upload_id_receipt',
    uncategorized_text: 'Customer signed 12-month contract on 2025-12-15. ' +
      'Cancellation policy requires 30-day notice. No cancellation was requested.'
  },
  submit: true  // Submit immediately (cannot be modified after)
});

// Handle dispute webhook
case 'charge.dispute.created':
  const dispute = data;
  await notifyTeam('dispute_alert', {
    amount: dispute.amount,
    reason: dispute.reason,        // 'fraudulent', 'product_not_received', etc.
    chargeId: dispute.charge,
    deadline: dispute.evidence_details.due_by
  });
  // Auto-gather evidence from your database
  await prepareDisputeEvidence(dispute);
  break;
Never ignore disputes. An unanswered dispute is an automatic loss. Set up alerts for charge.dispute.created webhooks and maintain templates for common dispute types. In production, we reduced our dispute rate to under 0.3% through proactive Radar rules and clear statement descriptors.

13. Real-World Experience

In production, I designed and implemented the complete payment infrastructure using Stripe, supporting gyms across Chile and Mexico with multi-currency billing, subscriptions, and marketplace-style payments.

  • Stripe + MercadoPago: Dual payment provider architecture. Stripe for card payments and subscriptions, MercadoPago for local payment methods in Latin America (bank transfers, cash payments at OXXO/Servipag). Unified internal API abstracted the provider
  • Multi-country tax: Handled VAT/IVA calculation for Chile (19%) and Mexico (16%). Used Stripe Tax for automatic calculation on Stripe payments and custom tax logic for MercadoPago. Integrated with Chile SII for DTE (boletas/facturas electrónicas) and Mexico SAT for CFDI stamping via PAC. Tax-compliant invoicing in both countries
  • Subscription management: Gym membership subscriptions with monthly and annual billing. Handled upgrades/downgrades with proration, trial periods for new members, and automated dunning for failed payments
  • Webhook reliability: All Stripe webhooks queued through BullMQ for reliable processing. Idempotency keys stored in Redis to prevent duplicate processing. Separate webhook endpoints for payments, subscriptions, and disputes
  • Reconciliation: Automated daily reconciliation between Stripe balance transactions, MercadoPago movements, and internal database records. Detected and resolved discrepancies automatically with Slack alerts for manual review cases
Book free 1-hour consult All Guides Home

14. Latest Features (2025-2026)

Stripe Agent Toolkit

Official Python and TypeScript SDKs that enable AI agents to interact with Stripe via natural language. Integrates with OpenAI, LangChain, CrewAI, and Vercel AI SDK. Agents can create products, set prices, generate payment links, and manage subscriptions through plain English instructions. Ideal for building AI-powered commerce workflows where the agent handles the entire payment setup.

Stablecoin Financial Accounts

Stripe now supports holding stablecoin balances in financial accounts. Businesses can receive funds via both crypto and fiat rails, with automatic conversion between stablecoins and traditional currencies. Available in 100+ countries. Enables new use cases for cross-border payments and treasury management with reduced FX volatility.

Adaptive Pricing

Automatically localize prices across 150+ markets based on purchasing power parity, local market conditions, and currency. Works with Stripe Elements, Checkout, and Hosted Invoice Page. No additional fees beyond standard Stripe pricing. Replaces the manual work of maintaining multi-currency price tables per region.

Stripe Orchestration

Manage multiple payment processors from within Stripe's dashboard and API. Route transactions to different processors based on rules (geography, amount, card type) while maintaining a single integration point. Useful for enterprises that need processor redundancy or have legacy processor contracts alongside Stripe.

Entitlements API

Define and control feature access based on customer pricing plans. Map product features to subscription tiers and query entitlements at runtime to gate access. Replaces custom feature-flag logic tied to subscription status. The API returns which features a customer has access to based on their active subscriptions and one-time purchases.

V2 API and Meter Events

The V2 API introduces high-throughput meter events supporting up to 10,000 events per second for usage-based billing. Report granular usage data (API calls, compute minutes, storage bytes) in real time. Events are aggregated into billing periods automatically. Designed for SaaS platforms with high-volume metered pricing models.

Agentic Commerce Suite and MCP

Stripe launched the Agentic Commerce Suite, a complete solution for selling on AI agents. It makes products discoverable to agents, simplifies checkout, and accepts agentic payments via a single integration. The Stripe Agent Toolkit (v0.9.0) now includes an MCP (Model Context Protocol) server, enabling AI agents to interact with the Stripe API and search its knowledge base. The toolkit supports OpenAI Agents SDK, Vercel AI SDK, LangChain, and CrewAI in both Python and TypeScript.

Shared Payment Tokens and x402

As of March 2026, Stripe expanded Shared Payment Tokens (SPTs) to support Mastercard Agent Pay and Visa Intelligent Commerce for network-led agentic payments, plus buy-now-pay-later options. Separately, Stripe launched x402 payments on Base, enabling AI agents to make instant USDC micropayments for APIs, data, and digital services. This opens the door for developers to charge agents for services using stablecoin-based machine-to-machine payments.

Machine Payments Protocol (MPP) Card

Stripe and Tempo launched the Machine Payments Protocol (MPP) card, an open standard for agent-to-service payments. The MPP card gives AI agents a dedicated payment identity — agents can autonomously purchase APIs, compute resources, and digital services using the standard PaymentIntents API. Unlike x402 (stablecoin-based), MPP operates on existing card networks, making it compatible with any Stripe-integrated merchant. Organizations set spending limits, approval rules, and audit trails per agent, maintaining human oversight over autonomous spending.

More Guides