Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Overview
Get started with Connect
Integration fundamentals
Example integrations
    Build a marketplace
    Build a SaaS platform
    Charge SaaS fees to connected accounts
    Build a fully embedded Connect integration
Onboard accounts
Configure account Dashboards
Accept payments
Pay out to accounts
Manage your Connect platform
Tax forms for your Connect platform
Work with connected account types
HomePlatforms and marketplacesExample integrations

Charge SaaS fees to your connected accountsPublic preview

Use Billing to charge SaaS fee subscriptions directly to your connected accounts.

Copy page

This guide explains how to use Accounts v2 to integrate Billing and Connect into your SaaS platform, which lets you charge subscription fees directly to your connected accounts.

You can enable Accounts v2 for your Connect platform from your Dashboard.

Test environment

To try this integration, you must use a Sandbox. You can’t use test mode.

Onboard your platform to Connect

Set up your Stripe account as a Connect platform by following the onboarding process in your Dashboard.

The Connect integration guide explains the platform configuration options.

If you have an existing platform, this integration doesn’t support your connected accounts that use Accounts v1. If you want to include them, you have to recreate them, following the process explained here, then remove their old accounts.

Create your connected accounts using the Accounts v2 API

Note

This integration uses only Accounts, Events, EventDestinations, and Persons from API v2. All other objects belong to API v1.

For each connected account, use the Accounts v2 API to create an Account object with the customer and merchant configurations.

  • The customer configuration allows the Account to pay your platform a subscription fee using a payment method that you attach to the Account.
  • The merchant configuration makes the Account a connected account that can accept card payments from its own customers. When you assign the merchant configuration, you also define other aspects of the connected account, such as:
    • Request the ability to accept card payments by setting configuration.merchant.capabilities.card_payments.requested to true.
    • Specify access to a Stripe Dashboard by setting dashboard. In the following example, we set dashboard to full, which means the Account has access to the full Stripe Dashboard.
    • Specify responsibility for collecting fees from the Account by setting defaults.responsibilities.fees_collector to stripe or application.
    • Specify responsibility for negative balances on the Account by setting defaults.responsibilities.losses_collector to stripe or application.

Use include to populate objects in the response

When you create, retrieve, or update an Account in API v2, certain properties are only populated in the response if you specify them in the include parameter. For any of those properties that you don’t specify, the response includes them as null, regardless of their actual value.

Command Line
cURL
curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer
{{YOUR_API_KEY}}
"
\ -H "Stripe-Version: 2025-04-30.preview" \ --json '{ "contact_email": "furever_contact@example.com", "display_name": "Furever", "dashboard": "full", "identity": { "business_details": { "registered_name": "Furever" }, "country": "us", "entity_type": "company" }, "configuration": { "customer": { "capabilities": { "automatic_indirect_tax": { "requested": true } } }, "merchant": { "capabilities": { "card_payments": { "requested": true } } } }, "defaults": { "currency": "usd", "responsibilities": { "fees_collector": "stripe", "losses_collector": "stripe" }, "locales": [ "en-US" ] }, "include": [ "configuration.customer", "configuration.merchant", "identity", "requirements" ] }'

The response includes the ID, which you use to reference the Account throughout your integration.

New Account response example
{ "id": "acct_xxxxxxxxxxxxxxxx", "object": "v2.core.account", "applied_configurations": [ "customer", "merchant" ], "configuration": { "customer": { "automatic_indirect_tax": { "exempt": "none", "ip_address": null, "location": null, "location-source": "identity_address" }, "billing": { ... }, "capabilities": { "automatic_indirect_tax": { "requested": true, "status": "restricted", "status_details": [ { "code": "requirements_past_due", "resolution": "provide_info" } ] } }, "shipping": ..., "test_clock": ... }, "merchant": { "bacs_debit_payments": null, "branding": { ... }, "capabilities": { ... "card_payments": { "requested": true, "status": "restricted", "status_details": [ { "code": "requirements_past_due", "resolution": "provide_info" } ] }, "stripe_balance": { "payouts": { "requested": true, "status": "restricted", "status_details": [ { "code": "requirements_past_due", "resolution": "provide_info" } ] } }, ... }, "card_payments": { "decline_on": { "avs_failure": false, "cvc_failure": false } }, "mcc": null, ... "statement_descriptor": { ... }, "support": { "address": { ... }, ... } }, "recipient": null }, "contact_email": "furever_contact@example.com", "created": "2025-03-04T02:23:20.000Z", "dashboard": "full", "identity": { "attestations": { ... }, "terms_of_service": { "account": null }, "business_details": { ... "registered_name": "Furever", ... }, "country": "US", "entity_type": "company", "individual": null }, "defaults": null, "display_name": "Furever", "metadata": {}, "requirements": { "collector": "stripe", "entries": [ { "awaiting_action_from": "user", "description": "representative.surname", "errors": [], "impact": { "restricts_capabilities": [ { "capability": "card_payments", "configuration": "merchant", "deadline": { "status": "past_due" } }, { "capability": "stripe_balance.payouts", "configuration": "merchant", "deadline": { "status": "past_due" } } ] }, "minimum_deadline": { "status": "past_due" }, "reference": null, "requested_reasons": [ { "code": "routine_onboarding" } ] } ], "summary": { "minimum_deadline": { "status": "past_due", "time": null } } } }

