450 lines
11 KiB
Plaintext
450 lines
11 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.
|
|
|
|
<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>
|
|
|
|
<Note>
|
|
If you're using a separate backend and frontend, make sure to install the
|
|
library in both.
|
|
</Note>
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
{/* REACT DOCS */}
|
|
<View title="React" icon="react">
|
|
|
|
Autumn's client-side [hooks](/react/hooks/useCustomer) allow you to handle billing directly from your frontend.
|
|
|
|
<Steps>
|
|
<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 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` to attach the <Badge color="blue">Pro</Badge> plan to the customer. The customer is redirected to an Autumn checkout page where they can review prorations and plan changes before confirming. 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` function.
|
|
</Note>
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
</View>
|
|
|
|
{/* SERVER SDK DOCS */}
|
|
<View title="Server SDK" icon="server">
|
|
|
|
<Steps>
|
|
<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 dropdown>
|
|
|
|
```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
|
|
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 `billing.attach` to attach the <Badge color="blue">Pro</Badge> plan to the customer. Redirect the customer to the returned `paymentUrl` to complete payment or confirm the plan change.
|
|
|
|
<CodeGroup dropdown>
|
|
|
|
```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
|
|
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>
|
|
**`redirectMode: "always"`** (shown above) always returns a `paymentUrl`, redirecting the customer to review and confirm the plan change — whether it's a new subscription, upgrade, or downgrade.
|
|
|
|
**Build your own UI:** If you want to handle checkout yourself:
|
|
1. Call [previewAttach](/api-reference/billing/previewAttach) to get line items and pricing details
|
|
2. Call `attach` with `redirectMode: "if_required"` — this only returns a `paymentUrl` when a payment action is needed (e.g., no card on file), otherwise charges automatically
|
|
</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>
|