Building an Integration

A start-to-finish guide that helps you build a Stripe integration. Browse the Works with Stripe gallery to discover hundreds of applications and services that already integrate with Stripe.

Introduction

Hundreds of thousands of businesses use Stripe to build and manage their internet business. Collectively, they accept billions of dollars in payments every year. While Stripe offers users hundreds of features, there’s some capabilities we don’t offer out of the box—that’s where you come in! By building an integration on top of Stripe, our network of businesses can use your products instantly and seamlessly. If you’d like to build a useful integration for all Stripe users, this guide covers the process from start to finish.

Integrations on Stripe range from simple tools to calculate taxes and shipping to fully-featured analytics platforms that calculate churn rates, ARR, MRR, and more.

Use cases

This guide is primarily useful for developers that want to build pre-built integrations to extend Stripe’s feature set (such as integrations for accounting, analytics and notifications, inventory management, sending emails, card readers, shipping, tax calculations, and more). Some example integrations include Baremetrics, CardFlight, Zapier, and EasyPost.

It should also prove useful for integrations that help non-technical users get started in accepting payments online, such as services to collect donations, or for setting up subscriptions or invoicing for small businesses. Some example integrations include Chargify, Invoice2Go, DonorBox, and Wufoo.

Getting started

It’s easy to get started with a simple OAuth 2.0 flow to connect to Stripe accounts. Optionally, you can request permissions to take actions on behalf of Stripe accounts. Stripe will automatically send webhooks to signal changes in accounts that connect to your integration. You also have the flexibility to set your own pricing and offer your integration for free, charge a per-transaction fee, or subscribe users to a recurring plan.

Once you’re ready to launch, we’ll be happy to feature you in our Works with Stripe gallery so that businesses on Stripe can discover and start using your integration.

OAuth workflow

We offer a standard OAuth 2.0 flow for you to connect to Stripe accounts. As part of this OAuth flow, you will need to create two pages on your website:

  • A start page that begins the connection process (i.e., where the user goes to connect to your integration).
  • A destination page to which the user will be redirected after connecting their Stripe account.

Once the OAuth flow is successfully completed, you will be able to use the Stripe API on behalf of your user’s account.

Registering your application

The first thing you need to do is register your platform with Stripe. We only ask you to complete a couple details about your application in the “Standalone accounts” section:

Your logo will be shown to users when linking their Stripe account to your application, and your icon will be displayed in their list of connected applications.

To get started with your integration, you will need two key pieces of information displayed just below:

  • Your client_id, a unique identifier for your platform, generated by Stripe.
  • Your redirect_uri, a page on your website to which the user will be redirected after connecting their account (or failing to, should that be the case), set by you.

Stripe provides a development client_id and lets you define a different redirect_uri for development, to make testing easier.

Connecting accounts

With these two pieces of information in hand, you’re ready to have your users link their Stripe account with your application.

We support connections under two different scopes: read_only, which is the default option, and read_write.

  • If you’re building an application only reading data from Stripe, you’ll want to request read_only. This permission type allows you to read data from the user’s account, but not create charges or transfers: you can see the money moving around, but not move it yourself.
  • If you’re building an application that needs to perform any actions on behalf of the connected user, you’ll want to request read_write scope instead. See the OAuth reference for more information.

We recommend showing a Connect with Stripe button that sends them to our authorize_url endpoint:

https://connect.stripe.com/oauth/authorize?response_type=code&client_id=ca_32D88BD1qLklliziD7gYQvctJIhWBSQ7&scope=read_only

Here is how your button may look (the href value matches that above):

Connect with Stripe

The user will be taken to a page like this to review the requested permissions and link their account:

At the end of the OAuth workflow, you’ll be provided with authorization credentials for the user’s account:

{
  ...
  "stripe_user_id": "acct_AMSU7Dz8dTFlII",
  ...
}

You’ll want to store the stripe_user_id on your side, as this is used to identify the account.

Using the Stripe-Account header

In order to perform API requests on behalf of this user’s account, all you will need is your platform account secret key, and a Stripe-Account header identifying the account for which the request is being made.

All of Stripe’s libraries support this style of authentication on a per-request basis, and we listed examples of use cases in the two following sections:

  1. Viewing and manipulating data
  2. Performing actions on behalf of Stripe accounts

Viewing and manipulating data

Whether you’re building an analytics or custom reporting integration, or any application on top of Stripe data, this section is for you. A few examples of what you can build by simply requesting the read_only scope are:

  • Trend identification, such as sales by weekday.
  • Percentage reporting, like how many charges are authorized but not captured or captured and later refunded.
  • Aggregation, such as the total fees paid within a period.
  • Custom accounting, for example, showing the difference between the cash on hand and the transfers pending.
  • Tax reporting, watching sales by geographic location.

Fetching data

Once a user links their Stripe account to your application, you have the ability to perform API requests on behalf of their Stripe account. Generally speaking, you can perform nearly any kind of request, but when granted a read_only scope, your integration is restricted to GET requests: fetching individual objects (e.g., a single charge) or lists of objects. This means that you can, through the API, make “list all” requests to fetch a connected user’s data such as listing customers or transactions.

