Files
cfw-autumn/apps/docs/mintlify/documentation/getting-started/setup.mdx
mintlify[bot] be628bd2e6 Add Elysia, Express, and Web Standard adapter docs (#987)
* fix: dashboard bugs

* latest

* Add Elysia, Express, and Web Standard adapter docs

Generated-By: mintlify-agent

---------

Co-authored-by: John Yeo <johnyeocx@gmail.com>
Co-authored-by: John Yeo <51376134+johnyeocx@users.noreply.github.com>
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-03-17 13:19:36 +00:00

613 lines
14 KiB
Plaintext

---
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 <Badge color="green">Free</Badge> plan that gives users 5 chat messages per month for free
- A <Badge color="blue">Pro</Badge> plan that gives users 100 chat messages per month for $20 per month.
{/* REACT DOCS */}
<View title="React hooks" icon="react">
<Info>
Autumn's client-side [hooks](/react/hooks/useCustomer) are supported for
fullstack TypeScript apps. Please use the Server SDK for other frameworks.
</Info>
<Steps>
<Step>
### 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.
<CreatePlans />
</Step>
<Step>
### 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...
```
<CodeGroup>
```bash bun
bun add autumn-js
```
```bash npm
npm install autumn-js
```
```bash pnpm
pnpm add autumn-js
```
```bash yarn
yarn add autumn-js
```
</CodeGroup>
<Note>
If you're using a separate backend and frontend, make sure to install the
library in both.
</Note>
</Step>
<Step>
### 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.
<CodeGroup>
```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 Elysia
import { autumnHandler } from "autumn-js/webStandard";
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 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 Elysia
import { autumnHandler } from "autumn-js/webStandard";
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 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 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" },
});
```
</CodeGroup>
<Check>
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.
</Check>
</Step>
<Step>
### Add Provider Client-side
Client side, wrap your application with the `<AutumnProvider>` component.
```jsx
// layout.tsx
import { AutumnProvider } from "autumn-js/react";
export default function RootLayout({ children }: {
children: React.ReactNode,
}) {
return (
<html>
<body>
<AutumnProvider>
{children}
</AutumnProvider>
</body>
</html>
);
}
```
</Step>
<Step>
### 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 <Badge color="green">Free</Badge> 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 <h1>My very profitable app</h1>;
};
```
<Expandable title="data object">
```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
}
}
}
```
</Expandable>
You will see your user under the [customers](https://app.useautumn.com/customers) page in the Autumn dashboard.
</Step>
<Step>
### Stripe Payment Flow
Call `attach` when the customer wants to purchase the <Badge color="blue">Pro</Badge> 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.
<Note>
Use Stripe's test card `4242 4242 4242 4242` to make a purchase in sandbox.
You can enter any Expiry and CVV.
</Note>
```jsx React
import { useCustomer } from "autumn-js/react";
export default function PurchaseButton() {
const { attach } = useCustomer();
return (
<button
onClick={async () => {
await attach({
planId: "pro",
redirectMode: "always",
});
}}
>
Select Pro Plan
</button>
);
}
```
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.
<Note>
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.
</Note>
</Step>
</Steps>
</View>
{/* SERVER SDK DOCS */}
<View title="Server SDK" icon="server">
<Steps>
<Step>
### 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.
<CreatePlans />
</Step>
<Step>
### 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...
```
<CodeGroup>
```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
```
</CodeGroup>
</Step>
<Step>
### Create an Autumn customer
When the customer signs up, create an Autumn customer for them. Autumn will automatically enable the <Badge color="green">Free</Badge> plan, since you marked it with the `auto-enable` flag.
<CodeGroup>
```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"
}'
```
</CodeGroup>
<Check>
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.
</Check>
In the Autumn dashboard, you will see your user under the [customers](https://app.useautumn.com/customers) page.
</Step>
<Step>
### Stripe Payment Flow
Call `attach` when the customer wants to purchase the <Badge color="blue">Pro</Badge> 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.
<CodeGroup>
```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"
}'
```
</CodeGroup>
<Note>
Use Stripe's test card `4242 4242 4242 4242` to make a purchase in sandbox.
You can enter any Expiry and CVV.
</Note>
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.
<Note>
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.
</Note>
</Step>
</Steps>
</View>
**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.
<Card
title="Track and limit usage"
href="/documentation/getting-started/gating"
>
Enforce usage limits and feature permissions using Autumn's `check` and
`track` functions
</Card>