Creating destination charges on your platform
Stripe recommends using destination charges for Express or Custom accounts. Destination charges are created on the platform, but as part of the charge operation, funds are transferred to the connected account specified in the transfer_data[destination]
parameter of the charge. The platform is responsible for the cost of the Stripe fees, refunds, and chargebacks. For more information about the different types of Connect charges, see the documentation on choosing an approach.
Caution
Destination charges are only supported if both your platform and the connected account are in the same region (for example, both in the US). For cross-region support, you must specify the settlement merchant to the connected account using the on_behalf_of
attribute on the charge or see other valid scenarios at Cross-border Transfers.
If you’re new to Connect, start with a guide to use destination charges to collect payments and then pay out.
Create a charge
To create a destination charge, specify the ID of the connected account that should receive the funds as the value of the transfer_data[destination]
parameter:
In the latest version of the API, specifying the automatic_payment_methods
parameter is optional because Stripe enables its functionality by default.
The payment method must be created using the platform’s publishable key. If charging a Customer
object, the Customer
must exist within the platform account. See accept a payment for the complete flow.
Specifying 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. When using destination charges, you have some flexibility for specifying the settlement merchant.
By default, creating a charge with transfer_data[destination]
makes the platform the settlement merchant. You can change this behavior and make the connected account the settlement merchant by using the on_behalf_of attribute on the charge.
Caution
The on_behalf_of
attribute is supported only for connected accounts with the card_payments capability. Accounts under the recipient service agreement can’t request card_payments
.
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 makes more sense for the connected account to be the settlement merchant.
When you use on_behalf_of
:
- Charges are settled in the connected account’s country and settlement currency.
- 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_behalf_of
is omitted, the platform is the business of record for the payment.
Collecting fees with application_fee_amount
When creating charges with an application_fee_amount
, the full charge amount is immediately transferred from the platform to the transfer_data[destination]
account after the charge is captured. The application_fee_amount
(capped at the full amount of the charge) is then transferred back to the platform.
In the latest version of the API, specifying the automatic_payment_methods
parameter is optional because Stripe enables its functionality by default.
To provide a better reporting experience, an application fee object is created once the application fee is collected. Use the amount
property on the application fee object for reporting. You can then access these objects with the Application Fees endpoint.
When using an application_fee_amount
, know that:
- The amount collected as an application fee is capped at the total transaction amount.
- The
application_fee_amount
is always processed in the same currency as the transaction. - Your platform pays the Stripe fee after the
application_fee_amount
is transferred to your account. - No additional Stripe fees are applied to the amount.
Flow of funds
With the above code, the full charge amount (10.00 USD) is added to the connected account’s pending balance. The application_fee_amount
(1.23 USD) is subtracted from the charge amount and is transferred to your platform. Then, Stripe fees (0.59 USD) are subtracted from the application_fee_amount
and the remaining funds (0.64 USD) are added to your platform account’s balance.
The application_fee_amount
becomes available on the platform account’s normal transfer schedule, just like funds from regular Stripe charges.
Note
Learn more about working with multiple currencies.
Collecting fees with transfer_data[amount]
You can also take a fee by using transfer_data[amount].
The transfer_data[amount]
is a positive integer reflecting the amount of the charge to be transferred to the transfer_data[destination]
. You subtract your platform’s fees from the charge amount, then pass the result of this calculation as the transfer_data[amount]
:
In the latest version of the API, specifying the automatic_payment_methods
parameter is optional because Stripe enables its functionality by default.
When using transfer_data[amount]
, know that:
- The amount is capped at the total transaction amount.
- The amount is always processed in the same currency as the transaction.
- Your platform separately pays the Stripe fees on the charge.
- No additional Stripe fees are applied to the amount.
- To calculate fees after a payment is created (often for reporting purposes), you need to retrieve the PaymentIntent and subtract the
transfer_data[amount]
from theamount
on the PaymentIntent.
If you need a more robust reporting experience, or if you plan to charge the same fee on all charges, an application fee amount might be a better fit for your integration.
Flow of funds
With the above code, the transfer_data[amount]
(8.77 USD) is added to the connected account’s pending balance. The charge total less the Stripe fees (on the charge amount) less the transfer_data[amount]
is added to the platform account’s pending balance (0.64 USD, which is 10.00 USD - 0.59 USD - 8.77 USD).
The transfer_data[amount]
becomes available on the connected account’s normal transfer schedule, just like funds from regular Stripe charges.
Platforms can track how much they retain from transfer_data[amount]
charges by looking at the Destination Platform Fee column in the Balance history export.
Note
Learn more about working with multiple currencies.
Differences between transfer_data[destination] and destination[account]
The destination[account]
parameter is deprecated, and replaced with transfer_data[destination]
. You should be aware of the following differences:
- When using
destination[account]
,on_behalf_of
is automatically set to the same value asdestination[account]
. - When using
transfer_data[destination]
, the settlement merchant can be specified withon_behalf_of
. If you need to retain the behavior ofdestination[account]
,on_behalf_of
must be explicitly set to the same value astransfer_data[destination]
. - When using
transfer_data[destination]
, the platform’s statement descriptor is used unlesson_behalf_of
is set.
Issuing refunds
If you are using the Payment Intents API, refunds should be issued against the most recent charge that is created.
Charges created on the platform account can be refunded using the platform account’s secret key. When refunding a charge that has a transfer_data[destination]
, by default the destination account keeps the funds that were transferred to it, leaving the platform account to cover the negative balance from the refund. To pull back the funds from the connected account to cover the refund, set the reverse_transfer
parameter to true
when creating the refund:
By default, the entire charge is refunded, but you can create a partial refund by setting an amount
value as a positive integer.
If the refund results in the entire charge being refunded, the entire transfer is reversed. Otherwise, a proportional amount of the transfer is reversed.
Refunding application fees
When refunding a charge with an application fee, by default the platform account keeps the funds from the application fee. To push the application fee funds back to the connected account, set the refund_application_fee
parameter to true
when creating the refund:
Note that if you refund the application fee for a destination charge, you must also reverse the transfer. If the refund results in the entire charge being refunded, the entire application fee is refunded as well. Otherwise, a proportional amount of the application fee is refunded.
Alternatively, you can provide a refund_application_fee
value of false and refund the application fee separately through the API.