--- title: "Setup and payments" description: "Implement your app's payments and pricing model" --- import CreatePlans from "/snippets/create-plans.mdx"; In this example we'll create the pricing for a premium AI chatbot. We're going to have: - A Free plan that gives users 5 chat messages per month for free - A Pro plan that gives users 100 chat messages per month for $20 per month. {/* REACT DOCS */} Autumn's client-side [hooks](/react/hooks/useCustomer) are supported for fullstack TypeScript apps. Please use the Server SDK for other frameworks. ### Create your pricing plans Create a plan for each pricing tier that your app offers. In our example we'll create a "Free" and "Pro" plan, and assign them features. ### Installation [Create an Autumn Secret key](https://app.useautumn.com/sandbox/dev?tab=api_keys), and paste it in your `.env` variables. Then, install the Autumn SDK. If you're using the CLI, this will be done for you. ```bash .env AUTUMN_SECRET_KEY=am_sk_test_42424242... ``` ```bash bun bun add autumn-js ``` ```bash npm npm install autumn-js ``` ```bash pnpm pnpm add autumn-js ``` ```bash yarn yarn add autumn-js ``` If you're using a separate backend and frontend, make sure to install the library in both. ### Add Endpoints Server-side Server-side, mount the Autumn handler. This will create endpoints in the `/api/autumn/*` path, which will be called by Autumn's frontend React hooks. These endpoints in turn call Autumn's API. The handler takes in an `identify` function where you should pass in the user ID or organization ID from your auth provider. ```typescript Next.js // app/api/autumn/[...all]/route.ts import { autumnHandler } from "autumn-js/next"; import { auth } from "@/lib/auth"; export const { GET, POST } = autumnHandler({ identify: async (request) => { // get the user from your auth provider (example: better-auth) const session = await auth.api.getSession({ headers: request.headers, }); return { customerId: session?.user.id, // or org ID customerData: { name: session?.user.name, email: session?.user.email, }, }; }, }); ``` ```typescript Hono // index.ts import { autumnHandler } from "autumn-js/hono"; app.use( "/api/autumn/*", autumnHandler({ identify: async (c: Context) => { // get the user from your auth provider (example: better-auth) const session = await auth.api.getSession({ headers: c.req.raw.headers, }); return { customerId: session?.user.id, customerData: { name: session?.user.name, email: session?.user.email, }, }; }, }), ); ``` ```typescript Express import express from "express"; import { autumnHandler } from "autumn-js/express"; const app = express(); // Body parser is required before the Autumn handler app.use(express.json()); app.use( "/api/autumn", autumnHandler({ identify: async (req) => { // get the user from your auth provider (example: better-auth) const session = await auth.api.getSession({ headers: req.headers, }); return { customerId: session?.user.id, customerData: { name: session?.user.name, email: session?.user.email, }, }; }, }), ); ``` ```typescript Web Standard (Elysia, CF Workers, etc...) // Works with any fetch()-compatible WinterTC environment import { autumnHandler } from "autumn-js/fetch"; import { Elysia } from "elysia"; const app = new Elysia() .mount( autumnHandler({ identify: async (request) => { // get the user from your auth provider (example: better-auth) const session = await auth.api.getSession({ headers: request.headers, }); return { customerId: session?.user.id, customerData: { name: session?.user.name, email: session?.user.email, }, }; }, }), ) .listen(3002); ``` ```typescript General (framework-agnostic) // For any framework not listed above import { autumnHandler } from "autumn-js/backend"; // Call this from your route handler const result = await autumnHandler({ request: { url: request.url, // Full URL or path (e.g., "/api/autumn/customer") method: request.method, body: await request.json(), }, customerId: session?.user.id, customerData: { name: session?.user.name, email: session?.user.email, }, }); // Return the response return new Response(JSON.stringify(result.response), { status: result.statusCode, headers: { "Content-Type": "application/json" }, }); ``` Autumn's customer ID is the same as your internal user or org ID generated from your auth provider. No need to store any extra IDs. ### Add Provider Client-side Client side, wrap your application with the `` component. ```jsx // layout.tsx import { AutumnProvider } from "autumn-js/react"; export default function RootLayout({ children }: { children: React.ReactNode, }) { return ( {children} ); } ``` ### Create an Autumn customer From a frontend component, use the [`useCustomer()` hook](/react/hooks/useCustomer). This will automatically create an Autumn customer if they're a new user and enable the Free plan for them, or get the customer's state for existing users. ```jsx React import { useCustomer } from "autumn-js/react"; const App = () => { const { data } = useCustomer(); console.log("Autumn customer:", data); return

My very profitable app

