Controlling Bank and Debit Card Payouts

    Stripe allows platforms to entirely control payouts for its Managed Accounts. If you need help after reading this, search our documentation or check out answers to common questions. You can even chat live with other developers in #stripe on freenode.

    By default, any charge you make on behalf of a connected account accumulates in the connected account’s Stripe balance and is paid out on a daily rolling basis. However, Stripe offers fine-grained control over this behavior for Managed Accounts.

    You can:

    Managing bank accounts and debit cards

    Managed Accounts have an external_accounts property: a list of all bank accounts and debit cards associated with the Stripe account. Any external account is a possible destination for funds.

    {
      ...
      "external_accounts": {
        "object": "list",
        "total_count": 3,
        "has_more": false,
        "url": "/v1/accounts/acct_14qyt6Alijdnw0EA/external_accounts",
        "data": [
          {
            "id": "ba_18u1IUJ6m0aiknMBHFQaTWOj",
            "object": "bank_account",
            "account": "acct_18rsqhJ6m0aiknMB",
            "account_holder_name": "Jane Austen",
            "account_holder_type": "individual",
            "bank_name": "STRIPE TEST BANK",
            "country": "US",
            "currency": "usd",
            "default_for_currency": false,
            "fingerprint": "sSZ2yLp0EZTH17cF",
            "last4": "6789",
            "metadata": {
            },
            "routing_number": "110000000",
            "status": "new"
          },
          {...},
          {...},
        ],
      ...
    }

    Destination accounts are added via the external_accounts parameter when creating or updating Stripe accounts. The value should be a bank account or debit card token returned from Stripe.js. Alternatively, you can provide a hash of the bank account details, but using Stripe.js is preferred as it prevents sensitive data from hitting your server.

    When using debit cards as a payout destination, the following restrictions apply:

    • Must be a non-prepaid U.S. Visa or Mastercard
    • Limited to $9,999 (USD) per payout on Instant Payouts
    • Generally limited to $3,000 (USD) per payout otherwise

    Managing multiple bank and debit accounts

    By default, providing a new value for external_accounts while updating a managed account replaces the existing account with the new one. To add additional bank accounts or debit cards to a connected account, use the Bank Account and Card creation API endpoints.

    curl https://api.stripe.com/v1/accounts/CONNECTED_STRIPE_ACCOUNT_ID/external_accounts \
       -u {PLATFORM_SECRET_KEY}: \
       -d external_account=btok_9CUINZPUJnubtQ
    
    Stripe.api_key = PLATFORM_SECRET_KEY
    account = Stripe::Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID)
    account.external_accounts.create(:external_account => "btok_9CUUxVXui4TQyJ")
    
    stripe.api_key = PLATFORM_SECRET_KEY
    account = stripe.Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID)
    account.external_accounts.create(external_account="btok_9CUY3ZiKZEHSlb")
    
    \Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY);
    $account = \Stripe\Account::retrieve(CONNECTED_STRIPE_ACCOUNT_ID);
    $account->external_accounts->create(array(
        "external_account" => "btok_9CUINZPUJnubtQ",
    ));
    
    Stripe.apiKey = PLATFORM_SECRET_KEY;
    Account account = Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID, null);
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("external_account", "btok_9CUaZTAdbT4G5z");
    account.getExternalAccounts().create(params);
    
    var stripe = require('stripe')(PLATFORM_SECRET_KEY);
    stripe.accounts.createExternalAccount(
      CONNECTED_STRIPE_ACCOUNT_ID,
      {external_account: "btok_9CUYdoUSROb2yg"}
    );
    

    When working with multiple currencies, Stripe automatically sends payouts to an associated bank account or debit card for its currency, thereby avoiding exchange fees. When there are multiple accounts available for a given currency, Stripe uses the one set as default_for_currency.

    Stripe maintains a list of available country/currency combinations for your reference and to help your users choose from the supported options.

    Payout information

    When using automatic payouts, the payout_schedule property on an account indicates how often the Stripe account’s balance is automatically paid out:

    {
      ...
      "payout_schedule": {
        "delay_days": 7,
        "interval": "daily"
      },
      ...
    }

    The delay_days property reflects how long it takes charges (or linked transfers) to become available for payout. This field is useful for controlling automatic payouts. For example, if you want your Managed Accounts to receive their funds 2 weeks after the charge is made, set interval to daily and delay_days to 14. The default is the lowest permitted value for the account, determined by the connected account’s country. When setting or updating this field, you may pass the string minimum to choose the lowest permitted value.

    There are four possible settings for the interval property:

    • manual prevents automatic payouts. You will have to manually pay out the account’s balance using the Payouts API (acting as the connected account). Also set an account to manual to use Instant Payouts.
    • daily automatically pays out charges delay_days days after they’re created. The delay_days value cannot be less than your own payout schedule or less than the default payout schedule for the account.
    • weekly automatically pays out the balance once a week, specified by the weekly_anchor parameter (a lower-case weekday such as monday).
    • monthly automatically pays out the balance once a month, specified by the monthly_anchor parameter (a number from 1 to 31).

    Using manual payouts

    If you set payout_schedule[interval] to manual using the Accounts API, Stripe will hold funds in the account holder’s balance until told to pay them out (or until a maximum of 90 days have passed). To trigger a payout of these funds, use the Payouts API.

    The Payouts API is only for moving funds from a connected Stripe account’s balance into their external account. To move funds between Stripe accounts, see creating separate charges and transfers or creating destination charges through the platform.

    Standard payouts

    As a basic payout example, to have $10 sent from a managed account’s Stripe balance to their external account:

    curl https://api.stripe.com/v1/payouts \
       -u {PLATFORM_SECRET_KEY}: \
       -H "Stripe-Account: {CONNECTED_STRIPE_ACCOUNT_ID}" \
       -d amount=1000 \
       -d currency=usd
    
    Stripe.api_key = PLATFORM_SECRET_KEY
    Stripe::Payout.create(
      {
        :amount => 1000,
        :currency => "usd"
      },
      {:stripe_account => CONNECTED_STRIPE_ACCOUNT_ID}
    )
    
    stripe.api_key = PLATFORM_SECRET_KEY
    stripe.Payout.create(
      amount=1000,
      currency="usd",
      stripe_account=CONNECTED_STRIPE_ACCOUNT_ID
    )
    
    \Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY);
    \Stripe\Payout::create(
      array(
        "amount" => 1000,
        "currency" => "usd"
      ),
      array("stripe_account" => CONNECTED_STRIPE_ACCOUNT_ID)
    );
    
    Stripe.apiKey = PLATFORM_SECRET_KEY;
    RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build();
    
    Map<String, Object> payoutParams = new HashMap<String, Object>();
    payoutParams.put("amount", 1000);
    payoutParams.put("currency", "usd");
    
    Payout.create(payoutParams, requestOptions);
    
    var stripe = require('stripe')(PLATFORM_SECRET_KEY);
    stripe.payouts.create(
      {
        amount: 1000,
        currency: "usd"
      },
      {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID}
    );
    

    With a standard payout, you can move up to the user’s available balance. To find that amount, perform a retrieve balance call on their behalf.

    Stripe tracks balance contributions from different payment sources in separate balances. The retrieve balance response breaks down the components of each balance by source type. For example, if you want to create a payout specifically for a non-credit-card balance, specify the source_type in your request.

    curl https://api.stripe.com/v1/payouts \
       -u {PLATFORM_SECRET_KEY}: \
       -d amount=24784 \
       -d currency=usd \
       -d source_type=bank_account
    
    Stripe.api_key = PLATFORM_SECRET_KEY
    Stripe::Payout.create(
      :amount => 24784,
      :currency => 'usd',
      :source_type => 'bank_account',
    )
    
    stripe.api_key = PLATFORM_SECRET_KEY
    stripe.Payout.create(
      amount=24784,
      currency="usd",
      source_type="bank_account",
    )
    
    \Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY);
    $tr = \Stripe\Payout::create(array(
      "amount" => 24784,
      "currency" => "usd",
      "source_type" => "bank_account"
    ));
    
    Stripe.apiKey = PLATFORM_SECRET_KEY;
    
    Map<String, Object> payoutParams = new HashMap<String, Object>();
    payoutParams.put("amount", 24784);
    payoutParams.put("currency", "usd");
    payoutParams.put("source_type", "bank_account");
    
    Payout.create(payoutParams);
    
    
    var stripe = require('stripe')(PLATFORM_SECRET_KEY);
    stripe.payouts.create(
      {
        amount: 24784,
        currency: 'usd',
        source_type: 'bank_account',
      }
    );
    

    Note that it is possible for any source’s balance component to go negative (through refunds or chargebacks), and payouts can’t be created for greater than the aggregate available balance.

    Using Instant Payouts (U.S. only)

    With Instant Payouts, you can immediately send funds to a managed account’s debit card. Funds typically appear in the associated bank account within 30 minutes, making it possible to go from charge to payout in mere moments.

    To use Instant Payouts, specify instant for the method property when creating the payout:

    curl https://api.stripe.com/v1/payouts \
       -u {PLATFORM_SECRET_KEY}: \
       -H "Stripe-Account: {CONNECTED_STRIPE_ACCOUNT_ID}" \
       -d amount=1000 \
       -d currency=usd \
       -d method=instant
    
    Stripe.api_key = PLATFORM_SECRET_KEY
    Stripe::Payout.create(
      {
        :amount => 1000,
        :currency => "usd",
        :method => "instant"
      },
      {:stripe_account => CONNECTED_STRIPE_ACCOUNT_ID}
    )
    
    stripe.api_key = PLATFORM_SECRET_KEY
    stripe.Payout.create(
      amount=1000,
      currency="usd",
      method="instant",
      stripe_account=CONNECTED_STRIPE_ACCOUNT_ID
    )
    
    \Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY);
    \Stripe\Payout::create(
      array(
        "amount" => 1000,
        "currency" => "usd",
        "method" => "instant"
      ),
      array("stripe_account" => CONNECTED_STRIPE_ACCOUNT_ID)
    );
    
    Stripe.apiKey = PLATFORM_SECRET_KEY;
    RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build();
    
    Map<String, Object> payoutParams = new HashMap<String, Object>();
    payoutParams.put("amount", 1000);
    payoutParams.put("currency", "usd");
    payoutParams.put("method", "instant");
    
    Payout.create(transferParams, requestOptions);
    
    var stripe = require('stripe')(PLATFORM_SECRET_KEY);
    stripe.payouts.create(
      {
        amount: 1000,
        currency: "usd",
        method: "instant"
      },
      {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID}
    );
    

    Instant Payouts differ from manual payouts in a couple of ways:

    • You can pay out an account’s available balance plus its pending balance
    • Instant Payouts can be requested on weekends and holidays

    Initially, platforms can pay out up to $5,000 (USD) per day—in total, across all connected accounts—through Instant Payouts. Contact us if you need this threshold increased.

    Instant Payouts is available for all of the largest U.S. banks, but a small percentage of banks do not yet support it. For those banks, you will have to fall back to standard payouts.

    When you add a card to an account, Stripe returns a property available_payout_methods in the response, which will be a set containing the payout methods Stripe supports for that card. This property will be either ["standard"] or ["standard", "instant"]. Only values in this set should be passed as the method when creating a payout.

    {
      "id": "card_9CUH5DBY1jTgQ0",
      "object": "card",
      ...
      "account": "acct_1032D82eZvKYlo2C",
      "available_payout_methods": ["standard", "instant"],
    }
    

    If a managed account's card does not support Instant Payouts, you should clearly communicate to the owner of that account that they will not receive their payouts instantly.

    Using webhooks with payouts

    All payout activity on connected accounts can be tracked using webhooks. (When using Connect, you should always be using webhooks.) Specific to payouts, you’ll see these events:

    • payout.created
    • payout.updated
    • payout.paid
    • payout.failed

    For most payouts, these event notifications occur over a series of days. For Instant Payouts, payout.paid will be sent on the next business day, although the funds should be received well beforehand.

    If a payout cannot be completed, a payout.failed event occurs. The event’s failure_reason property indicates why.

    Further reading

    Check out the rest of the guide for help with your integration.