Let’s try it out by fetching charges for a connected Stripe account. By only passing the account ID, that request would return by default the 10 most recent charges. Taking this further, you can use the created parameter to filter what transactions are returned, and paginate the request using the limit, ending_before, and starting_after parameters.

As an example of that, this request will fetch the first 50 charges starting at the beginning of the year:

# 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"

Stripe::Charge.list(
  {
    :limit => 50,
    :created => {"lte": 1451606400}
  },
  {:stripe_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"

stripe.Charge.list(
  limit=50,
  created={"lte": 1451606400},
  stripe_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");

\Stripe\Charge::all(
  array(
    "limit" => 50,
    "created" => array("lte" => 1451606400)
  ),
  array("stripe_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";

RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build();

Map<String, Object> chargeParams = new HashMap<String, Object>();
chargeParams.put("limit", 50);
chargeParams.put("created", {"lte": 1451606400});

Charge.list(chargeParams, requestOptions);
// 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.charges.list(
  {
    limit: 50,
    created: {lte: 1451606400}
  },
  {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID}
);

The response will look something like this:

{
  "object": "list",
  "url": "/v1/charges",
  "has_more": true,
  "data": [
  ]
  ...
}

All of the charges will be within the data attribute, which you can loop through. You could then use the final charge in that group as the after value in the request to retrieve the next 50 charges. (See the list all charges documentation.)

Although the API was designed for performance, repeatedly fetching large bodies of data will undoubtedly hurt the responsiveness of your application. We recommended storing fetched data on your side for subsequent analysis and reporting.

Getting real-time data

In addition to fetching historical data, you can also access data via webhooks. Once you’ve defined a platform webhook URL in your account, Stripe will send event notifications to your webhook URL for every connected account. Look at the event object’s user_id property to see the account on which the event occurred.

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

The above event shows that a customer was created in the acct_AMSU7Dz8dTFlII account. Again, we recommend storing these events locally for subsequent analysis and reporting. By watching for events as they occur, your application won’t require repeated and laborious API requests to fetch previous data.

Performing actions on behalf of Stripe accounts

This section is for you if you’re looking to extend Stripe’s functionality and perform actions on behalf of users’ accounts. You’ll need a read_write access to Stripe accounts to be able to perform any POST (or DELETE) API requests (e.g. creating customer objects or updating subscriptions).

The authentication works exactly the same way by passing your secret key along with the Stripe-Account header to identify the account on which you’d like to perform actions.

Here is for instance the code to create a new customer on a user’s Stripe account:

# 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"

Stripe::Customer.create(
  {
    :description => "Jenny Rosen",
    :email => "jenny@example.com"
  },
  {:stripe_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"

stripe.Customer.create(
  description="Jenny Rosen",
  email="jenny@example.com",
  stripe_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");

\Stripe\Customer::create(
  array(
    "description" => "Jenny Rosen",
    "email" => "jenny@example.com"
  ),
  array("stripe_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";

RequestOptions requestOptions = RequestOptions.builder().setStripeAccount(CONNECTED_STRIPE_ACCOUNT_ID).build();

Map<String, Object> customerParams = new HashMap<String, Object>();
customerParams.put("description", "Jenny Rosen");
customerParams.put("email", "jenny@example.com");

Customer.create(customerParams, requestOptions);
// 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.customers.create(
  {
    description: "Jenny Rosen",
    email: "jenny@example.com"
  },
  {stripe_account: CONNECTED_STRIPE_ACCOUNT_ID}
);

Now that you know how to identify a user account in any requests, check out our product guides as well as our reference to learn more about the objects and methods that you can use to build your integration.

Charging for your application

Even if you have requested, appropriately, a read_only connection, it’s still easy to accept payments for your application: your platform’s Stripe account can be used to process its own charges. After your customers connect their Stripe accounts, ask for their payment details and then create a subscription for them in your Stripe account. Store the created customer ID with the associated Stripe ID, and you’ll easily be able to see which of your users are paid and active, and which are not.

If you are creating subscriptions, you can also specify an application_fee_percent as a fee for your application, on top of any Stripe fees charged. Read more on how to implement this.

While you’re at it, you can even run your Stripe account’s data through your integration code to parse how your own business is growing or test your functionality against your real account!

Disconnecting accounts

At any point in time, a connected user can disconnect their account from your integration. When that occurs, you’ll receive an account.application.deauthorized event notification at your webhook URL. You can use this notification to perform any necessary clean up on your end, such as disabling the user’s account (on your site) and removing their data.

You can also disconnect an account from your integration by making a request to the OAuth deauthorization endpoint.

The Works with Stripe gallery showcases hundreds of applications and services already integrated with Stripe. To be included, we’ll need some basic information about your integration, as well as your logo and a few screenshots.

Ready for prime-time? Get in touch to be featured in our Works with Stripe gallery.