Create separate charges and transfers
Create charges on your platform account and transfer funds to multiple connected accounts.
Create separate charges and transfers to transfer funds from one payment to multiple connected accounts, or when a specific user isn’t known at the time of the payment. The charge on your platform account is decoupled from the transfers to your connected accounts. With this charge type:
- You create a charge on your platform’s account and also transfer funds to your connected accounts. The payment appears as a charge on your account and there are also transfers to connected accounts (amount determined by you), which are withdrawn from your account balance.
- You can transfer funds to multiple connected accounts.
- Your account balance is debited for the cost of the Stripe fees, refunds, and chargebacks.
This charge type helps marketplaces split payments between multiple parties. For example, a restaurant delivery platform that splits payments between the restaurant and the deliverer.
Note
Funds segregation is a private preview feature that keeps payment funds in a protected holding state before you transfer them to connected accounts. This prevents allocated funds from being used for unrelated platform operations. Contact your Stripe account manager to request access.
Stripe supports separate charges and transfers in the following regions:
In most scenarios, your platform and any connected account must be in the same region. Attempting to transfer funds across a disallowed border returns an error. For information about cross-region support, see cross-border transfers. You must only use transfers in combination with the permitted use cases for charges, tops-ups and fees. We recommend using separate charges and transfers for connected accounts that have access to the Express Dashboard or no Dashboard access.

