Authentication with Connect

    Learn how to authenticate as your users, so you can perform any API actions on their behalf. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

    API authentication

    There are two ways of authenticating requests when performing actions on behalf of a connected account. Both approaches assume you previously stored information about the connected account for later use: the Stripe account ID and/or the account’s secret and publishable keys.

    For most integrations, you should go with the first option—it’s easier and likely more secure. If you have any application that requires you to publish keys (e.g. a mobile app), you might want to use the second instead.

    Authentication via the Stripe-Account header

    The first, preferred, authentication option is to use your (the platform account’s) secret key and pass a Stripe-Account header identifying the connected account for which the request is being made. This code performs a refund of a charge on behalf of a connected account:

    curl https://api.stripe.com/v1/charges/{CHARGE_ID}/refunds \
       -u {PLATFORM_SECRET_KEY}: \
       -H "Stripe-Account: {CONNECTED_STRIPE_ACCOUNT_ID}" \
       -d amount=1000
    

    This authentication approach is implied in any API request that includes the Stripe account ID in the URL:

    curl https://api.stripe.com/v1/accounts/{CONNECTED_STRIPE_ACCOUNT_ID} \
       -u {PLATFORM_SECRET_KEY}:
    

    With this method, you only need to store a single secret key, which can be easier to secure than many keys.

    All of Stripe’s libraries support this style of authentication on a per-request basis:

    Stripe.api_key = PLATFORM_SECRET_KEY
    Stripe::Customer.create(
      {:description => "example@stripe.com"},
      {:stripe_account => CONNECTED_STRIPE_ACCOUNT_ID}
    )
    
    # Fetching an account just needs the ID as a parameter
    Stripe::Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID)
    
    stripe.api_key = PLATFORM_SECRET_KEY
    stripe.Customer.create(
      description="example@stripe.com",
      stripe_account=CONNECTED_STRIPE_ACCOUNT_ID
    )
    
    # Fetching an account just needs the ID as a parameter
    stripe.Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID)
    
    \Stripe\Stripe::setApiKey(PLATFORM_SECRET_KEY);
    \Stripe\Customer::create(
      array("description" => "example@stripe.com"),
      array("stripe_account" => CONNECTED_STRIPE_ACCOUNT_ID)
    );
    
    // Fetching an account just needs the ID as a parameter
    \Stripe\Account::retrieve(CONNECTED_STRIPE_ACCOUNT_ID);
    
    Stripe.apiKey = PLATFORM_SECRET_KEY;
    RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build();
    
    Map<String, Object> customerParams = new HashMap<String, Object>();
    customerParams.put("description", "example@stripe.com");
    
    Customer.create(customerParams, requestOptions);
    
    // Fetching an account just needs the ID as a parameter
    Account.retrieve(CONNECTED_STRIPE_ACCOUNT_ID);
    
    var stripe = require('stripe')(PLATFORM_SECRET_KEY);
    stripe.customers.create(
      {description: "example@stripe.com"},
      {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID}
    );
    
    // Fetching an account just needs the ID as a parameter
    stripe.accounts.retrieve(CONNECTED_STRIPE_ACCOUNT_ID);
    

    Authentication via API keys

    The second authentication option uses the connected account’s secret and publishable keys instead. Here is the same refund request as above performed using this second authentication method:

    curl https://api.stripe.com/v1/charges/{CHARGE_ID}/refunds \
       -u {CONNECTED_ACCOUNT_SECRET_KEY}: \
       -d amount=1000
    

    The connected account’s secret key can either be provided by the account creation’s API call under keys[secret], or an access_token, provided by the OAuth flow.

    You’d only want to use this authentication method if you intend to make the key accessible to the account holder. For example, if you created a mobile application that talks directly to Stripe, you would not want to store your secret key in the application (as then any user would be able to extract your key and use it to access any other user’s account). Instead you should send the account-specific secret key to the application, as it only allows access to the account holder’s account.

    If you are using this method, we recommend that you perform authentication with every request, instead of setting the API key globally.

    # Not recommended: setting global API key state
    Stripe.api_key = CONNECTED_ACCOUNT_SECRET_KEY
    Stripe::Customer.create(
      :description => "example@stripe.com"
    )
    
    # Recommended: sending API key with every request
    Stripe::Customer.create(
      {:description => "example@stripe.com"},
      :api_key => CONNECTED_ACCOUNT_SECRET_KEY # account's access token from the Connect flow
    )
    
    # Not recommended: setting global API key state
    stripe.api_key = CONNECTED_ACCOUNT_SECRET_KEY
    stripe.Customer.create(
      description="example@stripe.com"
    )
    
    # Recommended: sending API key with every request
    stripe.Customer.create(
      description="example@stripe.com",
      api_key=CONNECTED_ACCOUNT_SECRET_KEY # account's access token from the Connect flow
    )
    
    // Not recommended: setting global API key state
    \Stripe\Stripe::setApiKey(CONNECTED_ACCOUNT_SECRET_KEY);
    \Stripe\Customer::create(
      array("description" => "example@stripe.com")
    );
    
    // Recommended: sending API key with every request
    \Stripe\Customer::create(
      array("description" => "example@stripe.com"),
      array("api_key" => CONNECTED_ACCOUNT_SECRET_KEY) // account's access token from the Connect flow
    );
    
    // Not recommended: setting global API key state
    Stripe.apiKey = CONNECTED_ACCOUNT_SECRET_KEY;
    
    Map<String, Object> customerParams = new HashMap<String, Object>();
    customerParams.put("description", "example@stripe.com");
    
    Customer.create(customerParams);
    
    // Recommended: sending API key with every request
    RequestOptions requestOptions = RequestOptions.builder().setApiKey(CONNECTED_ACCOUNT_SECRET_KEY).build();
    
    Map<String, Object> customerParams = new HashMap<String, Object>();
    customerParams.put("description", "example@stripe.com");
    
    Customer.create(customerParams, requestOptions);
    
    // Not recommended: setting global API key state
    var stripe = require('stripe')(CONNECTED_ACCOUNT_SECRET_KEY);
    stripe.customers.create({
      description: "example@stripe.com"
    });
    
    // Recommended: sending API key with every request
    stripe.customers.create(
      { description: "example@stripe.com" },
      { api_key: CONNECTED_ACCOUNT_SECRET_KEY } // account's access token from the Connect flow
    );
    

    Webhooks

    You’ll use webhooks to be notified about events that happen in a Stripe account. Your webhook URLs, which receive the event notifications, are configured in your webhook settings.

    Note that there are two types of webhooks:

    • Account webhooks are for activity on your own account (e.g., most requests made using your API keys and without authenticating as another Stripe account).
    • Connect webhooks are for activity on any connected account. This includes the important account.updated event for any connected accounts.

    For Connect webhooks, it’s important to note that while only test webhooks will be sent to your development webhook URLs, both live and test webhooks will be sent to your production webhook URLs. This is due to the fact that you can perform both live and test transactions under a production application. For this reason, we recommend you check the livemode value when receiving an event webhook to know what action, if any, should be taken.

    In addition to the documented response properties in the event object reference, each event for a connected account will also contain a top-level user_id property. It identifies the user for whom the webhook is being sent.

    {
      "id": "evt_gB7L7njJbWfPQG",
      "livemode": true,
      "object": "event",
      "type": "customer.created",
      "user_id": "acct_5ua8PzyHulBNMp",
      "pending_webhooks": 2,
      "created": 1349654313,
      "data": {...}
    }

    For more information about webhooks, see the webhook documentation or event object reference.

    After authenticating

    Check out the rest of the guide to learn how to perform actions on behalf of your users.