Account Responsibilities

Responsibilities define certain behaviors of connected accounts, such as how they pay Stripe fees and responsibility for negative balances. You set them when you add the merchant configuration to your connected accounts.

To enable your Accounts to collect payments as connected accounts, set the following responsibilities:

PropertyDescriptionValues
defaults.responsibilities.fees_collectorDefines how Stripe collects payment fees for direct charges on the connected account. (For destination or separate charges, Stripe always collects fees from your platform.)
  • application: Your platform collects application fees from the connected account, and Stripe collects payment fees from your platform.
  • stripe: Stripe collects payment fees directly from the connected account.
defaults.responsibilities.losses_collectorAssigns responsibility for negative balances incurred by the connected account.
  • application: Your platform is responsible for negative balances and manages risk for the connected account.
  • stripe: Stripe is liable for the connected account’s negative balances. Your platform is still liable for negative balances on your platform account.

Responsibilities are subject to the following restrictions:

  • If you set losses_collector to application, then you must also set fees_collector to application.
  • If you use destination charges with an Account, we recommend that you set both losses_collector and fees_collector to application.

For more information about supported configurations, see Integration recommendations.

Charge types

The preview release supports only direct and destination charges for connected accounts. You can’t use separate charges and transfers.

To use destination charges, you must set the on_behalf_of parameter to make the connected account the settlement merchant. You must also add the recipient configuration to your connected accounts and request the stripe_transfers capability for them.

Add the recipient configuration to connected accounts

To allow the transfer of funds from your platform’s Stripe balance to the connected account’s Stripe balance, add the recipient configuration and request the stripe_balance.stripe_transfers capability. Destination charges require this capability.

Requesting stripe_balance.stripe_transfers also automatically requests the recipient configuration’s stripe_balance.payouts capability, which allows the connected account to pay out to their external bank account.

The merchant configuration automatically requests its own stripe_balance.payouts capability, which is identical to the recipient configuration’s stripe_balance.payouts capability. If the account doesn’t need any other recipient capabilities, you don’t need to add the recipient configuration.

Note

The preview release doesn’t support cross-border payouts.

To add the recipient configuration and request the stripe_balance.stripe_transfers capability, update the Account and set the configuration.recipient.capabilities.stripe_balance.stripe_transfers.requested parameter to true.

Command Line
cURL
curl -X POST https://api.stripe.com/v2/core/accounts/acct_xxxxxxxxxxxxxxxx \ -H "Authorization: Bearer
{{YOUR_API_KEY}}
"
\ -H "Stripe-Version: 2025-04-30.preview" \ --json '{ "include": [ "identity", "requirements" ], "configuration": { "recipient": { "capabilities": { "stripe_balance": { "stripe_transfers": { "requested": true } } } } } }'

Onboard your connected accounts

Before your connected accounts can accept payments through your platform, you must onboard them. You can direct your accounts to Stripe-hosted onboarding, offer a branded flow using a Connect embedded component, or code your own custom onboarding flow. Stripe-hosted onboarding is the simplest option. Using an embedded component allows for some customization while handling most of the process automatically. A custom onboarding flow gives your platform full control, but requires the most resources for implementation and ongoing updates.

To integrate Stripe-hosted onboarding, follow the steps in the Stripe-hosted onboarding guide, with the following changes:

  • In the Create an account and prefill information step, create your Accounts following the Accounts v2 process described in this guide.
  • In the Identify and address requirement updates step, create an event destination to listen for v2.core.account[requirements].updated events. Don’t listen for the account.updated v1 event.

Note

The Stripe-hosted onboarding guide uses the Accounts v1 API. You can’t use the Accounts v1 API with API v2, and the structure of an Account in API v2 differs from the structure of an Account in API v1. Where the hosted onboarding guide refers to properties of Accounts v1, use the corresponding properties in Accounts v2 instead. Remember to use the include parameter to retrieve most Account properties in API v2.