Integrate Stripe’s prebuilt payment UI into the checkout of your iOS app with the PaymentSheet class. See our sample integration on GitHub.
Set up StripeServer-sideClient-side
First, you need a Stripe account. Register now.
Server-side 
This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries for access to the Stripe API from your server:
Client-side 
The Stripe iOS SDK is open source, fully documented, and compatible with apps supporting iOS 13 or above.
Note
For details on the latest SDK release and past versions, see the Releases page on GitHub. To receive notifications when a new release is published, watch releases for the repository.
Configure the SDK with your Stripe publishable key on app start. This enables your app to make requests to the Stripe API.
Add an endpointServer-side
This integration uses three Stripe API objects:
- A PaymentIntent. Stripe uses this to represent your intent to collect a payment from a customer, tracking your charge attempts and payment state changes throughout the process.
- A Customer(optional). To set up a payment method for future payments, it must be attached to a Customer. Create a Customer object when your customer creates an account with your business. If your customer is making a payment as a guest, you can create a Customer object before payment and associate it with your own internal representation of the customer’s account later.
- A Customer Ephemeral Key (optional). Information on the Customer object is sensitive, and can’t be retrieved directly from an app. An Ephemeral Key grants the SDK temporary access to the Customer.
If you want to save cards and allow returning customers to reuse saved cards, you need the Customer and Customer Ephemeral Key objects for your integration. Otherwise, you can omit these objects.
For security reasons, your app can’t create these objects. Instead, add an endpoint on your server that:
- Retrieves the Customer, or creates a new one.
- Creates an Ephemeral Key for the Customer.
- Creates a PaymentIntent with the amount, currency, customer, and a transfer group to associate with the transfer of funds later.
- Returns the Payment Intent’s client secret, the Ephemeral Key’s
secret
, the Customer ID, and your publishable key to your app.
The payment methods shown to customers during the checkout process are also included on the PaymentIntent. You can let Stripe pull payment methods from your Dashboard settings or you can list them manually.
Unless your integration requires a code-based option for offering payment methods, don’t list payment methods manually. Stripe evaluates the currency, payment method restrictions, and other parameters to determine the list of supported payment methods. Stripe prioritizes payment methods that help increase conversion and are most relevant to the currency and the customer’s location. We hide lower priority payment methods in an overflow menu.
Integrate the payment sheetClient-side
To display the mobile Payment Element on your checkout screen, make sure you:
- Display the products the customer is purchasing along with the total amount
- Use the Address Element to collect any required shipping information from the customer
- Add a checkout button to display Stripe’s UI
If PaymentSheetResult
is .
, inform the user (for example, by displaying an order confirmation screen).
Setting allowsDelayedPaymentMethods
to true allows delayed notification payment methods like US bank accounts. For these payment methods, the final payment status isn’t known when the PaymentSheet
completes, and instead succeeds or fails later. If you support these types of payment methods, inform the customer their order is confirmed and only fulfill their order (for example, ship their product) when the payment is successful.
Set up a return URLClient-side
The customer might navigate away from your app to authenticate (for example, in Safari or their banking app). To allow them to automatically return to your app after authenticating, configure a custom URL scheme and set up your app delegate to forward the URL to the SDK. Stripe doesn’t support universal links.
Handle post-payment eventsServer-side
Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard webhook tool or follow the webhook guide to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.
Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events is what enables you to accept different types of payment methods with a single integration.
In addition to handling the payment_
event, we recommend handling these other events when collecting payments with the Payment Element:
Event | Description | Action |
---|---|---|
payment_intent.succeeded | Sent when a customer successfully completes a payment. | Send the customer an order confirmation and fulfill their order. |
payment_intent.processing | Sent when a customer successfully initiates a payment, but the payment has yet to complete. This event is most commonly sent when the customer initiates a bank debit. It’s followed by either a payment_ or payment_ event in the future. | Send the customer an order confirmation that indicates their payment is pending. For digital goods, you might want to fulfill the order before waiting for payment to complete. |
payment_intent.payment_failed | Sent when a customer attempts a payment, but the payment fails. | If a payment transitions from processing to payment_ , offer the customer another attempt to pay. |
Create a TransferServer-side
On your server, send funds from your account to a connected account by creating a Transfer and specifying the transfer_
used.
Transfer and charge amounts don’t have to match. You can split a single charge between multiple transfers or include multiple charges in a single transfer. The following example creates an additional transfer associated with the same transfer_
.
Transfer options
You can assign any value to the transfer_
string, but it must represent a single business action. You can also make a transfer with neither an associated charge nor a transfer_
—for example, when you must pay a provider but there’s no associated customer payment.
Note
The transfer_
only identifies associated objects. It doesn’t affect any standard functionality. To prevent a transfer from executing before the funds from the associated charge are available, use the transfer’s source_
attribute.
By default, a transfer request fails when the amount exceeds the platform’s available account balance. Stripe doesn’t automatically retry failed transfer requests.
You can avoid failed transfer requests for transfers that are associated with charges. When you specify the associated charge as the transfer’s source_transaction, the transfer request automatically succeeds. However, we don’t execute the transfer until the funds from that charge are available in the platform account.
Note
If you use separate charges and transfers, take that into account when planning your payout schedule. Automatic payouts can interfere with transfers that don’t have a defined source_
.
Test the integration
See Testing for additional information to test your integration.
OptionalEnable Apple Pay
Note
If your checkout screen has a dedicated Apple Pay button, follow the Apple Pay guide and use ApplePayContext
to collect payment from your Apple Pay button. You can use PaymentSheet
to handle other payment method types.
Register for an Apple Merchant ID
Obtain an Apple Merchant ID by registering for a new identifier on the Apple Developer website.
Fill out the form with a description and identifier. Your description is for your own records and you can modify it in the future. Stripe recommends using the name of your app as the identifier (for example, merchant.
).
Create a new Apple Pay certificate
Create a certificate for your app to encrypt payment data.
Go to the iOS Certificate Settings in the Dashboard, click Add new application, and follow the guide.
Download a Certificate Signing Request (CSR) file to get a secure certificate from Apple that allows you to use Apple Pay.
One CSR file must be used to issue exactly one certificate. If you switch your Apple Merchant ID, you must go to the iOS Certificate Settings in the Dashboard to obtain a new CSR and certificate.
Integrate with Xcode
Add the Apple Pay capability to your app. In Xcode, open your project settings, click the Signing & Capabilities tab, and add the Apple Pay capability. You might be prompted to log in to your developer account at this point. Select the merchant ID you created earlier, and your app is ready to accept Apple Pay.

