Creating Destination Charges on Your Platform

    With Connect, you can make charges through your platform account on behalf of connected accounts and take fees in the process. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

    Connect supports three approaches for processing charges on behalf of a connected account. For Managed Accounts, the easiest route is to create the charge on the platform account and use the destination parameter to indicate the connected account. 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, wherein customers interact with the platform and the platform leverages vendors (e.g., Lyft). 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 while setting a destination, perform a standard create charge request while providing the connected account ID as the destination[account] value:

    curl https://api.stripe.com/v1/charges \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d amount=1000 \
       -d currency=usd \
       -d source=tok_4ftPE42dKmkGeVSoulmrxLMu \
       -d destination[account]="{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Token is created using Stripe.js or Checkout!
    # Get the payment token submitted by the form:
    token = params[:stripeToken]
    
    # Create a Charge:
    charge = Stripe::Charge.create({
      :amount => 1000,
      :currency => "usd",
      :source => token,
      :destination => {
        :account => "{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Token is created using Stripe.js or Checkout!
    # Get the payment token submitted by the form:
    token = request.POST['stripeToken']
    
    # Create a Charge:
    charge = stripe.Charge.create(
      amount=1000,
      currency="usd",
      source=token,
      destination={
        account="{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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    $token = $_POST['stripeToken'];
    
    // Create a Charge:
    $charge = \Stripe\Charge::create(array(
      "amount" => 1000,
      "currency" => "usd",
      "source" => $token,
      "destination" => array(
        "account" => "{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_BQokikJOvBiI2HlWgH4olfQ2";
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    String token = request.getParameter("stripeToken");
    
    // Create a Charge:
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("source", token);
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    destinationParams.put("account", "{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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    var token = request.body.stripeToken; // Using Express
    
    // Create a Charge:
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      source: token,
      destination: {
        account: "{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    token := r.FormValue("stripeToken")
    
    // Create a Charge:
    params := &stripe.ChargeParams{
      Amount: 1000,
      Currency: "usd",
      Destination: &stripe.DestinationParams{
        StripeAccount: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    }
    params.SetSource(token)
    
    charge, err := charge.New(params)
    

    When using the destination[account] parameter, the token must be created using the platform’s publishable key. If charging a Customer object, the Customer must exist within the platform account.

    The charge is attributed to the destination account for tax reporting.

    Collecting platform fees

    With Connect, your platform can earn money while processing charges. When using the destination[account] parameter, you effectively take a fee using the destination[amount] parameter.

    The destination[amount] is a positive integer reflecting the amount of the charge to be transferred to the destination[account]. Calculate this value by subtracting your platform’s fees from the charge amount:

    curl https://api.stripe.com/v1/charges \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d amount=1000 \
       -d currency=usd \
       -d source=tok_RS7k6vXWLcUrrYCbBoLS2ULQ \
       -d destination[amount]=877 \
       -d destination[account]="{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Token is created using Stripe.js or Checkout!
    # Get the payment token submitted by the form:
    token = params[:stripeToken]
    
    # Create a Charge:
    charge = Stripe::Charge.create({
      :amount => 1000,
      :currency => "usd",
      :source => token,
      :destination => {
        :amount => 877,
        :account => "{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Token is created using Stripe.js or Checkout!
    # Get the payment token submitted by the form:
    token = request.POST['stripeToken']
    
    # Create a Charge:
    charge = stripe.Charge.create(
      amount=1000,
      currency="usd",
      source=token,
      destination={
        amount=877,
        account="{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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    $token = $_POST['stripeToken'];
    
    // Create a Charge:
    $charge = \Stripe\Charge::create(array(
      "amount" => 1000,
      "currency" => "usd",
      "source" => $token,
      "destination" => array(
        "amount" => 877,
        "account" => "{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_BQokikJOvBiI2HlWgH4olfQ2";
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    String token = request.getParameter("stripeToken");
    
    // Create a Charge:
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1000);
    params.put("currency", "usd");
    params.put("source", token);
    Map<String, Object> destinationParams = new HashMap<String, Object>();
    destinationParams.put("amount", 877);
    destinationParams.put("account", "{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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    var token = request.body.stripeToken; // Using Express
    
    // Create a Charge:
    stripe.charges.create({
      amount: 1000,
      currency: "usd",
      source: token,
      destination: {
        amount: 877,
        account: "{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_BQokikJOvBiI2HlWgH4olfQ2"
    
    // Token is created using Stripe.js or Checkout!
    // Get the payment token submitted by the form:
    token := r.FormValue("stripeToken")
    
    // Create a Charge:
    params := &stripe.ChargeParams{
      Amount: 1000,
      Currency: "usd",
      Destination: &stripe.DestinationParams{
        Amount: 877,
        StripeAccount: "{CONNECTED_STRIPE_ACCOUNT_ID}",
      },
    }
    params.SetSource(token)
    
    charge, err := charge.New(params)
    

    Keep in mind:

    • The destination[amount]—is capped at the total transaction amount
    • The amount is always processed in the same currency as the transaction
    • No Stripe fees are applied to the amount
    • Your platform separately pays the Stripe fees on the charge

    Flow of funds with fees

    With the above code, the destination[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 destination[amount] is added to the platform account’s pending balance ($0.64, which is $10.00 - $0.59 - $8.18).

    The destination[amount] becomes available on the connected account’s normal transfer schedule, just like funds from regular Stripe charges.

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

    Issuing refunds

    Charges created on the platform account can be refunded using the platform account's secret key. When refunding a charge that has a destination[account] value, 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_BQokikJOvBiI2HlWgH4olfQ2: \
       -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_BQokikJOvBiI2HlWgH4olfQ2"
    
    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_BQokikJOvBiI2HlWgH4olfQ2"
    
    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_BQokikJOvBiI2HlWgH4olfQ2");
    
    $refund = \Stripe\Refund::create(array(
      "refund" => "{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_BQokikJOvBiI2HlWgH4olfQ2";
    
    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_BQokikJOvBiI2HlWgH4olfQ2");
    
    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_BQokikJOvBiI2HlWgH4olfQ2"
    
    params := &stripe.RefundParams{
      Charge: "{CHARGE_ID}",
      Transfer: true,
    }
    
    refund, err := refund.New(params)
    

    Assuming this is a full refund of the same $10.00 charge as above:

    • $10 goes back to the end customer
    • The Stripe fees of $0.59 are refunded to the platform
    • The transfer of $8.77 is reversed from the connected account to your platform
    • The end customer, platform, and connected account all have net cost (or gain) of $0

    When you use the reverse_transfer parameter, a proportional amount of the transfer is reversed to cover the refund.

    Further reading

    Discover what other Connect functionality is available.