Create external accounts for your connected accounts

The process for creating an external account depends on your connected accounts’ Dashboard access:

  • If an Account’s dashboard is full or express, the account owner adds its external account using their Dashboard.
  • If an Account’s dashboard is none, you can create its external account using the /v1/external_accounts endpoint.

Note

Regardless of your connected accounts’ Dashboard access, you can retrieve, list, update, or delete their external accounts using an API v1 call.

Command Line
cURL
curl https://api.stripe.com/v1/external_accounts \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -H "Stripe-Version: 2025-04-30.preview" \ -H "Stripe-Account:
{{CONNECTED_ACCOUNT_ID}}
"
\ -d "external_account[account_number]"=000123456789 \ -d "external_account[routing_number]"=110000000 \ -d "external_account[country]"=US \ -d "external_account[currency]"=USD \ -d "external_account[object]"=bank_account

Set up payments for your connected accounts

To set up payments for your connected accounts, follow the instructions in Direct charges or Destination charges. To use destination charges, you must set the on_behalf_of parameter.

Set up payouts for your connected accounts

You can configure your connected accounts’ payout settings, including the schedule, statement descriptor, and delay days, using either your Dashboard or the API.

Use the /v1/balance_settings endpoint.

Command Line
cURL
curl https://api.stripe.com/v1/balance_settings \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -H "Stripe-Version: 2025-04-30.preview" \ -H "Stripe-Account:
{{CONNECTED_ACCOUNT_ID}}
"
\ -d debit_negative_balances=true \ -d "payouts[schedule][interval]"=weekly \ -d "payouts[schedule][weekly_anchor]"=monday

Listen for requirements changes on your connected accounts

Account requirements can change, often due to changes implemented by financial regulators, card networks, and other financial institutions. To set up webhook notifications of requirement changes, create an event destination to listen for Account v2 update events.

  1. In your Stripe Dashboard, open the Developers menu by clicking Developers in the navigation menu footer, then select Webhooks.
  2. Click + Add destination.
  3. In the Events from section, select Connected accounts.
  4. Select Show advanced options. In the Payload style section, select Thin.
  5. In the Events field, type “v2” to search for v2 event types. Select v2.account[requirements].updated and the v2.account[configuration.configuration_type].capability_status_updated type for each configuration type used by your connected accounts.

Continue setting up your event destination by following the interactive webhook endpoint builder.

Configure your application to respond to update events by collecting any updated requirements.

Set up a local listener during development

You can send events to your local server for development purposes by installing the Stripe CLI and setting up a local listener.

  1. Log in to the Stripe Dashboard.
  2. In the Stripe CLI, enter the stripe login command. It redirects you to your browser to confirm and authenticate your account.
  3. Return to the CLI and run the following command. It listens to all available V2 events on your platform and connected accounts, and forwards them to http://localhost:4242.
Command Line
stripe listen --thin-events 'v2.core.account[requirements].updated,v2.core.account[configuration.recipient].capability_status_updated,v2.core.account[configuration.merchant].capability_status_updated,v2.core.account[configuration.customer].capability_status_updated' --forward-thin-to http://localhost:4242

Integrate Billing to collect recurring fees

Collecting recurring fees from your connected accounts with Stripe Billing involves the following steps:

  1. Create one or more products to represent the recurring fees.
  2. Create subscriptions for your fee products with the accounts as customers.
  3. (Optional) To collect subscription fees directly from connected accounts’ Stripe balances, avoiding transaction fees associated with other payment methods such as cards, configure it as a payment method.

Note

A connected account can pay using its Stripe balance only if it has a sufficient available balance to make the payment. We provide recommendations for avoiding balance payment failures later in these instructions.

1. Create a product with a recurring price

Create a product and price representing your subscription fee. You can use the API or the Dashboard.

Create a Product and define the default price as a recurring charge. Return the price information by including default_price in the expand parameter.

Command Line
cURL
curl https://api.stripe.com/v1/products \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d name="Connected account subscription fee" \ -d "default_price_data[unit_amount]"=1000 \ -d "default_price_data[currency]"=usd \ -d "default_price_data[recurring][interval]"=month \ -d "expand[]"=default_price

Record the price ID (price_xxxxxxxxxxxxxx) to use later when you create a subscription.

Regional considerations

If you accept balance payments in multiple currencies, create a separate price in each currency for each product. For example, if you create a product with a USD price, and want to charge a connected account for it in EUR, add a price for that product in EUR.

2. Create subscriptions to charge your connected accounts

You can collect SaaS subscription fees directly from a connected account’s Stripe balance. The connected account must meet the following requirements:

  • It must have both the merchant and customer configurations.
  • Its merchant configuration’s card_payments capability must be active.
  • Its available balance must have sufficient funds to make a full payment.