Enable the Apple Pay capability in Xcode
Add Apple Pay
Order tracking
To add order tracking information in iOS 16 or later, configure an authorizationResultHandler in your PaymentSheet.
. Stripe calls your implementation after the payment is complete, but before iOS dismisses the Apple Pay sheet.
In your authorizationResultHandler
implementation, fetch the order details from your server for the completed order. Add the details to the provided PKPaymentAuthorizationResult and call the provided completion handler.
To learn more about order tracking, see Apple’s Wallet Orders documentation.
let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( authorizationResultHandler: { result, completion in // Fetch the order details from your service MyAPIClient.shared.fetchOrderDetails(orderID: orderID) { myOrderDetails result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: myOrderDetails.orderTypeIdentifier, // "com.myapp.order" orderIdentifier: myOrderDetails.orderIdentifier, // "ABC123-AAAA-1111" webServiceURL: myOrderDetails.webServiceURL, // "https://my-backend.example.com/apple-order-tracking-backend" authenticationToken: myOrderDetails.authenticationToken) // "abc123" // Call the completion block on the main queue with your modified PKPaymentAuthorizationResult completion(result) } } ) var configuration = PaymentSheet.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers)
OptionalEnable card scanning
To enable card scanning support, set the NSCameraUsageDescription
(Privacy - Camera Usage Description) in the Info.plist of your application, and provide a reason for accessing the camera (for example, “To scan cards”). Devices with iOS 13 or higher support card scanning.
OptionalCustomize the sheet
All customization is configured through the PaymentSheet.Configuration object.
Appearance
Customize colors, fonts, and so on to match the look and feel of your app by using the appearance API.
Payment method layout
Configure the layout of payment methods in the sheet using paymentMethodLayout. You can display them horizontally, vertically, or let Stripe optimize the layout automatically.

var configuration = PaymentSheet.Configuration() configuration.paymentMethodLayout = .automatic
Collect users addresses
Collect local and international shipping or billing addresses from your customers using the Address Element.
Merchant display name
Specify a customer-facing business name by setting merchantDisplayName. By default, this is your app’s name.
var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "My app, Inc."
Dark mode
PaymentSheet
automatically adapts to the user’s system-wide appearance settings (light and dark mode). If your app doesn’t support dark mode, you can set style to alwaysLight
or alwaysDark
mode.
var configuration = PaymentSheet.Configuration() configuration.style = .alwaysLight
Default billing details
To set default values for billing details collected in the payment sheet, configure the defaultBillingDetails
property. The PaymentSheet
pre-populates its fields with the values that you provide.
var configuration = PaymentSheet.Configuration() configuration.defaultBillingDetails.address.country = "US" configuration.defaultBillingDetails.email = "foo@bar.com"
Billing details collection
Use billingDetailsCollectionConfiguration
to specify how you want to collect billing details in the payment sheet.
You can collect your customer’s name, email, phone number, and address.
If you only want to billing details required by the payment method, set billingDetailsCollectionConfiguration.
to true. In that case, the PaymentSheet.
are set as the payment method’s billing details.
If you want to collect additional billing details that aren’t necessarily required by the payment method, set billingDetailsCollectionConfiguration.
to false. In that case, the billing details collected through the PaymentSheet
are set as the payment method’s billing details.
var configuration = PaymentSheet.Configuration() configuration.defaultBillingDetails.email = "foo@bar.com" configuration.billingDetailsCollectionConfiguration.name = .always configuration.billingDetailsCollectionConfiguration.email = .never configuration.billingDetailsCollectionConfiguration.address = .full configuration.billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod = true
Note
Consult with your legal counsel regarding laws that apply to collecting information. Only collect phone numbers if you need them for the transaction.
OptionalComplete payment in your UI
You can present the Payment Sheet to only collect payment method details and then later call a confirm
method to complete payment in your app’s UI. This is useful if you have a custom buy button or require additional steps after you collect payment details.

Complete the payment in your app’s UI
If PaymentSheetResult
is .
, inform the user (for example, by displaying an order confirmation screen).
Setting allowsDelayedPaymentMethods
to true allows delayed notification payment methods like US bank accounts. For these payment methods, the final payment status isn’t known when the PaymentSheet
completes, and instead succeeds or fails later. If you support these types of payment methods, inform the customer their order is confirmed and only fulfill their order (for example, ship their product) when the payment is successful.
OptionalEnable additional payment methods
Navigate to Manage payment methods for your connected accounts in the Dashboard to configure which payment methods your connected accounts accept. Changes to default settings apply to all new and existing connected accounts.
Consult the following resources for payment method information:
- A guide to payment methods to help you choose the correct payment methods for your platform.
- Account capabilities to make sure your chosen payment methods work for your connected accounts.
- Payment method and product support tables to make sure your chosen payment methods work for your Stripe products and payments flows.
For each payment method, you can select one of the following dropdown options:
On by default | Your connected accounts accept this payment method during checkout. Some payment methods can only be off or blocked. This is because your connected accounts with access to the Stripe Dashboard must activate them in their settings page. |
Off by default | Your connected accounts don’t accept this payment method during checkout. If you allow your connected accounts with access to the Stripe Dashboard to manage their own payment methods, they have the ability to turn it on. |
Blocked | Your connected accounts don’t accept this payment method during checkout. If you allow your connected accounts with access to the Stripe Dashboard to manage their own payment methods, they don’t have the option to turn it on. |

Payment method options
If you make a change to a payment method, you must click Review changes in the bottom bar of your screen and Save and apply to update your connected accounts.

Save dialog
Allow connected accounts to manage payment methods
Stripe recommends allowing your connected accounts to customize their own payment methods. This option allows each connected account with access to the Stripe Dashboard to view and update their Payment methods page. Only owners of the connected accounts can customize their payment methods. The Stripe Dashboard displays the set of payment method defaults you applied to all new and existing connected accounts. Your connected accounts can override these defaults, excluding payment methods you have blocked.
Check the Account customization checkbox to enable this option. You must click Review changes in the bottom bar of your screen and then select Save and apply to update this setting.

Account customization checkbox
Payment method capabilities
To allow your connected accounts to accept additional payment methods, you must make sure their connected accounts have active capabilities for each payment method. Most payment methods have the same verification requirements as the card_
capability, with some restrictions and exceptions. The payment method capabilities table lists the payment methods that require additional verification over cards.
Specify the settlement merchant 
The settlement merchant is dependent on the capabilities set on an account and how a charge is created. The settlement merchant determines whose information is used to make the charge. This includes the statement descriptor (either the platform’s or the connected account’s) that’s displayed on the customer’s credit card or bank statement for that charge.
Specifying the settlement merchant allows you to be more explicit about who to create charges for. For example, some platforms prefer to be the settlement merchant because the end customer interacts directly with their platform (such as on-demand platforms). However, some platforms have connected accounts that interact directly with end customers instead (such as a storefront on an e-commerce platform). In these scenarios, it might make more sense for the connected account to be the settlement merchant.
You can set the on_
parameter to the ID of a connected account to make that account the settlement merchant for the payment. When using on_
:
- Charges settle in the connected account’s country and settlement currency.
- The fee structure for the connected account’s country is used.
- The connected account’s statement descriptor is displayed on the customer’s credit card statement.
- If the connected account is in a different country than the platform, the connected account’s address and phone number are displayed on the customer’s credit card statement.
- The number of days that a pending balance is held before being paid out depends on the delay_days setting on the connected account.
If on_
is omitted, the platform is the business of record for the payment.
Caution
The on_
parameter is supported only for connected accounts with a payments capability such as card_payments. Accounts under the recipient service agreement can’t request card_
or other payments capabilities.
Collect fees 
When using separate charges and transfers, the platform can collect fees on a charge by reducing the amount it transfers to the destination accounts. For example, consider a restaurant delivery service transaction that involves payments to the restaurant and to the driver:
- The customer pays a 100 USD charge.
- Stripe collects a 3.20 USD fee and adds the remaining 96.80 USD to the platform account’s pending balance.
- The platform transfers 70 USD to the restaurant’s connected account and 20 USD to the driver’s connected account.
- A platform fee of 6.80 USD remains in the platform account.
Application fees with funds segregation
Funds segregation is a private preview feature that allows you to debit application fees directly from allocated funds during transfer, providing clean accounting separation. Contact your Stripe account manager to request access.

To learn about processing payments in multiple currencies with Connect, see working with multiple currencies.
Transfer availability
The default behavior is to transfer funds from the platform account’s available balance. Attempting a transfer that exceeds the available balance fails with an error. To avoid this problem, when creating a transfer, tie it to an existing charge by specifying the charge ID as the source_
parameter. With a source_
, the transfer request returns success regardless of your available balance if the related charge hasn’t settled yet. However, the funds don’t become available in the destination account until the funds from the associated charge are available to transfer from the platform account.
Transfers with funds segregation
The private preview funds segregation feature requires the source_
parameter for transfers from allocated funds so they are linked to their original payment.
Note
If a transfer fails due to insufficient funds in your platform balance, adding funds doesn’t automatically retry the failed action. After adding funds, you must repeat any failed transfers or payouts.
If the source charge has a transfer_
value, Stripe assigns the same value to the transfer’s transfer_
. If it doesn’t, then Stripe generates a string in the format group_
plus the associated PaymentIntent ID, for example: group_
. It assigns that string as the transfer_
for both the charge and the transfer.
Note
You must specify the source_
when you create a transfer. You can’t update that attribute later.
You can get the charge ID from the PaymentIntent:
- Get the PaymentIntent’s latest_charge attribute. This attribute is the ID of the most recent charge associated with the PaymentIntent.
- Request a list of charges, specifying the
payment_
in the request. This method returns full data for all charges associated with the PaymentIntent.intent
When using this parameter:
- The amount of the transfer must not exceed the amount of the source charge
- You can create multiple transfers with the same
source_
, as long as the sum of the transfers doesn’t exceed the source chargetransaction - The transfer takes on the pending status of the associated charge: if the funds from the charge become available in N days, the payment that the destination Stripe account receives from the transfer also becomes available in N days
- Stripe automatically creates a
transfer_
for yougroup - The currency of the balance transaction associated with the charge must match the currency of the transfer
Asynchronous payment methods, like ACH, can fail after a subsequent transfer request is made. For these payments, avoid using source_
. Instead, wait until a charge.succeeded event is triggered before transferring the funds. If you have to use source_
with these payments, you must implement functionality to manage payment failures.
When a payment used as a source_
fails, funds from your platform’s account balance are transferred to the connected account to cover the payment. To recover these funds, reverse the transfer associated with the failed source_
.
Issue refunds 
You can refund charges created on your platform using its secret key. However, refunding a charge has no impact on any associated transfers. It’s up to your platform to reconcile any amount owed back to it by reducing subsequent transfer amounts or by reversing transfers.
Refunds with funds segregation
The private preview funds segregation feature uses allocated funds for refunds before debiting your platform’s payments balance, providing clean accounting separation.
Reverse transfers 
Connect supports the ability to reverse transfers made to connected accounts, either entirely or partially (by setting an amount
value). Use transfer reversals only for refunds or disputes related to the charge, or to correct errors in the transfer.
Transfer reversals add the specified (or entire) amount back to the platform’s available balance, reducing the connected account’s available balance accordingly. It is only possible to reverse a transfer if the connected account’s available balance is greater than the reversal amount or has connected reserves enabled.
If the transfer reversal requires a currency conversion, and the reversal amount would result in a zero balance after the conversion, it returns an error.
Disabling refunds for a connected account won’t block the ability to process transfer reversals.