# Stripe Node.js Library The Stripe Node.js library provides convenient access to the Stripe API from server-side JavaScript applications. It enables developers to integrate payment processing, subscription management, checkout sessions, invoicing, and financial operations into their Node.js, Deno, and serverless applications. The library supports TypeScript out of the box, with types reflecting the latest API version, and works across multiple JavaScript runtimes including Node.js 18+, Deno, Bun, and Cloudflare Workers. This SDK wraps the Stripe REST API with a fluent, promise-based interface that handles authentication, request signing, automatic retries, pagination, and webhook signature verification. It covers the complete Stripe product suite including Payments, Billing, Connect, Terminal, Identity verification, Issuing, Treasury, and more. The library automatically manages idempotency keys for safe retries and provides both synchronous and asynchronous patterns for webhook event construction. ## Client Initialization Configure the Stripe client with your secret API key and optional settings for timeout, retries, proxy agents, and telemetry. ```typescript import Stripe from 'stripe'; // Basic initialization const stripe = new Stripe('sk_test_...'); // With configuration options const stripeClient = new Stripe('sk_test_...', { apiVersion: '2026-03-25.dahlia', // Optional: pin API version maxNetworkRetries: 2, // Default: 2, set 0 to disable timeout: 80000, // Request timeout in ms (default: 80000) telemetry: true, // Enable latency telemetry (default: true) appInfo: { // Identify your plugin name: 'MyAwesomePlugin', version: '1.2.34', url: 'https://myawesomeplugin.info', }, }); // For Stripe Connect - set account on all requests const connectClient = new Stripe('sk_test_...', { stripeAccount: 'acct_connected_account_id', }); ``` ## Create Customer Create a new customer with email, name, payment source, and metadata for tracking. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); const customer = await stripe.customers.create({ email: 'customer@example.com', name: 'Jenny Rosen', description: 'Premium subscriber', metadata: { user_id: '12345', plan: 'premium', }, address: { line1: '123 Main St', city: 'San Francisco', state: 'CA', postal_code: '94111', country: 'US', }, }); console.log('Customer created:', customer.id); // Output: Customer created: cus_NffrFeUfNV2Hib ``` ## List and Search Customers Retrieve customers with pagination and search for customers using query syntax. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // List customers with pagination const customers = await stripe.customers.list({ limit: 10, created: { gte: Math.floor(Date.now() / 1000) - 86400 * 30 }, // Last 30 days }); for (const customer of customers.data) { console.log(customer.id, customer.email); } // Search customers by email or metadata const searchResults = await stripe.customers.search({ query: "email:'customer@example.com' OR metadata['user_id']:'12345'", limit: 10, }); console.log('Found customers:', searchResults.data.length); ``` ## Create Payment Intent Create a PaymentIntent to collect payment, with support for various payment methods and capture modes. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); const paymentIntent = await stripe.paymentIntents.create({ amount: 2000, // Amount in cents ($20.00) currency: 'usd', customer: 'cus_NffrFeUfNV2Hib', payment_method_types: ['card'], description: 'Order #12345', metadata: { order_id: '12345', }, // For manual capture (authorize now, capture later) capture_method: 'manual', // Automatically confirm with payment method // payment_method: 'pm_card_visa', // confirm: true, }); console.log('PaymentIntent created:', paymentIntent.id); console.log('Client secret:', paymentIntent.client_secret); // Output: PaymentIntent created: pi_3MtwBw... // Output: Client secret: pi_3MtwBw..._secret_... ``` ## Confirm and Capture Payment Intent Confirm a payment intent with a payment method and capture authorized funds. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Confirm the payment intent with a payment method const confirmedIntent = await stripe.paymentIntents.confirm( 'pi_3MtwBwLkdIwHu7ix28a3tqPa', { payment_method: 'pm_card_visa', return_url: 'https://yoursite.com/payment/complete', } ); console.log('Payment status:', confirmedIntent.status); // Output: Payment status: requires_capture (if capture_method was 'manual') // Output: Payment status: succeeded (if capture_method was 'automatic') // Capture a previously authorized payment const capturedIntent = await stripe.paymentIntents.capture( 'pi_3MtwBwLkdIwHu7ix28a3tqPa', { amount_to_capture: 1500, // Capture $15.00 of the $20.00 authorized } ); console.log('Captured amount:', capturedIntent.amount_received); ``` ## Create Checkout Session Create a Stripe-hosted checkout page for one-time payments or subscriptions. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // One-time payment checkout const session = await stripe.checkout.sessions.create({ mode: 'payment', success_url: 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://yoursite.com/cancel', line_items: [ { price_data: { currency: 'usd', product_data: { name: 'T-shirt', description: 'Comfortable cotton t-shirt', images: ['https://example.com/t-shirt.png'], }, unit_amount: 2000, }, quantity: 1, }, ], customer_email: 'customer@example.com', metadata: { order_id: '12345', }, }); console.log('Checkout URL:', session.url); // Output: Checkout URL: https://checkout.stripe.com/c/pay/cs_test_... // Subscription checkout const subscriptionSession = await stripe.checkout.sessions.create({ mode: 'subscription', success_url: 'https://yoursite.com/success', cancel_url: 'https://yoursite.com/cancel', line_items: [ { price: 'price_1MoBy5LkdIwHu7ixZhnattbh', // Recurring price ID quantity: 1, }, ], }); ``` ## Create Product and Price Create products and prices for use in subscriptions, checkout, and payment links. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Create a product const product = await stripe.products.create({ name: 'Pro Plan', description: 'Full access to all features', metadata: { tier: 'pro', }, }); // Create a recurring price const monthlyPrice = await stripe.prices.create({ product: product.id, unit_amount: 1999, // $19.99 currency: 'usd', recurring: { interval: 'month', }, metadata: { billing_period: 'monthly', }, }); // Create a one-time price const setupPrice = await stripe.prices.create({ product: product.id, unit_amount: 4999, // $49.99 one-time setup fee currency: 'usd', }); console.log('Product:', product.id); console.log('Monthly price:', monthlyPrice.id); // Output: Product: prod_NWjs8kKbJWmuuc // Output: Monthly price: price_1MoBy5LkdIwHu7ixZhnattbh ``` ## Create Subscription Create and manage recurring subscriptions with trials, coupons, and multiple items. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Create a subscription const subscription = await stripe.subscriptions.create({ customer: 'cus_NffrFeUfNV2Hib', items: [ { price: 'price_1MoBy5LkdIwHu7ixZhnattbh' }, ], trial_period_days: 14, payment_behavior: 'default_incomplete', // Requires payment method payment_settings: { save_default_payment_method: 'on_subscription', }, expand: ['latest_invoice.payment_intent'], metadata: { plan_name: 'pro', }, }); console.log('Subscription:', subscription.id); console.log('Status:', subscription.status); // Output: Subscription: sub_1MowQVLkdIwHu7ixeRlqHVzs // Output: Status: trialing // Update subscription (change plan) const updatedSubscription = await stripe.subscriptions.update( 'sub_1MowQVLkdIwHu7ixeRlqHVzs', { items: [ { id: subscription.items.data[0].id, price: 'price_new_plan_id', }, ], proration_behavior: 'create_prorations', } ); // Cancel subscription at period end await stripe.subscriptions.update('sub_1MowQVLkdIwHu7ixeRlqHVzs', { cancel_at_period_end: true, }); ``` ## Create and Manage Invoices Create invoices, add line items, and send to customers. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Create an invoice item (adds to upcoming invoice) await stripe.invoiceItems.create({ customer: 'cus_NffrFeUfNV2Hib', amount: 2500, currency: 'usd', description: 'One-time consulting fee', }); // Create and finalize an invoice const invoice = await stripe.invoices.create({ customer: 'cus_NffrFeUfNV2Hib', collection_method: 'send_invoice', days_until_due: 30, auto_advance: false, }); // Add line items await stripe.invoiceItems.create({ customer: 'cus_NffrFeUfNV2Hib', invoice: invoice.id, amount: 5000, currency: 'usd', description: 'Additional services', }); // Finalize and send the invoice const finalizedInvoice = await stripe.invoices.finalizeInvoice(invoice.id); const sentInvoice = await stripe.invoices.sendInvoice(invoice.id); console.log('Invoice:', sentInvoice.id); console.log('Hosted URL:', sentInvoice.hosted_invoice_url); // Output: Invoice: in_1MtHbE... // Output: Hosted URL: https://invoice.stripe.com/i/acct_.../test_... ``` ## Webhook Event Construction (Express) Verify webhook signatures and construct events from Stripe webhook payloads. ```typescript import Stripe from 'stripe'; import express from 'express'; const stripe = new Stripe('sk_test_...'); const webhookSecret = 'whsec_...'; const app = express(); app.post( '/webhook', express.raw({ type: 'application/json' }), (req, res) => { const sig = req.headers['stripe-signature']; let event: Stripe.Event; try { event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret); } catch (err) { console.log(`Webhook signature verification failed: ${err.message}`); return res.status(400).send(`Webhook Error: ${err.message}`); } // Handle the event switch (event.type) { case 'payment_intent.succeeded': const paymentIntent = event.data.object as Stripe.PaymentIntent; console.log(`Payment for ${paymentIntent.amount} succeeded`); break; case 'customer.subscription.created': const subscription = event.data.object as Stripe.Subscription; console.log(`Subscription ${subscription.id} created`); break; case 'invoice.paid': const invoice = event.data.object as Stripe.Invoice; console.log(`Invoice ${invoice.id} paid`); break; default: console.log(`Unhandled event type: ${event.type}`); } res.json({ received: true }); } ); app.listen(3000); ``` ## Async Webhook Construction Use the async version for environments that don't support synchronous crypto operations. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); const webhookSecret = 'whsec_...'; // For Cloudflare Workers, Deno, or other async environments async function handleWebhook(payload: string, signature: string) { try { const event = await stripe.webhooks.constructEventAsync( payload, signature, webhookSecret ); console.log('Event type:', event.type); console.log('Event data:', event.data.object); return { success: true }; } catch (err) { console.error('Webhook error:', err.message); return { success: false, error: err.message }; } } ``` ## Auto-Pagination Automatically iterate through large lists without manually handling pagination. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Using async iterators (for-await-of) for await (const customer of stripe.customers.list({ limit: 100 })) { console.log(customer.id, customer.email); // Break early if needed if (customer.email === 'target@example.com') { break; } } // Using autoPagingEach with callback await stripe.customers.list({ limit: 100 }).autoPagingEach(async (customer) => { await processCustomer(customer); // Return false to stop iteration if (shouldStop()) { return false; } }); // Using autoPagingToArray (with required limit) const allCustomers = await stripe.customers .list({ limit: 100 }) .autoPagingToArray({ limit: 500 }); // Max 10,000 console.log('Total customers fetched:', allCustomers.length); ``` ## Stripe Connect (Platform Operations) Make API calls on behalf of connected accounts. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Create a connected account const account = await stripe.accounts.create({ type: 'express', country: 'US', email: 'merchant@example.com', capabilities: { card_payments: { requested: true }, transfers: { requested: true }, }, }); // Create account link for onboarding const accountLink = await stripe.accountLinks.create({ account: account.id, refresh_url: 'https://yoursite.com/reauth', return_url: 'https://yoursite.com/return', type: 'account_onboarding', }); console.log('Onboarding URL:', accountLink.url); // Make API calls on behalf of connected account const paymentIntent = await stripe.paymentIntents.create( { amount: 1000, currency: 'usd', application_fee_amount: 100, // Platform takes $1.00 fee }, { stripeAccount: account.id, // Connected account ID } ); // Or set globally for all requests const connectedStripe = new Stripe('sk_test_...', { stripeAccount: 'acct_connected_account_id', }); ``` ## Create Refund Issue full or partial refunds for charges and payment intents. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Full refund of a payment intent const fullRefund = await stripe.refunds.create({ payment_intent: 'pi_3MtwBwLkdIwHu7ix28a3tqPa', reason: 'requested_by_customer', }); // Partial refund const partialRefund = await stripe.refunds.create({ payment_intent: 'pi_3MtwBwLkdIwHu7ix28a3tqPa', amount: 500, // Refund $5.00 }); // Refund with metadata const refund = await stripe.refunds.create({ charge: 'ch_3MtwBwLkdIwHu7ix28a3tqPa', metadata: { reason: 'Product returned', ticket_id: 'SUPPORT-12345', }, }); console.log('Refund ID:', refund.id); console.log('Refund status:', refund.status); // Output: Refund ID: re_3MtwBw... // Output: Refund status: succeeded ``` ## Error Handling Handle Stripe API errors with specific error types and retry logic. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); async function createPaymentWithErrorHandling(amount: number) { try { const paymentIntent = await stripe.paymentIntents.create({ amount, currency: 'usd', }); return paymentIntent; } catch (error) { if (error instanceof Stripe.errors.StripeCardError) { // Card was declined console.log('Card declined:', error.decline_code); console.log('Message:', error.message); } else if (error instanceof Stripe.errors.StripeRateLimitError) { // Too many requests - implement backoff console.log('Rate limited, retrying...'); await new Promise(resolve => setTimeout(resolve, 1000)); return createPaymentWithErrorHandling(amount); } else if (error instanceof Stripe.errors.StripeInvalidRequestError) { // Invalid parameters console.log('Invalid request:', error.param, error.message); } else if (error instanceof Stripe.errors.StripeAuthenticationError) { // Invalid API key console.log('Authentication failed'); } else if (error instanceof Stripe.errors.StripeConnectionError) { // Network error console.log('Network error, retrying...'); } else if (error instanceof Stripe.errors.StripeAPIError) { // Stripe server error console.log('Stripe API error:', error.message); } throw error; } } ``` ## Request Options and Idempotency Configure per-request options including timeouts, idempotency keys, and API versions. ```typescript import Stripe from 'stripe'; import { v4 as uuidv4 } from 'uuid'; const stripe = new Stripe('sk_test_...'); // Per-request timeout and retries const customer = await stripe.customers.create( { email: 'customer@example.com' }, { timeout: 5000, // 5 second timeout for this request maxNetworkRetries: 3, } ); // Idempotency key to prevent duplicate operations const idempotencyKey = uuidv4(); const paymentIntent = await stripe.paymentIntents.create( { amount: 2000, currency: 'usd', }, { idempotencyKey: idempotencyKey, } ); // Making the same request with the same key returns the original result const sameIntent = await stripe.paymentIntents.create( { amount: 2000, currency: 'usd', }, { idempotencyKey: idempotencyKey, // Returns cached result } ); console.log(paymentIntent.id === sameIntent.id); // true ``` ## Raw API Requests Send requests to undocumented or beta API endpoints. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Make raw API request to any endpoint const response = await stripe.rawRequest( 'POST', '/v1/payment_intents', { amount: 1000, currency: 'usd', }, { apiVersion: '2026-03-25.dahlia', } ); // Access beta endpoints const betaResponse = await stripe.rawRequest( 'GET', '/v1/some_beta_resource', {}, { apiVersion: '2026-03-25.dahlia; some_beta=v1', } ); ``` ## V2 Billing Meter Events Send high-throughput usage events for metered billing using the V2 API. ```typescript import Stripe from 'stripe'; const apiKey = 'sk_test_...'; const customerId = 'cus_...'; let meterEventSession: any = null; async function refreshMeterEventSession() { if (!meterEventSession || new Date(meterEventSession.expires_at) <= new Date()) { const client = new Stripe(apiKey); meterEventSession = await client.v2.billing.meterEventSession.create(); } } async function sendMeterEvent(eventName: string, value: string) { await refreshMeterEventSession(); // Use the session token for high-throughput events const client = new Stripe(meterEventSession.authentication_token); await client.v2.billing.meterEventStream.create({ events: [{ event_name: eventName, payload: { stripe_customer_id: customerId, value: value, }, }], }); } // Report usage await sendMeterEvent('api_calls', '100'); await sendMeterEvent('storage_gb', '5.5'); ``` ## Expanding Objects Expand nested objects in API responses to avoid additional API calls. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Expand customer on payment intent const paymentIntent = await stripe.paymentIntents.retrieve( 'pi_3MtwBwLkdIwHu7ix28a3tqPa', { expand: ['customer', 'payment_method'], } ); // Access expanded customer const customer = paymentIntent.customer as Stripe.Customer; console.log('Customer email:', customer.email); // Expand multiple levels const invoice = await stripe.invoices.retrieve('in_1MtHbE...', { expand: ['subscription', 'customer.default_source'], }); // Expand on list operations const charges = await stripe.charges.list({ limit: 10, expand: ['data.customer', 'data.balance_transaction'], }); ``` ## Test Webhook Headers Generate test webhook headers for unit testing webhook handlers. ```typescript import Stripe from 'stripe'; const stripe = new Stripe('sk_test_...'); // Create a test event payload const testPayload = JSON.stringify({ id: 'evt_test_webhook', object: 'event', type: 'payment_intent.succeeded', data: { object: { id: 'pi_test', object: 'payment_intent', amount: 2000, currency: 'usd', status: 'succeeded', }, }, }); // Generate a test signature header const testSecret = 'whsec_test_secret'; const header = stripe.webhooks.generateTestHeaderString({ payload: testPayload, secret: testSecret, }); // Use in tests const event = stripe.webhooks.constructEvent(testPayload, header, testSecret); console.log('Event type:', event.type); // Output: Event type: payment_intent.succeeded ``` The Stripe Node.js library serves as the foundation for building payment-enabled applications, from simple one-time charges to complex marketplace platforms with Stripe Connect. It is commonly used for e-commerce checkout flows, SaaS subscription billing, marketplace payment splitting, invoice generation, and usage-based billing with metered products. The SDK handles the complexity of PCI compliance by keeping sensitive card data on Stripe's servers while providing full control over the payment flow. Integration patterns typically involve combining the server-side SDK with Stripe.js on the frontend for secure card collection, webhooks for asynchronous event handling (payment completion, subscription changes, disputes), and Stripe Elements or Checkout for prebuilt UI components. For platforms, Connect enables splitting payments between the platform and connected merchants, while Treasury provides banking-as-a-service capabilities. The library's TypeScript support, automatic retries, and comprehensive error types make it production-ready for applications of any scale.