To implement a custom process for your connected account owners to purchase subscriptions, use a SetupIntent to attach a PaymentMethod to their Account object.

To attach payment from the account’s Stripe balance as the payment method when creating a SetupIntent, specify the following values:

Command Line
cURL
curl https://api.stripe.com/v1/setup_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -H "Stripe-Version: 2025-04-30.preview" \ -d "payment_method_types[]"=stripe_balance \ -d confirm=true \ -d customer_account=acct_xxxxxxxxxxxxxx \ -d usage=off_session \ -d "payment_method_data[type]"=stripe_balance

Successful creation of the SetupIntent returns data similar to the following:

{ "id": "seti_123", "object": "setup_intent", "customer": "cus_xxxxxxxxxxxxxx", "customer_account": "acct_xxxxxxxxxxxxxx", "payment_method": "pm_xxxxxxxxxxxxxx", "status": "succeeded" }

You can then create Subscriptions using the account’s attached PaymentMethod by passing the Account ID as the customer_account.

To create a subscription that collects payments from the account’s Stripe balance, set the payment method type explicitly, as in the following example.

Command Line
cURL
curl https://api.stripe.com/v1/subscriptions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -H "Stripe-Version: 2025-04-30.preview" \ -d customer_account=acct_xxxxxxxxxxxxxx \ -d default_payment_method=pm_xxxxxxxxxxxxxx \ -d "items[0][price]"=price_xxxxxxxxxxxxxx \ -d "items[0][quantity]"=1 \ -d "payment_settings[payment_method_types][0]"=stripe_balance

Configure your integration to manage Stripe balance payment failures

When you collect a payment from a connected account’s Stripe balance, the account’s available balance must have sufficient funds to make the full payment. Otherwise, the payment fails. If you plan to collect payments directly from your connected accounts’ Stripe balances, we recommend configuring your integration to manage balance-related payment failures.

Avoid balance payment failures

Because payments from a connected account’s Stripe balance rely on its available funds, you can avoid payment failures by taking steps to maximize your connected accounts’ balances.

Tailor connected account payout schedules

Coordinate your payout schedules with your subscription billing cycles. For example, if you charge subscription fees on the first day of each month, and schedule weekly payouts on Mondays, then months with more Mondays have more payouts. Those months have lower available balances than months with fewer payouts, making payment failures more likely.

Another way to avoid payment failures due to payouts is to change to manual payouts before a subscription payment. At a set time before each subscription payment, if a connected account has sufficient available funds, switch it to manual payouts so the subscription payment gets paid before the automatic payout clears the account. After the subscription payment, resume automatic payouts.

Set a minimum balance on connected accounts

You can prevent automatic payouts from reducing a connected account’s available balance below a certain amount by defining a minimum balance for that account.

  1. Find the account in your Dashboard.
  2. From the account’s overflow menu (), select View Dashboard as….
  3. Click the gear icon and select Settings.
  4. Under Account Settings, click Business.
  5. Select the External payout accounts and scheduling tab.
  6. Turn on Keep a minimum amount in your payments balance and enter an amount.

You must manually set the minimum balance for each connected account.

Handle balance payment failures

Set up webhooks and event destinations to receive notifications about subscription payments. Identify payment failures by listening for the invoice.payment_failed event. When a payment fails:

  • The PaymentIntent status changes to requires_action.
  • The Subscription status remains incomplete for the current invoice.
  • The Subscription continues to generate invoices, which remain in draft status.

Note

Payments from Stripe balances don’t support smart retries.

If a payment from a Stripe balance fails due to insufficient available funds, you can retry it by following these steps:

  1. Set the connected account’s payout schedule interval to manual.
  2. Listen for the next payment that comes into the connected account, then check the account’s available balance.
  3. If the available balance is equal to or greater than the subscription fee, set the unpaid invoice’s payment method to stripe_balance and retry it. Otherwise, continue listening for payments until the available balance is enough to pay the invoice.
  4. If the payment succeeds, restore the connected account’s normal payout schedule.

Instead of retrying a failed payment from a Stripe balance, you can try using a different payment method by specifying it directly on the invoice. You can also implement a flow that allows connected accounts to update their own subscription payment methods.

Preview considerations

Accounts v2 allows you to use a single, configurable account for each business on your platform that collects payments directly. The preview release doesn’t support Treasury, Issuing, or payment methods that are in preview. You can still use Treasury, Issuing, or payment methods in preview with Accounts v1.

Enable Accounts v2 for your Connect platform from your Dashboard.

Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access program.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc