# Connect Stripe

An account of Stripe is connected once, on the instance, by a person who then gives missions access to its resources; the agent never receives the credential. Billing operations on a Stripe account : catalog, customers, subscriptions, invoices, refunds, payouts, webhooks — test and live modes as separate resources.

One account is one Stripe account, given as a test key, a live key, or both; each mode is its own resource, labelled test or live by the plugin. Every permission is held per mode, so a mission can work freely in test mode and touch live billing only within its limits and after your yes.

Permissions, presets and tools of this service: [Stripe plugin](/plugins/stripe).

## How to connect

On the instance: Accounts → Connect an account, then pick the service. A company app, when the service needs one, is registered once by an administrator under Settings → Administration → Company apps, or set in the configuration (`providers.<id>.*`, see [configuration keys](/docs/configuration/keys)). Every instance registers its own app: this gateway never uses an app shared with another one.

### The usual way: with a key pasted by hand

Where: [https://dashboard.stripe.com/apikeys](https://dashboard.stripe.com/apikeys)

What the connect page asks:

- Test-mode key (secret): Key of the sandbox. Leave empty for a live-only account. A restricted key (rk\_…) limited to the objects you expect the agent to touch is preferable to the full secret key (sk\_…).
- Live-mode key (secret): Key of the live account (real money). Leave empty for a test-only account. A restricted key (rk\_…) limited to the objects you expect the agent to touch is preferable to the full secret key (sk\_…).

## Disconnecting

Delete or roll the API key in the Stripe Dashboard, under Developers, API keys.

## Registration notes from the plugin

From the plugin's [README](https://github.com/vaubaan/gateway/blob/main/plugins/stripe/README.md), written for the people who register the app or create the token.

### Credential and resources

Kind `api-key`, two optional secret fields; at least one must be filled:

| Field      | Pattern                        | Purpose                                |
| ---------- | ------------------------------ | -------------------------------------- |
| `test_key` | `^(sk\|rk)_test_[A-Za-z0-9]+$` | Sandbox key (`sk_test_…`, `rk_test_…`) |
| `live_key` | `^(sk\|rk)_live_[A-Za-z0-9]+$` | Live key (`sk_live_…`, `rk_live_…`)    |

There is no company-registered app for Stripe: the owner creates the keys
in the Stripe dashboard (`https://dashboard.stripe.com/apikeys`) and pastes
them. A restricted key (`rk_…`) limited to the objects the agent should
touch is preferable to the full secret key.

`discoverResources` calls `GET /v1/account` once per key present and
returns **one resource per mode**:

```ts
{ provider: 'stripe', ref: 'acct_1A2B/live', env: 'live', displayName: 'Acme (live)',
  metadata: { account_id: 'acct_1A2B', mode: 'live' } }
```

The mode is in the ref, in `metadata.mode` and in `env`. `execute` picks the
key from the ref / metadata, never from the env label, so relabelling the
environment cannot switch keys — and the classifier refuses a resource whose
label is not its mode, or whose mode cannot be read, so a live call is never
judged under a `stripe[test].*` risk. A key pasted in the wrong field
(`sk_live_…` as `test_key`) is refused before any call; a credential with
no key at all fails discovery.
