# How to create OAuth credentials for Stripe

The Apideck Stripe connector authenticates through a **Stripe App that you build and own**, with OAuth enabled. Your consumers install that app on their own Stripe account, and Apideck exchanges the resulting authorization code for tokens on your behalf.

Obtaining the credentials is therefore a small build rather than a portal form: you create the app with the Stripe CLI, set a few fields in its manifest, upload it, and then copy three values into the [Apideck Stripe connector settings](https://platform.apideck.com/configuration/accounting/stripe).

Apideck publishes a working reference app you can copy from: [apideck-samples/stripe-app](https://github.com/apideck-samples/stripe-app).

## Before you start

You will need:

- A **Stripe account**. Sign up free at [dashboard.stripe.com/register](https://dashboard.stripe.com/register). Publishing to the Stripe App Marketplace later additionally requires an [activated account](https://docs.stripe.com/get-started/account/set-up), and a Connect platform account cannot publish (see **Scaling beyond external testing**), so pick the owning account with that in mind.
- A developer (or a developer's help) and the local tooling Stripe requires for Stripe Apps: the **Stripe CLI**, Node.js and pnpm. Stripe lists the current prerequisites and supported versions on [Getting started with Stripe Apps](https://docs.stripe.com/stripe-apps/create-app) and the [Stripe CLI install page](https://docs.stripe.com/stripe-cli).
- Access to your Apideck Dashboard to save the credentials.

## 1. Install the Stripe CLI and the Apps plugin

Install the [Stripe CLI](https://docs.stripe.com/stripe-cli), then log in so the CLI is paired with your Stripe account:

```bash
stripe login
```

Stripe Apps commands come from CLI plugins, so install both the `apps` plugin and the `generate` plugin Stripe now uses to scaffold new apps:

```bash
stripe plugin install apps
stripe plugin install generate
```

Stripe documents the exact prerequisites and any additional plugins on [Getting started with Stripe Apps](https://docs.stripe.com/stripe-apps/create-app). Follow that page rather than pinning tool versions, since Stripe moves them regularly.

## 2. Create the app

```bash
stripe generate app your-app-name
```

Stripe's OAuth guide still shows the previous form `stripe apps create your-app-name`; follow the [Getting started with Stripe Apps](https://docs.stripe.com/stripe-apps/create-app) page, which is the current one. The CLI prompts for two things:

- **ID**: how Stripe identifies your app. It must be globally unique.
- **Display name**: the name Stripe displays for your app. Pick something your consumers will recognise as yours; Stripe lets you change the name later.

If you intend to publish the app on the Stripe App Marketplace at any point, note Stripe's naming rules for public apps (see **Scaling beyond external testing** below).

## 3. Configure the manifest for OAuth

Open the generated `stripe-app.json` and set the following fields. The first three turn an ordinary Stripe App into one Apideck can authenticate through; the fourth is optional:

| Manifest field | Value | Why |
|---|---|---|
| `stripe_api_access_type` | `"oauth"` | Makes the app authenticate through OAuth instead of only running inside the Dashboard. |
| `distribution_type` | `"public"` | Required for OAuth apps. It makes OAuth installation possible; it does **not** publish the app or list it anywhere. |
| `allowed_redirect_uris` | must include `"https://unify.apideck.com/vault/callback"` | Where Stripe returns the consumer after they install the app. |
| `sandbox_install_compatible` | `true` | Only needed if you want the app to be installable in Stripe sandboxes. |

**Redirect URL.** The value Apideck listens on is always:

```
https://unify.apideck.com/vault/callback
```

Stripe uses the **first** entry in `allowed_redirect_uris` as the default redirect, so list the Apideck callback first. The [sample app's manifest](https://github.com/apideck-samples/stripe-app/blob/main/stripe-app.json) does exactly that. Stripe also requires live-mode redirect URIs to use HTTPS, which the Apideck callback does.

Stripe's own field-by-field reference is [Stripe Apps: OAuth 2.0](https://docs.stripe.com/stripe-apps/api-authentication/oauth) and the [app manifest reference](https://docs.stripe.com/stripe-apps/reference/app-manifest).

## 4. Grant the permissions the connector needs

Stripe Apps declare their access as a list of `permissions` in the manifest, and the consumer sees that list on the install screen. Stripe Apps OAuth has no per-request scopes, so **whatever the manifest declares is what the connection can do**: a permission you leave out becomes a failing call later, and adding one afterwards means uploading a new version of the app and asking your users to re-authorise it.

Broadly, the connector needs read and write access to the Stripe resources it maps (customers, invoices, invoice items, products, credit notes, charges and payment intents, refunds, tax rates), read access to the account itself, and the ability to manage webhook endpoints so Apideck can register event subscriptions for each connection.

Rather than assembling that list by hand, copy the `permissions` array from the [sample app's manifest](https://github.com/apideck-samples/stripe-app/blob/main/stripe-app.json), which is the working reference for this connector. Stripe's [permissions reference](https://docs.stripe.com/stripe-apps/reference/permissions) documents what each individual permission grants if you want to trim the list for your own use case.

## 5. Upload the app

```bash
stripe apps upload
```

Each upload creates a new version of the app. You will select a version when you set up the install link in the next step, so re-upload whenever you change permissions or redirect URIs, and then point the link at the new version.

## 6. Get your install link and the three Apideck values

The install link the connector uses comes from the app's **External test** tab.

1. In the [Stripe Dashboard](https://dashboard.stripe.com), open **Developers** → **Apps** and select your app.
2. Open the **External test** tab and click **Get started**.
3. Choose **Link access** (anyone with the link, or only people you invite) and select the app version to serve.
4. Save. Stripe now shows install links under **Test OAuth**, with separate links for live mode, test mode and sandboxes.
5. Copy the link for the mode you want to configure. It looks like this:

```
https://marketplace.stripe.com/oauth/v2/chnlink_XXXXXXXX/authorize?client_id=ca_XXXXXXXX
```

Two of the three values you need are inside that link. Then open the [Apideck Stripe connector settings](https://platform.apideck.com/configuration/accounting/stripe) and fill in, under **OAuth Configuration**:

| Apideck Dashboard field | What to enter | Where it comes from |
|---|---|---|
| **Client ID** | `ca_...` | The `client_id` query parameter of the install link. |
| **Client Secret** | `sk_test_...` or `sk_live_...` | Your Stripe **secret API key**, from **Developers** → **API keys**. Not a value from the link. |
| **Channel Link ID** | `chnlink_...` | The path segment of the install link between `/oauth/v2/` and `/authorize`. |

**The Client Secret is a secret key, not an app secret.** Stripe's token endpoint authenticates the code exchange with the app developer's secret API key, so that is what Apideck stores in the Client Secret field. Treat it accordingly: it is a full-access credential for your own Stripe account.

Save the configuration. Consumers can now authorize the connector from Vault; they install your app on their Stripe account and are returned to the Apideck callback, and Apideck handles the code exchange and all subsequent token refreshes. There is nothing for a consumer to paste in, and no callback handler for you to build.

## 7. Match the mode of the link and the key

Stripe keeps test-mode, sandbox and live-mode data fully separate, and the code exchange must be authenticated with a key from the **same** mode as the install link.

| Environment | Install link | Client Secret to use |
|---|---|---|
| Test mode | The test-mode link from **Test OAuth** | Your test-mode secret key (`sk_test_...`) |
| Sandbox | The sandbox link from **Test OAuth** (requires `sandbox_install_compatible: true`) | The sandbox's secret key |
| Live mode | The live-mode link from **Test OAuth** | Your live-mode secret key (`sk_live_...`) |

A mismatch (for example a test-mode link with a live-mode key) fails at the token exchange, so the connection never completes. If you want to try the connector before going live, configure the test-mode pair first and switch both values together when you move to live mode.

Keep the secret key you configured valid: Stripe authenticates token refreshes with the same key, so if you roll or delete it, update the **Client Secret** in the Apideck Dashboard at the same time.

## 8. Scaling beyond external testing

External testing is Stripe's distribution route for an app that has not been through review, and Stripe applies its own rules to it:

- **A limit of 25 testers per app.** Each Stripe account that installs your app counts as one tester.
- The app is shown as a **test version**, and Stripe requires you to tell your users that the app is still in development and has not been reviewed by Stripe.

To move past those rules, submit the app to the **Stripe App Marketplace**. Stripe's [publishing guide](https://docs.stripe.com/stripe-apps/publish-app) covers the process; the requirements worth knowing before you build are:

- Stripe reviews the submission and replies with approval or feedback by email; Stripe states this takes **4 business days**.
- Your Stripe account must be [activated](https://docs.stripe.com/get-started/account/set-up), with a verified email address and business details, and your business must not be on Stripe's Prohibited and Restricted Businesses list.
- **A Connect platform account cannot publish an app on the Stripe Marketplace** (stated on Stripe's [Getting started with Stripe Apps](https://docs.stripe.com/stripe-apps/create-app) page). If your company runs a Connect platform, decide up front which Stripe account will own the app.
- **One public app per Stripe account.** Marketplace listings are English only.
- The listed name is limited to 35 characters, **cannot contain** the words *Stripe*, *app*, *free* or *paid*, and must match the manifest `name`.

Any change to the app or its listing after approval means resubmitting for review.

## 9. Webhooks: nothing to register

You do not create webhook endpoints for this connector. Apideck registers the Stripe webhook endpoint for each connection automatically once that connection becomes callable, and removes it when the connection is disabled or deleted. The only thing you have to do is make sure your app's manifest grants the webhook-endpoint permissions (step 4); without them, registration cannot happen.

## FAQ and troubleshooting

**Does `distribution_type: "public"` make my app public?**
No. It is a manifest requirement for OAuth apps and only enables OAuth installation. Your app is not listed anywhere until you submit it to the Stripe App Marketplace and Stripe approves it.

**The install link has no `chnlink_` segment.**
You are looking at the wrong link. The **Settings** tab shows the public Marketplace links (`.../oauth/v2/authorize?client_id=ca_...`), which do not work until the app is published. Take the link from the **External test** tab's **Test OAuth** section instead; that is the one whose path contains the Channel Link ID.

**Authorization fails at the end of the flow.**
Check the three usual causes, in order: the Client Secret is a secret key from the same mode as the install link; `https://unify.apideck.com/vault/callback` is present in `allowed_redirect_uris` in the *uploaded* version of the app (a manifest change only takes effect after `stripe apps upload` and pointing the external-test link at the new version); and the Channel Link ID and Client ID were copied from the same link.

**Who can install the app?**
Stripe requires **administrator** rights on the Stripe account to install a Stripe App, so each tester needs an administrator on their side.

**A tester already has the published version of the app installed.**
Stripe does not allow both at once. The published version has to be uninstalled before the test version can be installed on that account.

**I changed the permissions. Do existing connections get them?**
Not automatically. Stripe moves current testers to the version you select in the External test settings, but when that version changes the permissions, Stripe prompts each user by email and in their Dashboard to re-authorise the app and approve the new permissions. Until they do, calls that need a new permission fail.

**I do not see the External test tab.**
Stripe only shows it for apps with public distribution. Check that `distribution_type` is `"public"` in the uploaded version of the manifest.

Still stuck? Contact [Apideck Support](https://help.apideck.com/en/articles/7774658).

## Learn more

- [Stripe Apps: OAuth 2.0 authentication](https://docs.stripe.com/stripe-apps/api-authentication/oauth)
- [Test your app externally](https://docs.stripe.com/stripe-apps/test-app)
- [Publish an app to the Stripe App Marketplace](https://docs.stripe.com/stripe-apps/publish-app)
- [Stripe Apps permissions reference](https://docs.stripe.com/stripe-apps/reference/permissions)
- [Example Stripe App for Apideck](https://github.com/apideck-samples/stripe-app)
