1---
2title: Stripe
3description: Sell subscriptions and onboard merchants from a Cloudflare Worker — catalog, Checkout, the Billing Portal, Connect, and webhooks declared next to the code that uses them.
4---
5
6Stripe with alchemy means your billing lives in the same TypeScript
7program as the app that does the billing. The `Product` and `Price`
8are declared on the Worker that sells them. The Worker calls Stripe
9through typed bindings that carry their own permissions. Webhooks are
10one function call that provisions the endpoint and hands your handler
11a typed event. `bun alchemy deploy` ships all of it; `alchemy destroy`
12takes it down without leaving orphans in the Dashboard.
13
14New here? [Set up credentials](/stripe/setup), then pick the guide
15that matches what you're building.
16
17## What are you building?
18
19- **A SaaS that charges monthly** →
20 [Sell a subscription](/stripe/guides/subscriptions). Hosted Checkout,
21 the Billing Portal, and an entitlement record kept current by
22 webhooks. One Worker, one KV namespace.
23- **A platform that pays other businesses** →
24 [Onboard merchants with Connect](/stripe/guides/connect). Express
25 accounts, hosted onboarding with link refresh, and `account.updated`
26 driving a D1 merchant table.
27- **Anything that needs to know what Stripe did** →
28 [React to Stripe events](/stripe/guides/webhooks). Which events, how
29 `consumeEvents` works, when to declare the endpoint yourself.
30
31Both guides walk a runnable example under `examples/` end to end and
32end with the full source.
33
34## What it looks like
35
36```typescript
37// src/Api.ts
38export default class Api extends Cloudflare.Worker<Api>()(
39 "Api",
40 { main: import.meta.url },
41 Effect.gen(function* () {
42 // Catalog — deployed with the Worker.
43 const product = yield* Stripe.Product("Pro", { name: "Pro" });
44 const price = yield* Stripe.Price("ProMonthly", {
45 product,
46 currency: "usd",
47 unitAmount: 2000,
48 recurring: { interval: "month" },
49 });
50 const priceId = yield* price.id;
51
52 // Runtime calls — each adds its permission to the Worker's token.
53 const createCustomer = yield* Stripe.CreateCustomer();
54 const createCheckout = yield* Stripe.CreateCheckoutSession();
55
56 // Stripe → app.
57 yield* Stripe.consumeEvents(
58 "Events",
59 { events: [Stripe.CustomerSubscriptionCreated] },
60 Effect.fn(function* (event) {
61 yield* Effect.log(`${event.object.customer} subscribed`);
62 }),
63 );
64
65 return {
66 fetch: Effect.gen(function* () {
67 const customer = yield* createCustomer({ email: "a@example.com" });
68 const session = yield* createCheckout({
69 mode: "subscription",
70 customer: customer.id,
71 line_items: [{ price: yield* priceId, quantity: 1 }],
72 success_url: "https://example.com/welcome",
73 cancel_url: "https://example.com/pricing",
74 });
75 return HttpServerResponse.redirect(session.url!);
76 }).pipe(Effect.orDie),
77 };
78 }).pipe(
79 Effect.provide([
80 Stripe.CreateCustomerHttp,
81 Stripe.CreateCheckoutSessionHttp,
82 Stripe.ConsumeEventsLive,
83 ]),
84 ),
85) {}
86```
87
88Three ideas carry the whole integration:
89
90- **Resources** (`Product`, `Price`, `Coupon`, `WebhookEndpoint`,
91 `BillingPortalConfiguration`, …) are Stack-managed. Alchemy creates,
92 updates, and deletes them. Objects Stripe won't hard-delete are
93 deactivated instead.
94- **Bindings** (`CreateCustomer`, `CreateCheckoutSession`,
95 `RetrieveProduct`, …) are what a Worker calls at runtime. Yielding
96 one registers the permission it needs on a
97 [`RestrictedApiKey`](/providers/stripe/restrictedapikey) and returns
98 a callable. Provide the matching `*Http` layer once at the end.
99- **Outputs** like `price.id` are yielded at plan time to get an
100 accessor, then yielded again inside a route. That's how a resource
101 id reaches runtime.
102
103## Reference
104
105[Product](/providers/stripe/product) ·
106[Price](/providers/stripe/price) ·
107[Coupon](/providers/stripe/coupon) ·
108[Customer](/providers/stripe/customer) ·
109[BillingPortalConfiguration](/providers/stripe/billingportalconfiguration) ·
110[WebhookEndpoint](/providers/stripe/webhookendpoint) ·
111[RestrictedApiKey](/providers/stripe/restrictedapikey)
112
113The full list is under **Resources** in the sidebar.