1---
2title: Setup
3description: Connect alchemy to Stripe — secret key, profiles, CI, and how Worker bindings get their credentials.
4---
5
6## Get a key
7
8Sign up at [stripe.com](https://stripe.com). Every account has a
9**test mode** with its own keys and data — use that for everything
10until you're ready to charge real cards. Copy the test secret key
11(`sk_test_…`) from
12[Developers → API keys](https://dashboard.stripe.com/test/apikeys).
13
14## Register the provider
15
16```typescript
17// alchemy.run.ts
18import * as Alchemy from "alchemy";
19import * as Cloudflare from "alchemy/Cloudflare";
20import * as Stripe from "alchemy/Stripe";
21import * as Effect from "effect/Effect";
22import * as Layer from "effect/Layer";
23
24export default Alchemy.Stack(
25 "MyApp",
26 {
27 providers: Layer.mergeAll(Cloudflare.providers(), Stripe.providers()),
28 state: Alchemy.localState(),
29 },
30 Effect.gen(function* () {
31 // resources go here
32 }),
33);
34```
35
36## Store the key
37
38The first `alchemy deploy` that touches a Stripe resource prompts for
39the key and saves it under `~/.alchemy/credentials/<profile>/`. To set
40it up ahead of time, or to add Stripe to an existing profile:
41
42```sh
43alchemy profile edit --add Stripe
44```
45
46An optional API base URL overrides `https://api.stripe.com` (useful for
47[stripe-mock](https://github.com/stripe/stripe-mock)).
48
49In CI (`CI=true`) profiles are bypassed and alchemy reads
50`STRIPE_API_KEY` from the environment. `STRIPE_API_BASE_URL` is
51optional.
52
53See [Profiles](/environments/profiles) for switching between accounts
54and stages.
55
56## Test mode is real
57
58A `sk_test_…` key talks to a fully working Stripe account. Products,
59Prices, Customers, Checkout Sessions, and webhook deliveries all
60behave exactly as in live mode; the only difference is that cards
61like `4242 4242 4242 4242` succeed and no money moves. Deploy, destroy,
62and redeploy freely.
63
64## How Workers get credentials
65
66A Worker that calls Stripe at runtime needs a key on the host. You
67never wire that up by hand. Each binding you yield —
68`Stripe.CreateCustomer()`, `Stripe.CreateCheckoutSession()`, and so
69on — declares the permission it needs (`customers_write`,
70`checkout_sessions_write`, …) on a
71[`RestrictedApiKey`](/providers/stripe/restrictedapikey) resource
72that alchemy creates per Worker. The key's value is injected as a
73`secret_text` binding.
74
75Today Stripe has no public API for minting restricted keys, so the
76value alchemy injects is your account secret key. The permissions are
77still recorded on the resource, which means:
78
79- you can see exactly which Stripe scopes each Worker uses in the plan
80 output, and
81- if you'd rather the Worker hold a narrower key, create one in
82 [Dashboard → API keys → Restricted keys](https://dashboard.stripe.com/test/apikeys)
83 with those scopes and pass it as `value` — bindings will use it
84 unchanged.
85
86When Stripe ships a mint API the same declarations will drive it with
87no code change in your Worker.
88
89## Enable Connect (platforms only)
90
91If you're going to create connected accounts, Connect must be switched
92on once at
93[dashboard.stripe.com/connect](https://dashboard.stripe.com/test/connect).
94There's no API for that step; `POST /v1/accounts` returns an error
95until it's done.
96
97## Next
98
99- [Sell a subscription](/stripe/guides/subscriptions)
100- [Onboard merchants with Connect](/stripe/guides/connect)