; }; ``` ```json expandable { "id": "user_123", "createdAt": 1764932560414, "name": "My First Customer", "email": null, "fingerprint": null, "stripeId": null, "env": "sandbox", "metadata": {}, "sendEmailReceipts": false, "subscriptions": [ { "planId": "free", "autoEnable": true, "addOn": false, "status": "active", "pastDue": false, "canceledAt": null, "expiresAt": null, "trialEndsAt": null, "startedAt": 1764932560519, "currentPeriodStart": null, "currentPeriodEnd": null, "quantity": 1 } ], "purchases": [], "balances": { "messages": { "featureId": "messages", "granted": 5, "remaining": 5, "usage": 0, "unlimited": false, "overageAllowed": false, "maxPurchase": null, "nextResetAt": 1767610960519 } } } ``` You will see your user under the [customers](https://app.useautumn.com/customers) page in the Autumn dashboard.
### Stripe Payment Flow Call `attach` when the customer wants to purchase the Pro plan. This will return a Stripe payment URL. Once they've paid, Autumn will grant access to "100 messages per month" defined in Step 1. Use Stripe's test card `4242 4242 4242 4242` to make a purchase in sandbox. You can enter any Expiry and CVV. ```jsx React import { useCustomer } from "autumn-js/react"; export default function PurchaseButton() { const { attach } = useCustomer(); return ( ); } ``` This will handle any plan changes scenario (upgrades, downgrades, one-time topups, renewals, etc). Upgrades will happen immediately, and downgrades will be scheduled for the next billing cycle. The **`redirectMode: "always"`** flag will always return a payment URL. New purchases redirect to Stripe Checkout to enter payment details, and subsequent charges redirect to an Autumn hosted, one-click confirmation page. You can build your own billing confirmation flows by using the [previewAttach](/api-reference/billing/previewAttach) function.
{/* SERVER SDK DOCS */} ### Create your pricing plans Create a plan for each pricing tier that your app offers. In our example we'll create a "Free" and "Pro" plan, and assign them features. ### Installation [Create an Autumn Secret key](https://app.useautumn.com/sandbox/dev?tab=api_keys), and paste it in your `.env` variables. Then, install the Autumn SDK. If you're using the CLI, this will be done for you. ```bash .env AUTUMN_SECRET_KEY=am_sk_test_42424242... ``` ```bash bun bun add autumn-js ``` ```bash npm npm install autumn-js ``` ```bash pnpm pnpm add autumn-js ``` ```bash yarn yarn add autumn-js ``` ```bash pip pip install autumn-sdk ``` ### Create an Autumn customer When the customer signs up, create an Autumn customer for them. Autumn will automatically enable the Free plan, since you marked it with the `auto-enable` flag. ```typescript TypeScript import { Autumn } from "autumn-js"; const autumn = new Autumn({ secretKey: "am_sk_42424242", }); const customer = await autumn.customers.getOrCreate({ customerId: "user_or_org_id_from_auth", name: "John Doe", email: "john@example.com", }); ``` ```python Python import asyncio from autumn_sdk import Autumn autumn = Autumn('am_sk_42424242') async def main(): customer = await autumn.customers.get_or_create( customer_id="user_or_org_id_from_auth", name="John Doe", email="john@example.com", ) asyncio.run(main()) ``` ```bash cURL curl --request POST \ --url https://api.useautumn.com/v1/customers \ --header 'Authorization: Bearer am_sk_42424242' \ --header 'Content-Type: application/json' \ --data '{ "customer_id": "user_or_org_id_from_auth", "name": "John Doe", "email": "john@example.com" }' ``` Autumn's customer ID is the same as your internal user or org ID generated from your auth provider. No need to store any extra IDs. In the Autumn dashboard, you will see your user under the [customers](https://app.useautumn.com/customers) page. ### Stripe Payment Flow Call `attach` when the customer wants to purchase the Pro plan. This will return a Stripe payment URL. Once they've paid, Autumn will grant access to "100 messages per month" defined in Step 1. ```typescript TypeScript import { Autumn } from "autumn-js"; const autumn = new Autumn({ secretKey: "am_sk_42424242", }); const response = await autumn.billing.attach({ customerId: "user_or_org_id_from_auth", planId: "pro", redirectMode: "always", }); // Redirect customer to complete payment or confirm plan change redirect(response.paymentUrl); ``` ```python Python import asyncio from autumn_sdk import Autumn autumn = Autumn('am_sk_42424242') async def main(): response = await autumn.billing.attach( customer_id='user_or_org_id_from_auth', plan_id='pro', redirect_mode='always', ) asyncio.run(main()) ``` ```bash cURL curl -X POST 'https://api.useautumn.com/v1/attach' \ -H 'Authorization: Bearer am_sk_42424242' \ -H 'Content-Type: application/json' \ -d '{ "customer_id": "user_or_org_id_from_auth", "plan_id": "pro", "redirect_mode": "always" }' ``` Use Stripe's test card `4242 4242 4242 4242` to make a purchase in sandbox. You can enter any Expiry and CVV. This can be used for any plan changes scenario (upgrades, downgrades, one-time topups, renewals, etc). Upgrades will happen immediately, and downgrades will be scheduled for the next billing cycle. The **`redirectMode: "always"`** flag will always return a payment URL. New purchases redirect to Stripe Checkout to enter payment details, and subsequent charges redirect to an Autumn hosted, one-click confirmation page. You can build your own billing confirmation flows by using the [previewAttach](/api-reference/billing/previewAttach) function. **Next: Track and limit usage** Now that the plan is enabled and you've handled payments, you can now make sure that customers have the access to the right features and limits based on their plan. Enforce usage limits and feature permissions using Autumn's `check` and `track` functions