Payouts

Transfer funds from your Stripe balance to bank accounts with the Payouts API. Comprehensive guide to payout creation, scheduling, and multi-currency support.

What Are Stripe Payouts

Managing payouts effectively is essential for any business processing payments through Stripe. The platform provides a comprehensive payouts API that enables you to move funds from your Stripe balance to bank accounts, debit cards, or connected accounts. Whether you're building an e-commerce platform, a marketplace, or a SaaS application, understanding how to leverage Stripe's payout capabilities ensures smooth cash flow management for your business and your users.

A payout in Stripe represents the transfer of funds from your Stripe balance to a designated bank account or debit card. When customers make purchases through your integration, the funds accumulate in your Stripe balance. Payouts enable you to withdraw these funds according to your business needs, whether on a regular schedule or initiated manually.

Payout Versus Transfer

It's important to distinguish between payouts and transfers in the Stripe ecosystem. A payout moves funds from your Stripe balance to an external bank account, effectively withdrawing money from Stripe. A transfer moves funds between Stripe accounts, such as from your platform to a connected account.

The Stripe Payouts API

The Stripe Payouts API provides programmatic access to all payout operations. The API follows RESTful conventions, with predictable resource URLs and JSON-encoded request and response bodies. This consistency makes it straightforward to integrate payout functionality into your existing codebase.

Creating a Payout

To create a payout, you send a POST request to the payouts endpoint with the amount and currency parameters. The amount is specified in the smallest currency unit (cents for USD, for example), and the currency is a three-letter ISO code.

