Creating Destination Charges on Your Platform

    With Connect, you can create charges on your platform account, take fees, and then transfer remaining funds to your connected accounts.

    Connect supports three approaches for processing charges. For Express and Custom accounts, the easiest route is to create a destination charge. Destination charges are created on the platform, but funds are then transferred to the connected account with the transfer_data[destination] parameter. Using this approach, the platform is responsible for the cost of the Stripe fees, refunds, and chargebacks.

    This approach best fits an on-demand model, where customers interact with the platform and the platform leverages vendors (e.g., a ride-hailing company). This model also has a simple relationship between the charge (for the ride) and the transfer (to the individual driver).

    To charge on the platform and set a connected account as a destination, provide the connected account ID as the transfer_data[destination] value:

    curl https://api.stripe.com/v1/charges \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1000 \
      -d currency=usd \
      -d source=tok_visa \
      -d transfer_data[destination]="{CONNECTED_STRIPE_ACCOUNT_ID}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = Stripe::Charge.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      transfer_data: {
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    charge = stripe.Charge.create(
      amount=1000,
      currency="usd",
      source="tok_visa",
      transfer_data={
        "destination": "{CONNECTED_STRIPE_ACCOUNT_ID}",
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $charge = \Stripe\Charge::create([
      "amount" => 1000,
      "currency" => "usd",
      "source" => "tok_visa",
      "transfer_data" => [
        "destination" => "{CONNECTED_STRIPE_ACCOUNT_ID}",
      ],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("source", "tok_visa");
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    transferDataParams.put("destination", "{CONNECTED_STRIPE_ACCOUNT_ID}");
    params.put("destination", destinationParams);
    Charge charge = Charge.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      transfer_data: {
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    }).then(function(charge) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.ChargeParams{
      Amount: stripe.Int64(1000),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      TransferData: &stripe.DestinationParams{
        Destination: stripe.String("{CONNECTED_STRIPE_ACCOUNT_ID}"),
      },
    }
    params.SetSource("tok_visa")
    
    charge, err := charge.New(params)
    
    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d payment_method_types[]=card \
      -d amount=1000 \
      -d currency=usd \
      -d transfer_data[destination]="{CONNECTED_STRIPE_ACCOUNT_ID}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    payment_intent = Stripe::PaymentIntent.create({
      payment_method_types: ['card'],
      amount: 1000,
      currency: 'usd',
      transfer_data: {
        destination: '{CONNECTED_STRIPE_ACCOUNT_ID}',
      },
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    payment_intent = stripe.PaymentIntent.create(
      payment_method_types: ['card'],
      amount=1000,
      currency='usd',
      transfer_data={
        'destination': '{CONNECTED_STRIPE_ACCOUNT_ID}',
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $payment_intent = \Stripe\PaymentIntent::create([
      'payment_method_types' => ['card'],
      'amount' => 1000,
      'currency' => 'usd',
      'transfer_data' => [
        'destination' => '{CONNECTED_STRIPE_ACCOUNT_ID}',
      ],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    ArrayList paymentMethodTypes = new ArrayList();
    paymentMethodTypes.add("card");
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("payment_method_types", paymentMethodTypes);
    params.put("amount", 1000);
    params.put("currency", "usd");
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    transferDataParams.put("destination", "{CONNECTED_STRIPE_ACCOUNT_ID}");
    params.put("destination", destinationParams);
    PaymentIntent paymentIntent = PaymentIntent.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.paymentIntents.create({
      payment_method_types: ['card'],
      amount: 1000,
      currency: 'usd',
      transfer_data: {
        destination: '{CONNECTED_STRIPE_ACCOUNT_ID}',
      },
    }).then(function(paymentIntent) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentParams{
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
      Amount: stripe.Int64(1000),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      TransferData: &stripe.DestinationParams{
        Destination: stripe.String("{CONNECTED_STRIPE_ACCOUNT_ID}"),
      },
    }
    pi, err := paymentIntent.New(params)
    

    The Charges API example uses a test tokentok_visa—but you could tokenize a test card using Stripe.js and Elements or Stripe Checkout instead.

    The PaymentIntents API example doesn’t attach a payment method. Instead, attach one using Stripe.js & Elements or our iOS and Android SDKs.

    When using the transfer_data[destination] attribute, 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.

    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.

    Specifying the settlement merchant allows you to be more explicit about who charges are created for. For example, some platforms prefer to be the settlement merchant because the end customer interacts directly with their platform (e.g., on-demand platforms). However, some platforms have connected accounts that interact directly with end customers instead (e.g., a storefront on an e-commerce platform). In these scenarios, it makes more sense for the connected account to be the settlement merchant.

    Collecting fees with transfer_data[amount]

    When using transfer_data[destination], you can 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 need to calculate this value by subtracting your platform’s fees from the charge amount, and then pass it as the transfer_data[amount]:

    curl https://api.stripe.com/v1/charges \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1000 \
      -d currency=usd \
      -d source=tok_visa \
      -d transfer_data[amount]=877 \
      -d transfer_data[destination]="{CONNECTED_STRIPE_ACCOUNT_ID}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = Stripe::Charge.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      transfer_data: {
        amount: 877,
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    charge = stripe.Charge.create(
      amount=1000,
      currency="usd",
      source="tok_visa",
      transfer_data={
        "amount": 877,
        "destination": "{CONNECTED_STRIPE_ACCOUNT_ID}",
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $charge = \Stripe\Charge::create([
      "amount" => 1000,
      "currency" => "usd",
      "source" => "tok_visa",
      "transfer_data" => [
        "amount" => 877,
        "destination" => "{CONNECTED_STRIPE_ACCOUNT_ID}",
      ],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("source", "tok_visa");
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    transferDataParams.put("amount", 877);
    transferDataParams.put("destination", "{CONNECTED_STRIPE_ACCOUNT_ID}");
    params.put("destination", destinationParams);
    Charge charge = Charge.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      transfer_data: {
        amount: 877,
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    }).then(function(charge) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.ChargeParams{
      Amount: stripe.Int64(1000),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      TransferData: &stripe.DestinationParams{
        Amount: stripe.Int64(877),
        Destination: stripe.String("{CONNECTED_STRIPE_ACCOUNT_ID}"),
      },
    }
    params.SetSource("tok_visa")
    
    charge, err := charge.New(params)
    

    When using transfer_data[amount], know that:

    • You have to use the Charges API.
    • 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 charges are created (often for reporting purposes), you need to retrieve the charge and subtract the transfer_data[amount] from the amount on the charge.

    If you need a more robust reporting experience, or if you plan to charge the same fee on all charges, using 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) 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, which is $10.00 - $0.59 - $8.77).

    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.

    If you process payments in multiple currencies, you should also read how that is handled in Connect.

    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.

    curl https://api.stripe.com/v1/charges \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1000 \
      -d currency=usd \
      -d source=tok_visa \
      -d application_fee_amount=123 \
      -d transfer_data[destination]="{CONNECTED_STRIPE_ACCOUNT_ID}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = Stripe::Charge.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      application_fee_amount: 123,
      transfer_data: {
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    charge = stripe.Charge.create(
      amount=1000,
      currency="usd",
      source="tok_visa",
      application_fee_amount=123,
      transfer_data={
        "destination": "{CONNECTED_STRIPE_ACCOUNT_ID}",
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $charge = \Stripe\Charge::create([
      "amount" => 1000,
      "currency" => "usd",
      "source" => "tok_visa",
      "application_fee_amount" => 123,
      "transfer_data" => [
        "destination" => "{CONNECTED_STRIPE_ACCOUNT_ID}",
      ],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("source", "tok_visa");
    params.put("application_fee_amount", 123);
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    transferDataParams.put("destination", "{CONNECTED_STRIPE_ACCOUNT_ID}");
    params.put("destination", destinationParams);
    Charge charge = Charge.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      source: "tok_visa",
      application_fee_amount: 123,
      transfer_data: {
        destination: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    }).then(function(charge) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.ChargeParams{
      Amount: stripe.Int64(1000),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      ApplicationFeeAmount: stripe.Int64(123),
      TransferData: &stripe.DestinationParams{
        Destination: stripe.String("{CONNECTED_STRIPE_ACCOUNT_ID}"),
      },
    }
    params.SetSource("tok_visa")
    
    charge, err := charge.New(params)
    
    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d payment_method_types[]=card \
      -d amount=1000 \
      -d currency=usd \
      -d application_fee_amount=123 \
      -d transfer_data[destination]="{CONNECTED_STRIPE_ACCOUNT_ID}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    payment_intent = Stripe::PaymentIntent.create({
      payment_method_types: ['card'],
      amount: 1000,
      currency: 'usd',
      application_fee_amount: 123,
      transfer_data: {
        destination: '{CONNECTED_STRIPE_ACCOUNT_ID}',
      },
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    payment_intent = stripe.PaymentIntent.create(
      payment_method_types: ['card'],
      amount=1000,
      currency='usd',
      application_fee_amount=123,
      transfer_data={
        'destination': '{CONNECTED_STRIPE_ACCOUNT_ID}',
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $payment_intent = \Stripe\PaymentIntent::create([
      'payment_method_types' => ['card'],
      'amount' => 1000,
      'currency' => 'usd',
      'application_fee_amount' => 123,
      'transfer_data' => [
        'destination' => '{CONNECTED_STRIPE_ACCOUNT_ID}',
      ],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    ArrayList paymentMethodTypes = new ArrayList();
    paymentMethodTypes.add("card");
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("payment_method_types", paymentMethodTypes);
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("application_fee_amount", 123);
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    transferDataParams.put("destination", "{CONNECTED_STRIPE_ACCOUNT_ID}");
    params.put("destination", destinationParams);
    PaymentIntent paymentIntent = PaymentIntent.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.paymentIntents.create({
      payment_method_types: ['card'],
      amount: 1000,
      currency: 'usd',
      application_fee_amount: 123,
      transfer_data: {
        destination: '{CONNECTED_STRIPE_ACCOUNT_ID}',
      },
    }).then(function(paymentIntent) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentParams{
      PaymentMethodTypes: []*string{
        stripe.String("card"),
      },
      Amount: stripe.Int64(1000),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      ApplicationFeeAmount: stripe.Int64(123),
      TransferData: &stripe.DestinationParams{
        Destination: stripe.String("{CONNECTED_STRIPE_ACCOUNT_ID}"),
      },
    }
    pi, err := paymentIntent.New(params)
    

    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.
    • An application fee object is created and can be accessed in the charge object’s application_fee field.
    • The application fee 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.

    Differences between transfer_data[destination] and destination[account]

    If you’ve been using destination[account] to specify destination charges, there a few differences you should know about.

    • When using destination[account], on_behalf_of is automatically set to the same value as destination[account].
    • When using transfer_data[destination], the settlement merchant can be specified with on_behalf_of. If you need to retain the behavior of destination[account], on_behalf_of must be explicitly set to the same value as transfer_data[destination].
    • When using transfer_data[destination], the platform’s statement descriptor is used unless on_behalf_of is set.

    Issuing refunds

    If you are using the PaymentIntents 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:

    curl https://api.stripe.com/v1/refunds \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d charge="{CHARGE_ID}" \
      -d reverse_transfer=true
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    refund = Stripe::Refund.create({
      charge: "{CHARGE_ID}",
      reverse_transfer: true,
    })
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    refund = stripe.Refund.create(
      charge="{CHARGE_ID}",
      reverse_transfer=True,
    )
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $refund = \Stripe\Refund::create([
      "charge" => "{CHARGE_ID}",
      "reverse_transfer" => true,
    ]);
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("charge", "{CHARGE_ID}");
    params.put("reverse_transfer", true);
    Refund refund = Refund.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.refunds.create({
      charge: "{CHARGE_ID}",
      reverse_transfer: true,
    }).then(function(refund) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.RefundParams{
      Charge: stripe.String("{CHARGE_ID}"),
      ReverseTransfer: stripe.Bool(true),
    }
    refund, err := refund.New(params)
    

    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:

    curl https://api.stripe.com/v1/refunds \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d charge="{CHARGE_ID}" \
      -d reverse_transfer=true \
      -d refund_application_fee=true
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    refund = Stripe::Refund.create({
      charge: "{CHARGE_ID}",
      reverse_transfer: true,
      refund_application_fee: true,
    })
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    refund = stripe.Refund.create(
      charge="{CHARGE_ID}",
      reverse_transfer=True,
      refund_application_fee=True,
    )
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $refund = \Stripe\Refund::create([
      "charge" => "{CHARGE_ID}",
      "reverse_transfer" => true,
      "refund_application_fee" => true,
    ]);
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("charge", "{CHARGE_ID}");
    params.put("reverse_transfer", true);
    params.put("refund_application_fee", true);
    Refund refund = Refund.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.refunds.create({
      charge: "{CHARGE_ID}",
      reverse_transfer: true,
      refund_application_fee: true,
    }).then(function(refund) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.RefundParams{
      Charge: stripe.String("{CHARGE_ID}"),
      RefundApplicationFee: stripe.Bool(true),
      ReverseTransfer: stripe.Bool(true),
    }
    refund, err := refund.New(params)
    

    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.

    Further reading

    Discover what other Connect functionality is available.

    Questions?

    We're always happy to help with code or other questions you might have! Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.