Creating a Payout
1import Stripe from 'stripe';2 3const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);4 5async function createPayout(amount: number, currency: string) {6 try {7 const payout = await stripe.payouts.create({8 amount: amount, // Amount in cents (e.g., $1000 = 100000)9 currency: currency, // Three-letter ISO currency code (e.g., 'usd')10 });11 12 console.log(`Payout created: ${payout.id}`);13 console.log(`Amount: ${payout.amount} ${payout.currency.toUpperCase()}`);14 console.log(`Status: ${payout.status}`);15 console.log(`Arrival Date: ${new Date(payout.arrival_date * 1000).toISOString()}`);16 17 return payout;18 } catch (error) {19 console.error('Failed to create payout:', error);20 throw error;21 }22}23 24// Example usage25createPayout(50000, 'usd'); // Payout $500 USD

Retrieving Payout Information

The API provides endpoints to retrieve individual payouts by their unique identifier or list all payouts with optional filtering. Retrieving a payout returns the complete object including status updates, failure reasons if applicable, and tracking metadata.

Retrieving Payout Details
1async function getPayoutDetails(payoutId: string) {2 try {3 const payout = await stripe.payouts.retrieve(payoutId);4 5 return {6 id: payout.id,7 amount: payout.amount,8 currency: payout.currency,9 status: payout.status,10 arrivalDate: new Date(payout.arrival_date * 1000).toISOString(),11 destination: payout.destination,12 failureMessage: payout.failure_message,13 metadata: payout.metadata,14 };15 } catch (error) {16 console.error('Failed to retrieve payout:', error);17 throw error;18 }19}20 21async function listPayouts(options?: {22 limit?: number,23 status?: string,24 created?: { gt?: number, lt?: number }25}) {26 try {27 const payouts = await stripe.payouts.list({28 limit: options?.limit || 10,29 status: options?.status,30 created: options?.created,31 });32 33 return payouts.data.map(payout => ({34 id: payout.id,35 amount: payout.amount,36 currency: payout.currency,37 status: payout.status,38 arrivalDate: new Date(payout.arrival_date * 1000).toISOString(),39 }));40 } catch (error) {41 console.error('Failed to list payouts:', error);42 throw error;43 }44}

Supported Currencies

Stripe supports payouts in numerous currencies, enabling businesses to operate globally. The platform handles currency conversion when payout currencies differ from the currencies in which funds were collected, applying competitive exchange rates with transparent pricing. This global reach is essential for businesses expanding internationally and needing multi-currency support.

Multi-Currency Settlement

For businesses operating internationally, Stripe's multi-currency settlement allows you to receive payouts in currencies different from your default settlement currency. This capability is particularly valuable for businesses that collect payments in one currency but need to pay expenses or suppliers in another. Implementing proper currency management helps streamline international operations.

When you configure multi-currency settlement, Stripe converts accumulated funds to your desired payout currency before initiating the transfer. The conversion uses rates available at the time of settlement, with conversion details included in your payout records for reconciliation purposes.

Multi-Currency Payout Example
1async function createMultiCurrencyPayout(2 amount: number,3 payoutCurrency: string,4 settlementCurrency: string5) {6 try {7 // Create payout in specified currency8 const payout = await stripe.payouts.create({9 amount: amount,10 currency: payoutCurrency,11 });12 13 // Note: Stripe handles conversion to settlement currency automatically14 console.log(`Payout ${payout.id} created in ${payoutCurrency.toUpperCase()}`);15 console.log(`This will be converted to ${settlementCurrency} for settlement`);16 17 return payout;18 } catch (error) {19 console.error('Failed to create multi-currency payout:', error);20 throw error;21 }22}

Payout Schedule and Timing

Understanding payout timing helps you manage cash flow expectations and communicate accurately with stakeholders. Stripe provides arrival date estimates for each payout, though actual arrival times may vary based on banking systems and holidays.

Standard Payout Timing

Standard payouts typically arrive within two to three business days, depending on the destination country's banking infrastructure. The arrival_date field in the payout object provides an estimate, which you can use for planning purposes.

Instant Payouts

For qualifying accounts and destinations, Stripe offers instant payouts that arrive within minutes rather than days. Instant payouts use debit card rails to accelerate fund delivery and are available for same-day or next-day arrival to most major banks.

Instant payouts incur additional fees compared to standard payouts, reflecting the premium speed of delivery.

Creating Manual Payouts
1async function createManualPayout(amount: number, currency: string) {2 const payout = await stripe.payouts.create({3 amount: amount,4 currency: currency,5 // Omitting transfer_group enables immediate payout6 // By default, Stripe will process this according to schedule7 });8 9 return payout;10}11 12// Configure automatic payouts through Stripe Dashboard13// Options include daily, weekly, or monthly schedules

Payout Status and Webhooks

Monitoring payout status in real-time ensures your systems reflect the current state of fund movements. Stripe provides webhooks for payout events, enabling automated responses to status changes. Implementing proper webhook automation can streamline your financial workflows.

Payout Statuses

A payout progresses through several status values during its lifecycle:

  • pending: Stripe has received the payout request and is preparing to send the funds
  • in_transit: The payout has left Stripe's systems and is being processed by the banking network
  • paid: Confirms successful delivery to the destination account
  • failed: Indicates an issue that prevented completion
  • canceled: Has been reversed before completion, returning funds to the Stripe balance

Webhook Events for Payouts

Stripe sends webhook events when payout statuses change. Key events include payout.created, payout.paid, payout.failed, and payout.canceled.

Webhook Handler for Payout Events
1import express, { Request, Response } from 'express';2import Stripe from 'stripe';3 4const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);5const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;6 7const app = express();8 9app.post('/webhooks', express.raw({ type: 'application/json' }),10 async (req: Request, res: Response) => {11 const signature = req.headers['stripe-signature'] as string;12 13 let event: Stripe.Event;14 15 try {16 event = stripe.webhooks.constructEvent(17 req.body,18 signature,19 webhookSecret20 );21 } catch (err) {22 console.error('Webhook signature verification failed');23 return res.status(400).send('Webhook error');24 }25 26 switch (event.type) {27 case 'payout.created':28 const payoutCreated = event.data.object as Stripe.Payout;29 console.log(`Payout created: ${payoutCreated.id}`);30 break;31 32 case 'payout.paid':33 const payoutPaid = event.data.object as Stripe.Payout;34 console.log(`Payout completed: ${payoutPaid.id}`);35 break;36 37 case 'payout.failed':38 const payoutFailed = event.data.object as Stripe.Payout;39 console.log(`Payout failed: ${payoutFailed.id}`);40 break;41 }42 43 res.json({ received: true });44 }45);

Best Practices for Payout Implementation

Building robust payout functionality requires attention to error handling, reconciliation, and security considerations.

Error Handling and Idempotency

Network issues and API rate limits can cause payout requests to fail or timeout. Implementing idempotent requests using Stripe's idempotency keys prevents duplicate payouts when retries occur.

Reconciliation and Reporting

Regular reconciliation between your Stripe payouts and internal financial records ensures accuracy and helps identify discrepancies early. Comparing payout amounts, dates, and statuses against your expected entries catches issues before they compound. Partnering with professional development services ensures your payment infrastructure follows industry best practices.

Security Considerations

Protect payout-related API keys and restrict access to payout operations. Use separate API keys for different environments (test versus live) and implement proper access controls in your application.

Idempotent Payout Creation
1import { v4 as uuidv4 } from 'uuid';2 3async function createPayoutIdempotent(4 amount: number,5 currency: string,6 idempotencyKey?: string7) {8 const key = idempotencyKey || uuidv4();9 10 try {11 const payout = await stripe.payouts.create(12 {13 amount: amount,14 currency: currency,15 },16 {17 idempotencyKey: key,18 }19 );20 21 return payout;22 } catch (error) {23 if (error.type === 'StripeCardError') {24 console.error('Card error during payout creation');25 }26 throw error;27 }28}

Frequently Asked Questions