docs wip
This commit is contained in:
259
apps/docs/mintlify/cli/commands.mdx
Normal file
259
apps/docs/mintlify/cli/commands.mdx
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
title: "Command reference"
|
||||
description: "Every command, flag, and option available in the atmn CLI"
|
||||
---
|
||||
|
||||
## Global flags
|
||||
|
||||
These flags work with any command:
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-p, --prod` | Target production instead of sandbox |
|
||||
| `-l, --local` | Use `localhost:8080` API server |
|
||||
| `--headless` | Force non-interactive mode (for CI/agents) |
|
||||
| `-c, --config <path>` | Path to config file (default: `autumn.config.ts`) |
|
||||
| `-v, --version` | Show CLI version |
|
||||
|
||||
Flags can be combined -- for example, `atmn push -lp` targets production on a local API server.
|
||||
|
||||
## Authentication
|
||||
|
||||
### `atmn login`
|
||||
|
||||
Authenticate with Autumn via OAuth. Opens your browser, lets you select an organization, and saves sandbox + production API keys to `.env`.
|
||||
|
||||
```bash
|
||||
atmn login
|
||||
```
|
||||
|
||||
In non-TTY environments (CI), it prints a URL you can open manually.
|
||||
|
||||
### `atmn logout`
|
||||
|
||||
Remove `AUTUMN_SECRET_KEY` and `AUTUMN_PROD_SECRET_KEY` from your `.env` file.
|
||||
|
||||
```bash
|
||||
atmn logout
|
||||
```
|
||||
|
||||
### `atmn env`
|
||||
|
||||
Show your current organization and environment:
|
||||
|
||||
```bash
|
||||
atmn env
|
||||
```
|
||||
|
||||
```
|
||||
Organization: Acme Corp
|
||||
Slug: acme-corp
|
||||
Environment: Sandbox
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### `atmn init`
|
||||
|
||||
Create an `autumn.config.ts` from a starter template. Prompts for login if you haven't authenticated yet.
|
||||
|
||||
```bash
|
||||
atmn init
|
||||
```
|
||||
|
||||
### `atmn push`
|
||||
|
||||
Push your local `autumn.config.ts` to Autumn.
|
||||
|
||||
```bash
|
||||
atmn push [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-y, --yes` | Auto-confirm all prompts |
|
||||
|
||||
The CLI compares your local config with what's in Autumn and shows a summary of changes before applying. If plans with existing customers are modified, it will prompt about versioning.
|
||||
|
||||
### `atmn pull`
|
||||
|
||||
Pull plans and features from Autumn into your local `autumn.config.ts`.
|
||||
|
||||
```bash
|
||||
atmn pull [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-f, --force` | Overwrite config instead of smart in-place update |
|
||||
|
||||
By default, `pull` does a smart in-place update -- it adds new features and plans, updates existing ones, and removes deleted ones while preserving your formatting. Use `--force` to overwrite the entire file.
|
||||
|
||||
`pull` also generates an `@useautumn-sdk.d.ts` file with typed `FeatureIds` and `PlanIds` for IDE autocompletion.
|
||||
|
||||
### `atmn preview`
|
||||
|
||||
Render a pricing table from your local config without making any API calls.
|
||||
|
||||
```bash
|
||||
atmn preview [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--plan <id>` | Preview a specific plan |
|
||||
| `--currency <code>` | Currency for display (default: `USD`) |
|
||||
|
||||
### `atmn nuke`
|
||||
|
||||
Permanently delete all data in your **sandbox**. This command refuses to run with `--prod`.
|
||||
|
||||
```bash
|
||||
atmn nuke
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--dangerously-skip-all-confirmation-prompts` | Skip all safety prompts |
|
||||
|
||||
<Warning>
|
||||
This is irreversible. The flag name is intentionally long to prevent accidental use.
|
||||
</Warning>
|
||||
|
||||
## Data browsing
|
||||
|
||||
These commands open a full interactive TUI for browsing and inspecting your Autumn data. Use the `--headless` flag to get structured data instead.
|
||||
|
||||
### `atmn customers`
|
||||
|
||||
```bash
|
||||
atmn customers [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--id <id>` | Get a specific customer |
|
||||
| `--search <query>` | Filter customers |
|
||||
| `--page <n>` | Page number (default: `1`) |
|
||||
| `--limit <n>` | Results per page (default: `50`) |
|
||||
| `--format <fmt>` | Output: `text`, `json`, `csv` (default: `text`) |
|
||||
|
||||
### `atmn plans`
|
||||
|
||||
```bash
|
||||
atmn plans [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--id <id>` | Get a specific plan |
|
||||
| `--search <query>` | Filter plans |
|
||||
| `--include-archived` | Include archived plans |
|
||||
| `--page <n>` | Page number (default: `1`) |
|
||||
| `--limit <n>` | Results per page (default: `50`) |
|
||||
| `--format <fmt>` | Output: `text`, `json`, `csv` (default: `text`) |
|
||||
|
||||
<Note>
|
||||
`atmn products` is an alias for `atmn plans`.
|
||||
</Note>
|
||||
|
||||
### `atmn features`
|
||||
|
||||
```bash
|
||||
atmn features [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--id <id>` | Get a specific feature |
|
||||
| `--search <query>` | Filter features |
|
||||
| `--include-archived` | Include archived features |
|
||||
| `--page <n>` | Page number (default: `1`) |
|
||||
| `--limit <n>` | Results per page (default: `50`) |
|
||||
| `--format <fmt>` | Output: `text`, `json`, `csv` (default: `text`) |
|
||||
|
||||
### `atmn events`
|
||||
|
||||
```bash
|
||||
atmn events [options]
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--customer <id>` | Filter by customer |
|
||||
| `--feature <id>` | Filter by feature (comma-separated for multiple) |
|
||||
| `--time <range>` | Time range: `24h`, `7d`, `30d`, `90d` (default: `7d`) |
|
||||
| `--mode <mode>` | `list` or `aggregate` (default: `list`) |
|
||||
| `--bin <size>` | Bin size for aggregate: `hour`, `day`, `month` |
|
||||
| `--group-by <prop>` | Group by property in aggregate mode |
|
||||
| `--page <n>` | Page number (default: `1`) |
|
||||
| `--limit <n>` | Results per page (default: `100`) |
|
||||
| `--format <fmt>` | Output: `text`, `json`, `csv` (default: `text`) |
|
||||
|
||||
## Configuration
|
||||
|
||||
### `atmn config`
|
||||
|
||||
View and manage persistent CLI settings.
|
||||
|
||||
```bash
|
||||
atmn config # Show help and config file location
|
||||
atmn config --global # Same as above
|
||||
atmn config --global <key> # Read a setting
|
||||
atmn config --global <key> <value> # Write a setting
|
||||
```
|
||||
|
||||
Running `atmn config` with no arguments shows the full path to your config file, supported keys, and usage info.
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-g, --global` | Use global config |
|
||||
|
||||
#### Available keys
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `noDeclarationFile` | `boolean` | `false` | Skip generating `@useautumn-sdk.d.ts` on `atmn pull` |
|
||||
|
||||
#### Priority order
|
||||
|
||||
Settings are resolved in this order: **CLI flag** → **global config** → **default value**. For example, `--no-declaration-file` on `atmn pull` always takes priority over the global `noDeclarationFile` setting.
|
||||
|
||||
#### Config file location
|
||||
|
||||
Running `atmn config` or `atmn config --global` (with no key) prints the exact path to your config file on disk.
|
||||
|
||||
| OS | Path |
|
||||
|----|------|
|
||||
| macOS | `~/Library/Preferences/atmn/config.json` |
|
||||
| Linux | `~/.config/atmn/config.json` (or `$XDG_CONFIG_HOME`) |
|
||||
| Windows | `%APPDATA%\atmn\config.json` |
|
||||
|
||||
## Utilities
|
||||
|
||||
### `atmn dashboard`
|
||||
|
||||
Open the Autumn dashboard in your browser.
|
||||
|
||||
```bash
|
||||
atmn dashboard
|
||||
```
|
||||
|
||||
### `atmn version`
|
||||
|
||||
Print the CLI version. Alias: `atmn v`.
|
||||
|
||||
```bash
|
||||
atmn version
|
||||
```
|
||||
|
||||
## Headless mode
|
||||
|
||||
The CLI automatically detects non-TTY environments and switches to headless mode with plain text output and no interactive prompts. You can also force it with `--headless`.
|
||||
|
||||
### Exit codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| `0` | Success |
|
||||
| `1` | Error (network, auth, validation, or confirmation required) |
|
||||
364
apps/docs/mintlify/cli/config.mdx
Normal file
364
apps/docs/mintlify/cli/config.mdx
Normal file
@@ -0,0 +1,364 @@
|
||||
---
|
||||
title: "Configuration reference"
|
||||
description: "Define features, plans, and pricing in autumn.config.ts"
|
||||
---
|
||||
|
||||
Your `autumn.config.ts` file is the source of truth for your pricing. It exports features and plans using helper functions from the `atmn` package.
|
||||
|
||||
```ts autumn.config.ts
|
||||
import { feature, plan, planFeature } from 'atmn';
|
||||
|
||||
export const messages = feature({ ... });
|
||||
export const pro = plan({ ... });
|
||||
```
|
||||
|
||||
Push changes with `atmn push`, or pull existing config with `atmn pull`.
|
||||
|
||||
## Features
|
||||
|
||||
Features define what can be gated, metered, or billed in your app.
|
||||
|
||||
### `feature(config)`
|
||||
|
||||
<ParamField body="id" type="string" required>
|
||||
Unique identifier used in API calls (`check`, `track`, etc).
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="name" type="string" required>
|
||||
Display name shown in the dashboard and billing UI.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="type" type="enum" required>
|
||||
`"boolean"` | `"metered"` | `"credit_system"`
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="consumable" type="boolean">
|
||||
**Required for `metered` features.**
|
||||
- `true` -- usage is consumed (messages, API calls, credits)
|
||||
- `false` -- usage is ongoing (seats, storage, workspaces)
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="credit_schema" type="array">
|
||||
**Required for `credit_system` features.** Maps metered features to credit costs.
|
||||
|
||||
Each entry: `{ metered_feature_id: string, credit_cost: number }`
|
||||
</ParamField>
|
||||
|
||||
### Feature types
|
||||
|
||||
**Boolean** -- simple on/off flag:
|
||||
|
||||
```ts
|
||||
export const sso = feature({
|
||||
id: 'sso',
|
||||
name: 'SSO Authentication',
|
||||
type: 'boolean',
|
||||
});
|
||||
```
|
||||
|
||||
**Metered, consumable** -- used up and replenished (messages, API calls):
|
||||
|
||||
```ts
|
||||
export const messages = feature({
|
||||
id: 'messages',
|
||||
name: 'Messages',
|
||||
type: 'metered',
|
||||
consumable: true,
|
||||
});
|
||||
```
|
||||
|
||||
**Metered, non-consumable** -- ongoing usage (seats, storage):
|
||||
|
||||
```ts
|
||||
export const seats = feature({
|
||||
id: 'seats',
|
||||
name: 'Seats',
|
||||
type: 'metered',
|
||||
consumable: false,
|
||||
});
|
||||
```
|
||||
|
||||
**Credit system** -- maps multiple metered features to credit costs:
|
||||
|
||||
```ts
|
||||
export const basicModel = feature({
|
||||
id: 'basic_model',
|
||||
name: 'Basic Model',
|
||||
type: 'metered',
|
||||
consumable: true,
|
||||
});
|
||||
|
||||
export const premiumModel = feature({
|
||||
id: 'premium_model',
|
||||
name: 'Premium Model',
|
||||
type: 'metered',
|
||||
consumable: true,
|
||||
});
|
||||
|
||||
export const credits = feature({
|
||||
id: 'credits',
|
||||
name: 'AI Credits',
|
||||
type: 'credit_system',
|
||||
credit_schema: [
|
||||
{ metered_feature_id: basicModel.id, credit_cost: 1 },
|
||||
{ metered_feature_id: premiumModel.id, credit_cost: 5 },
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
<Tip>
|
||||
If you set the price per credit to 1 cent, credits become monetary credits (eg, 5 credits = $0.05 per premium message).
|
||||
</Tip>
|
||||
|
||||
## Plans
|
||||
|
||||
Plans combine features with pricing to create your subscription tiers, add-ons, and top-ups.
|
||||
|
||||
### `plan(config)`
|
||||
|
||||
<ParamField body="id" type="string" required>
|
||||
Unique identifier used in checkout and subscription APIs.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="name" type="string" required>
|
||||
Display name shown in pricing tables and billing.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="price" type="object">
|
||||
Base subscription price:
|
||||
- `amount: number` -- price amount (eg, `20` for $20)
|
||||
- `interval: string` -- `"month"` | `"quarter"` | `"semi_annual"` | `"year"` | `"one_off"`
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="items" type="array">
|
||||
Array of `planFeature()` objects defining what's included.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="auto_enable" type="boolean" default="false">
|
||||
Automatically assign this plan to new customers. Typically used for free plans.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="add_on" type="boolean" default="false">
|
||||
Allow this plan to be purchased alongside other plans (instead of replacing them).
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="free_trial" type="object">
|
||||
Free trial before billing starts:
|
||||
- `duration_length: number` -- eg, `14`
|
||||
- `duration_type: string` -- `"day"` | `"month"` | `"year"`
|
||||
- `card_required: boolean` -- whether a card is needed to start the trial
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="group" type="string">
|
||||
Group related plans together. Plans in the same group replace each other on upgrade/downgrade.
|
||||
</ParamField>
|
||||
|
||||
## Plan features
|
||||
|
||||
Plan features define what each plan includes -- usage limits, pricing, and billing behavior.
|
||||
|
||||
### `planFeature(config)`
|
||||
|
||||
<ParamField body="feature_id" type="string" required>
|
||||
The `id` of the feature to include.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="included" type="number">
|
||||
Amount included for free. Omit for boolean features.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="unlimited" type="boolean">
|
||||
Grant unlimited usage of this feature.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="reset" type="object">
|
||||
How often the included amount resets:
|
||||
- `interval: string` -- `"hour"` | `"day"` | `"week"` | `"month"` | `"quarter"` | `"semi_annual"` | `"year"`
|
||||
- `interval_count: number` -- defaults to `1`
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="price" type="object">
|
||||
Pricing for usage beyond the included amount. See [pricing patterns](#pricing-patterns) below.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="proration" type="object">
|
||||
How to handle mid-cycle quantity changes:
|
||||
- `on_increase:` `"prorate"` | `"charge_immediately"`
|
||||
- `on_decrease:` `"prorate"` | `"refund_immediately"` | `"no_action"`
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="rollover" type="object">
|
||||
Carry unused balance forward:
|
||||
- `max: number` -- maximum rollover amount
|
||||
- `expiry_duration_type:` `"month"` | `"forever"`
|
||||
- `expiry_duration_length: number` -- ignored if type is `"forever"`
|
||||
</ParamField>
|
||||
|
||||
### Pricing patterns
|
||||
|
||||
The `price` object on a plan feature supports different billing models:
|
||||
|
||||
**Usage-based** -- charge based on actual usage:
|
||||
|
||||
```ts
|
||||
planFeature({
|
||||
feature_id: seats.id,
|
||||
included: 5,
|
||||
price: {
|
||||
amount: 10,
|
||||
interval: 'month',
|
||||
billing_method: 'usage_based',
|
||||
billing_units: 1,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Prepaid** -- customer buys a fixed quantity upfront:
|
||||
|
||||
```ts
|
||||
planFeature({
|
||||
feature_id: credits.id,
|
||||
price: {
|
||||
amount: 5,
|
||||
billing_units: 100,
|
||||
billing_method: 'prepaid',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Tiered** -- price changes based on usage volume:
|
||||
|
||||
```ts
|
||||
planFeature({
|
||||
feature_id: apiCalls.id,
|
||||
price: {
|
||||
tiers: [
|
||||
{ to: 1000, amount: 0.01 },
|
||||
{ to: 10000, amount: 0.008 },
|
||||
{ to: 'inf', amount: 0.005 },
|
||||
],
|
||||
billing_method: 'usage_based',
|
||||
interval: 'month',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
#### Price fields
|
||||
|
||||
<ParamField body="amount" type="number">
|
||||
Price per `billing_units`. Mutually exclusive with `tiers`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="tiers" type="array">
|
||||
Tiered pricing. Each entry: `{ to: number | "inf", amount: number }`. Mutually exclusive with `amount`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="billing_method" type="enum" required>
|
||||
`"usage_based"` | `"prepaid"`
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="interval" type="enum">
|
||||
`"week"` | `"month"` | `"quarter"` | `"semi_annual"` | `"year"`. Omit for one-time charges. Not needed if the plan feature has a top-level `reset`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="billing_units" type="number" default="1">
|
||||
Units per price. Eg, $5 per 100 credits = `amount: 5, billing_units: 100`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="max_purchase" type="number">
|
||||
Maximum quantity that can be purchased.
|
||||
</ParamField>
|
||||
|
||||
## Full example
|
||||
|
||||
A complete config with a free plan, a paid plan with a trial, and a credits top-up add-on:
|
||||
|
||||
```ts autumn.config.ts
|
||||
import { feature, plan, planFeature } from 'atmn';
|
||||
|
||||
// Features
|
||||
export const messages = feature({
|
||||
id: 'messages',
|
||||
name: 'Messages',
|
||||
type: 'metered',
|
||||
consumable: true,
|
||||
});
|
||||
|
||||
export const seats = feature({
|
||||
id: 'seats',
|
||||
name: 'Seats',
|
||||
type: 'metered',
|
||||
consumable: false,
|
||||
});
|
||||
|
||||
export const sso = feature({
|
||||
id: 'sso',
|
||||
name: 'SSO',
|
||||
type: 'boolean',
|
||||
});
|
||||
|
||||
// Plans
|
||||
export const free = plan({
|
||||
id: 'free',
|
||||
name: 'Free',
|
||||
auto_enable: true,
|
||||
items: [
|
||||
planFeature({
|
||||
feature_id: messages.id,
|
||||
included: 5,
|
||||
reset: { interval: 'month' },
|
||||
}),
|
||||
planFeature({
|
||||
feature_id: seats.id,
|
||||
included: 1,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const pro = plan({
|
||||
id: 'pro',
|
||||
name: 'Pro',
|
||||
price: { amount: 20, interval: 'month' },
|
||||
free_trial: {
|
||||
duration_length: 14,
|
||||
duration_type: 'day',
|
||||
card_required: true,
|
||||
},
|
||||
items: [
|
||||
planFeature({
|
||||
feature_id: messages.id,
|
||||
included: 1000,
|
||||
reset: { interval: 'month' },
|
||||
}),
|
||||
planFeature({
|
||||
feature_id: seats.id,
|
||||
included: 5,
|
||||
price: {
|
||||
amount: 10,
|
||||
interval: 'month',
|
||||
billing_method: 'usage_based',
|
||||
billing_units: 1,
|
||||
},
|
||||
}),
|
||||
planFeature({
|
||||
feature_id: sso.id,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const topUp = plan({
|
||||
id: 'top_up',
|
||||
name: 'Message Top-Up',
|
||||
add_on: true,
|
||||
items: [
|
||||
planFeature({
|
||||
feature_id: messages.id,
|
||||
price: {
|
||||
amount: 5,
|
||||
billing_units: 100,
|
||||
billing_method: 'prepaid',
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
121
apps/docs/mintlify/cli/getting-started.mdx
Normal file
121
apps/docs/mintlify/cli/getting-started.mdx
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
title: "Getting started"
|
||||
description: "Install the CLI, authenticate, and sync your pricing config"
|
||||
---
|
||||
|
||||
The `atmn` CLI lets you define your pricing plans in code via an `autumn.config.ts` file, and sync them to Autumn with a single command.
|
||||
|
||||
## Installation
|
||||
|
||||
Run the CLI directly with your package manager:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash bunx
|
||||
bunx atmn
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm dlx atmn
|
||||
```
|
||||
|
||||
```bash npx
|
||||
npx atmn
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Login
|
||||
|
||||
Authenticate with your Autumn account:
|
||||
|
||||
```bash
|
||||
bunx atmn login
|
||||
```
|
||||
|
||||
This opens your browser, lets you pick an organization, and saves API keys for both sandbox and production to your `.env` file:
|
||||
|
||||
```bash .env
|
||||
AUTUMN_SECRET_KEY=am_sk_test_...
|
||||
AUTUMN_PROD_SECRET_KEY=am_sk_live_...
|
||||
```
|
||||
|
||||
<Check>
|
||||
You can verify your setup at any time with `bunx atmn env`, which shows your current organization and environment.
|
||||
</Check>
|
||||
|
||||
## Initialize a project
|
||||
|
||||
Run `atmn init` in your project root to create an `autumn.config.ts` file:
|
||||
|
||||
```bash
|
||||
bunx atmn init
|
||||
```
|
||||
|
||||
You'll be prompted to choose a starter template:
|
||||
|
||||
| Template | Pricing model |
|
||||
|----------|--------------|
|
||||
| **T3 Chat** | Freemium with message limits and a credits add-on |
|
||||
| **Railway** | Credit-based infrastructure pricing with overage |
|
||||
| **Linear** | Per-seat pricing with team limits |
|
||||
| **OpenAI** | Credit system mapping multiple AI models |
|
||||
|
||||
Pick whichever is closest to your use case, or start from scratch and build your own using the [config reference](/api-reference/cli/config).
|
||||
|
||||
## Push and pull
|
||||
|
||||
Once you have an `autumn.config.ts`, sync it with Autumn:
|
||||
|
||||
```bash
|
||||
# Push local config to Autumn
|
||||
bunx atmn push
|
||||
|
||||
# Pull remote config into your local file
|
||||
bunx atmn pull
|
||||
```
|
||||
|
||||
`push` reads your config file, compares it with what's in Autumn, and applies the changes. In interactive mode you'll see a summary of what will be created, updated, or deleted before confirming.
|
||||
|
||||
`pull` fetches your plans and features from Autumn and writes them into your local `autumn.config.ts`. If the file already exists, it does a smart in-place update that preserves your local formatting and comments where possible.
|
||||
|
||||
<Tip>
|
||||
Use `bunx atmn pull` to generate an `autumn.config.ts` from plans you've already created in the dashboard.
|
||||
</Tip>
|
||||
|
||||
## Preview locally
|
||||
|
||||
You can preview your plans without pushing anything:
|
||||
|
||||
```bash
|
||||
bunx atmn preview
|
||||
```
|
||||
|
||||
This renders a pricing table from your local config.
|
||||
|
||||
## Environments
|
||||
|
||||
By default, all commands target your **sandbox** environment. Add the `-p` flag to target production:
|
||||
|
||||
```bash
|
||||
# Push to production
|
||||
bunx atmn push -p
|
||||
|
||||
# Pull from production
|
||||
bunx atmn pull -p
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Pushing to production will prompt for confirmation. Use `--yes` to skip the prompt automatically.
|
||||
</Warning>
|
||||
|
||||
**Next: Configuration reference**
|
||||
|
||||
Learn how to define features, plans, and pricing in your `autumn.config.ts`.
|
||||
|
||||
<Card
|
||||
title="Configuration reference"
|
||||
href="/api-reference/cli/config"
|
||||
>
|
||||
Complete reference for features, plans, and plan features
|
||||
</Card>
|
||||
@@ -45,7 +45,7 @@
|
||||
"groups": [
|
||||
{
|
||||
"group": " ",
|
||||
"pages": ["welcome"]
|
||||
"pages": ["welcome", "documentation/getting-started/migration"]
|
||||
},
|
||||
{
|
||||
"group": "Getting Started",
|
||||
@@ -76,19 +76,36 @@
|
||||
{
|
||||
"group": "Manage Customers",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Subscriptions",
|
||||
"pages": [
|
||||
"documentation/customers/subscriptions/overview",
|
||||
"documentation/customers/subscriptions/accepting-payments",
|
||||
"documentation/customers/subscriptions/managing-subscriptions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Balances",
|
||||
"pages": [
|
||||
"documentation/customers/balances/overview",
|
||||
"documentation/customers/balances/balance-stacking",
|
||||
"documentation/customers/balances/managing-balances"
|
||||
]
|
||||
},
|
||||
"documentation/customers/check",
|
||||
"documentation/customers/tracking-usage",
|
||||
"documentation/customers/balances",
|
||||
"documentation/customers/feature-entities",
|
||||
"documentation/customers/attaching-plans",
|
||||
"documentation/customers/updating-subscriptions",
|
||||
"documentation/customers/creating-customers",
|
||||
"documentation/customers/managing-customers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Additional Resources",
|
||||
"pages": ["documentation/external-providers/revenuecat"]
|
||||
"pages": [
|
||||
"documentation/webhooks",
|
||||
"documentation/external-providers/revenuecat",
|
||||
"documentation/external-providers/vercel-marketplace"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -104,7 +121,7 @@
|
||||
},
|
||||
{
|
||||
"tab": "React",
|
||||
"icon": "image",
|
||||
"icon": "react",
|
||||
"groups": [
|
||||
{
|
||||
"group": "React Hooks",
|
||||
@@ -122,9 +139,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "CLI",
|
||||
"icon": "square-terminal",
|
||||
"pages": ["cli/getting-started", "cli/config", "cli/commands"]
|
||||
},
|
||||
{
|
||||
"tab": "API Reference",
|
||||
"icon": "rectangle-terminal",
|
||||
"icon": "display-code",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Billing",
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
---
|
||||
title: Balances
|
||||
description: Learn about feature balances for your metered features
|
||||
---
|
||||
|
||||
Each metered feature you create has 3 different fields associated with it per customer:
|
||||
|
||||
1. **Granted**: The total allowance of usage granted to the customer (included + prepaid).
|
||||
2. **Usage**: The amount of the feature that the customer has used.
|
||||
3. **Remaining**: The amount of usage that the customer has left (`granted - usage`).
|
||||
|
||||
<Note>
|
||||
If the product item has a `prepaid` price, the granted amount will be dynamically set to the quantity of the product item purchased in advance.
|
||||
</Note>
|
||||
|
||||
## Getting a Customer's Balances
|
||||
|
||||
You can get a customer's balances with the `customers.getOrCreate` method:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
import { Autumn } from "autumn-js";
|
||||
|
||||
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
|
||||
|
||||
const customer = await autumn.customers.getOrCreate({
|
||||
customerId: "user_123",
|
||||
});
|
||||
|
||||
// Access balances by feature ID
|
||||
const messages = customer.balances?.messages;
|
||||
console.log(`${messages?.remaining} / ${messages?.granted} remaining`);
|
||||
```
|
||||
|
||||
```python Python
|
||||
from autumn_sdk import Autumn
|
||||
|
||||
autumn = Autumn("am_sk_test_1234")
|
||||
|
||||
customer = await autumn.customers.get_or_create(
|
||||
customer_id="user_123"
|
||||
)
|
||||
|
||||
messages = customer.balances.get("messages")
|
||||
print(f"{messages.remaining} / {messages.granted} remaining")
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.useautumn.com/v1/customers" \
|
||||
-H "Authorization: Bearer am_sk_test_1234" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "customer_id": "user_123" }'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Expandable title="Example response">
|
||||
```json
|
||||
{
|
||||
"id": "user_123",
|
||||
"balances": {
|
||||
"ai-messages": {
|
||||
"featureId": "ai-messages",
|
||||
"granted": 100,
|
||||
"remaining": 40,
|
||||
"usage": 60,
|
||||
"unlimited": false,
|
||||
"overageAllowed": false,
|
||||
"nextResetAt": 1745193600011
|
||||
},
|
||||
"seats": {
|
||||
"featureId": "seats",
|
||||
"granted": 5,
|
||||
"remaining": -1,
|
||||
"usage": 6,
|
||||
"unlimited": false,
|
||||
"overageAllowed": true,
|
||||
"nextResetAt": null
|
||||
},
|
||||
"premium-support": {
|
||||
"featureId": "premium-support",
|
||||
"granted": 0,
|
||||
"remaining": 0,
|
||||
"usage": 0,
|
||||
"unlimited": true,
|
||||
"overageAllowed": false,
|
||||
"nextResetAt": null
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Expandable>
|
||||
|
||||
## Positive and Negative Balances
|
||||
|
||||
A feature's remaining balance can be positive or negative:
|
||||
|
||||
- **Positive Balance**: The customer has used less than the granted amount — they have usage remaining.
|
||||
- **Negative Balance**: The customer has used more than the granted amount — they will be billed for overage in the next billing period.
|
||||
|
||||
<Note>
|
||||
Features can only have a negative balance if they have a [usage-based price](/documentation/pricing/plan-features#priced-features) associated with them.
|
||||
|
||||
If a feature does not have a price, its balance will never fall below 0 even if more usage events are sent.
|
||||
</Note>
|
||||
|
||||
## Reset Intervals
|
||||
|
||||
When you create a product item, you'll define a usage reset interval. When the reset interval comes around, `usage` will be reset to 0, and `remaining` will be set back to the `granted` amount.
|
||||
|
||||
Reset intervals can be: `minute`, `hour`, `day`, `week`, `month`, `quarter`, `semi_annual`, or `year`.
|
||||
|
||||
If a feature has a price associated with it, the reset interval will be the same as the billing interval. This means it can be one of the following: `month`, `quarter`, `semi_annual`, or `year`.
|
||||
|
||||
#### No Reset
|
||||
|
||||
Certain features are consumable, and can have balances that are replenished. For example, you may have features like:
|
||||
|
||||
- Credits
|
||||
- AI messages
|
||||
- Hours of compute
|
||||
|
||||
Other features are not consumable, and their usage is continuous. For example:
|
||||
|
||||
- Seats
|
||||
- Workspaces
|
||||
- Number of compute instances in use
|
||||
|
||||
These features should not have a reset interval, so that their balances are never reset.
|
||||
|
||||
<Note>
|
||||
This is not a hard rule. You may have consumable features like messages, but
|
||||
want them to last forever. In this case, they should also have a reset
|
||||
interval of "no reset"
|
||||
</Note>
|
||||
|
||||
You can configure a product item to have no reset interval by selecting "One-off" in the plan editor dashboard.
|
||||
|
||||
<Info>
|
||||
|
||||
**Example use case**
|
||||
|
||||
We have a free tier, which gives customers access to 3 seats.
|
||||
We also have a pro tier, which is charged at $10/seat/month.
|
||||
|
||||
For our free tier, we'd create a product item with:
|
||||
|
||||
- Usage reset: No Reset
|
||||
- Via API: `interval: null`
|
||||
|
||||
For our pro tier, we'd create a product item with:
|
||||
|
||||
- Usage reset: No Reset
|
||||
- Billing Interval: Month
|
||||
- Via API: `interval: month`, and `reset_usage_on_billing: false`
|
||||
|
||||
</Info>
|
||||
|
||||
#### Features with multiple intervals
|
||||
|
||||
You may have a pricing model in which a customer can buy the following together:
|
||||
|
||||
- a pro plan with 50 credits per month.
|
||||
- a top-up add-on that grants 100 credits that don't expire
|
||||
|
||||
In this case you have a feature that shares two intervals: `month` and "no reset".
|
||||
|
||||
Autumn will create 2 separate balances for each of these. You will see each of these in the `customers` route and on the customer details page in the dashboard.
|
||||
|
||||
When you send a usage event, Autumn will deduct from the balance with the shortest reset interval first.
|
||||
|
||||
<Note>
|
||||
If you want to deduct from the balance with the longest reset interval first,
|
||||
please contact us.
|
||||
</Note>
|
||||
|
||||
## Edge Cases
|
||||
|
||||
There are certain cases in which a feature's balance will diverge from the typical `granted` minus `usage` calculation.
|
||||
|
||||
#### Setting a feature's balance manually
|
||||
|
||||
You can manually edit a users balance via the dashboard or via the API.
|
||||
|
||||
When this happens, the balance will be updated to the new value, but the `granted` and `usage` will not be updated.
|
||||
|
||||
#### Customer has paid for more than they are using
|
||||
|
||||
Let's take a pricing model in which a customer pays $10 per seat per month. At the start of the billing period, they are using 5 seats (`remaining: -5`, `usage: 5`). Then, they remove a seat.
|
||||
|
||||
If `prorate_decrease` is set to `false`, the customer will be paying for 5 seats and using 4 seats (`remaining: -5`, `usage: 4`). This means that our customer has 1 seat available that they have paid for but not using.
|
||||
|
||||
In this case, the balance and usage has diverged. Autumn accounts for this scenario: they can add another seat at any time, which will not be charged for.
|
||||
|
||||
Otherwise, at the start of the next billing period, they usage and balance will synchronize again (`remaining: -4`, `usage: 4`), and they will be billed for 4 seats.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Balance Stacking"
|
||||
description: "How multiple balances combine and how usage is deducted"
|
||||
---
|
||||
|
||||
A single feature can have balances from multiple sources - different plans, add-ons, or standalone grants.
|
||||
|
||||
Autumn combines these into a single parent balance while tracking each source separately in a `breakdown` array, grouped by plan and interval.
|
||||
|
||||
> **Example** <br />
|
||||
> A customer has a feature, `messages`, with the following balances:
|
||||
> - Pro plan: 500 messages per month
|
||||
> - Top-up add-on: 200 lifetime messages
|
||||
>
|
||||
> Their total available balance is 700 `messages`.
|
||||
|
||||
## The Breakdown Array
|
||||
|
||||
Each balance source is tracked separately in the `breakdown` array. This lets you see exactly where the balance came from and how much remains from each source.
|
||||
|
||||
```json expandable
|
||||
{
|
||||
"balances": {
|
||||
"messages": {
|
||||
"included_usage": 700,
|
||||
"balance": 700,
|
||||
"usage": 0,
|
||||
"breakdown": [
|
||||
{
|
||||
"id": "ent_abc123",
|
||||
"product_id": "pro",
|
||||
"included_usage": 500,
|
||||
"balance": 500,
|
||||
"usage": 0,
|
||||
"interval": "month",
|
||||
"next_reset_at": 1745193600000
|
||||
},
|
||||
{
|
||||
"id": "ent_def456",
|
||||
"product_id": "top-up",
|
||||
"included_usage": 200,
|
||||
"balance": 200,
|
||||
"usage": 0,
|
||||
"interval": "one_off",
|
||||
"next_reset_at": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Deduction Order
|
||||
|
||||
When usage is tracked, Autumn deducts from balances in a specific order based on their reset interval. **Shorter intervals are deducted first** by default.
|
||||
|
||||
The order is: `hour` (shortest) > `day` > `week` > `month` > `quarter` > `semi_annual` > `year` > `one_off` (lifetime - never resets).
|
||||
|
||||
This ensures that expiring balances are used before permanent ones.
|
||||
|
||||
<Note>
|
||||
If you need the deduction order reversed (longest interval first), please [contact us](https://discord.gg/STqxY92zuS).
|
||||
</Note>
|
||||
|
||||
> **Example** <br />
|
||||
> Suppose a customer has two balances for messages: 500 monthly and 200 lifetime. They have a total of 700 messages. <br />
|
||||
> - The customer uses 400 messages. The monthly balance (the shorter interval) is used up first, leaving 100 in monthly and 200 in lifetime (300 total). <br />
|
||||
> - The customer uses another 200 messages. The remaining 100 monthly is depleted, and the next 100 is deducted from the lifetime balance. Now, monthly is 0, lifetime is 100 (100 total). <br />
|
||||
> - On the next cycle, the monthly balance resets to 500, and the lifetime remains at 100, for a new total of 600. <br />
|
||||
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
title: "Managing Balances"
|
||||
description: "Create, update, and manage balances via the dashboard or API"
|
||||
---
|
||||
|
||||
You can manage customer balances through the Autumn dashboard or programmatically via the API.
|
||||
|
||||
## From the Dashboard
|
||||
|
||||
### Viewing Balances
|
||||
|
||||
1. Go to the [Customers page](https://app.useautumn.com/customers)
|
||||
2. Click on a customer to view their details
|
||||
3. Their balances are displayed in the **Balances** section, including breakdown by source
|
||||
|
||||
### Modifying a Balance
|
||||
|
||||
To set or add to a feature's balance:
|
||||
|
||||
1. Navigate to the customer's detail page
|
||||
2. Under the balances section, click on the feature you want to modify. If there are [stacked balances](/documentation/customers/balance-stacking), choose the one you want to modify.
|
||||
3. Choose whether to **set the balance** to a specific value or **add to the balance**
|
||||
4. Enter the amount and save
|
||||
|
||||
## Creating Standalone Balances (API)
|
||||
|
||||
You can use the `/balances/create` endpoint to grant balances independent of any plan, for example to issue one-time promotional credits, referral rewards, or make manual customer adjustments.
|
||||
|
||||
You can also set expiration dates for promotional usage grants and configure reset intervals.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Node.js
|
||||
import { Autumn } from "autumn-js";
|
||||
|
||||
const autumn = new Autumn({ secretKey: "am_sk_..." });
|
||||
|
||||
await autumn.balances.create({
|
||||
customer_id: "user_123",
|
||||
feature_id: "credits",
|
||||
granted_balance: 500,
|
||||
reset: {
|
||||
interval: "one_off"
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from autumn import Autumn
|
||||
|
||||
autumn = Autumn(secret_key="am_sk_...")
|
||||
|
||||
autumn.balances.create(
|
||||
customer_id="user_123",
|
||||
feature_id="credits",
|
||||
granted_balance=500,
|
||||
reset={
|
||||
"interval": "one_off"
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST https://api.useautumn.com/v1/balances/create \
|
||||
-H "Authorization: Bearer am_sk_..." \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"feature_id": "credits",
|
||||
"granted_balance": 500,
|
||||
"reset": {
|
||||
"interval": "one_off"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
See the [Create Balance API reference](/api-reference/features/create-balance) for all available parameters.
|
||||
|
||||
## Updating Balances (API)
|
||||
|
||||
Use the `/customers/{customer_id}/balances` endpoint to set balances for a customer.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Node.js
|
||||
import { Autumn } from "autumn-js";
|
||||
|
||||
const autumn = new Autumn({ secretKey: "am_sk_..." });
|
||||
|
||||
await autumn.customers.updateBalances("user_123", {
|
||||
balances: [{ feature_id: "credits", balance: 750 }]
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from autumn import Autumn
|
||||
|
||||
autumn = Autumn(secret_key="am_sk_...")
|
||||
|
||||
autumn.customers.update_balances(
|
||||
"user_123",
|
||||
balances=[{"feature_id": "credits", "balance": 750}]
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST https://api.useautumn.com/v1/customers/user_123/balances \
|
||||
-H "Authorization: Bearer am_sk_..." \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"balances": [{ "feature_id": "credits", "balance": 750 }]
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
See the [Set Feature Balance API reference](/api-reference/features/set-feature-balances) for all available parameters.
|
||||
|
||||
## Querying Balances
|
||||
|
||||
### Via Get Customer
|
||||
|
||||
Retrieve all balances for a customer:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Node.js
|
||||
const customer = await autumn.customers.get("user_123");
|
||||
console.log(customer.balances);
|
||||
```
|
||||
|
||||
```python Python
|
||||
customer = autumn.customers.get("user_123")
|
||||
print(customer.balances)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl https://api.useautumn.com/v1/customers/user_123 \
|
||||
-H "Authorization: Bearer am_sk_..."
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
See the [Get Customer API reference](/api-reference/customers/get-customer) for the full response schema.
|
||||
|
||||
### Via Check Endpoint
|
||||
|
||||
Check access and get the current balance for a specific feature:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Node.js
|
||||
const result = await autumn.check({
|
||||
customer_id: "user_123",
|
||||
feature_id: "credits"
|
||||
});
|
||||
|
||||
console.log(result.allowed);
|
||||
console.log(result.balance);
|
||||
```
|
||||
|
||||
```python Python
|
||||
result = autumn.check(
|
||||
customer_id="user_123",
|
||||
feature_id="credits"
|
||||
)
|
||||
|
||||
print(result.allowed)
|
||||
print(result.balance)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST https://api.useautumn.com/v1/check \
|
||||
-H "Authorization: Bearer am_sk_..." \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"feature_id": "credits"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
See the [Check API reference](/api-reference/core/check) for more details.
|
||||
105
apps/docs/mintlify/documentation/customers/balances/overview.mdx
Normal file
105
apps/docs/mintlify/documentation/customers/balances/overview.mdx
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: "Balances"
|
||||
description: "Understanding how feature balances work in Autumn"
|
||||
---
|
||||
|
||||
Balances determine what features a customer can use, and track how much they have used.
|
||||
|
||||
Balances are created in two ways:
|
||||
|
||||
1. **Automatically from plans**: When a plan is attached to a customer, each feature in the plan becomes a balance for that customer.
|
||||
2. **Standalone via API**: You can create balances directly using the API, independent of any plan. See [Managing Balances](/documentation/customers/managing-balances) for details.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
F[Feature] -->|added to plan| PF[Plan Feature]
|
||||
PF -->|plan attached to customer| B[Customer Balance]
|
||||
|
||||
```
|
||||
|
||||
Customers can also [Stack Balances](/documentation/customers/balance-stacking) of the same feature from multiple plans (eg, an add-on plan), or different reset intervals (eg, monthly credits and one-time top-ups).
|
||||
|
||||
|
||||
## Core Fields
|
||||
|
||||
Each balance has the following key fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `included_usage` | The amount granted by the plan, or a purchased quantity |
|
||||
| `balance` | The remaining amount available |
|
||||
| `usage` | The amount that has been consumed |
|
||||
|
||||
When you retrieve a customer, their balances will be included in the response.
|
||||
|
||||
<Tip>
|
||||
For the complete balance schema including reset configuration, overage settings, and breakdown details, see the [Get Customer API reference](/api-reference/customers/get-customer).
|
||||
</Tip>
|
||||
|
||||
<Expandable title="example customer response">
|
||||
```json
|
||||
{
|
||||
"balances": {
|
||||
"messages": {
|
||||
"granted_balance": 1000,
|
||||
"current_balance": 750,
|
||||
"usage": 250,
|
||||
"unlimited": false,
|
||||
"reset": {
|
||||
"interval": "month",
|
||||
"resets_at": 1745193600000
|
||||
}
|
||||
},
|
||||
"premium-support": {
|
||||
"unlimited": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Expandable>
|
||||
|
||||
## Feature Types and Balances
|
||||
|
||||
When you create a feature, you define its type. This affects how balances behave.
|
||||
|
||||
### Consumable Features
|
||||
|
||||
Features that are used up and can be replenished. Examples: credits, API requests, AI tokens.
|
||||
|
||||
Consumable features support **reset intervals** - the balance resets to the granted amount on a regular schedule.
|
||||
|
||||
Available reset intervals:
|
||||
- `hour`, `day`, `week`, `month`, `quarter`, `semi_annual`, `year`
|
||||
- `one_off` - the balance never resets (useful for one-time grants or top-ups)
|
||||
|
||||
### Non-Consumable Features
|
||||
|
||||
Features with persistent, continuous usage. Examples: seats, workspaces, storage.
|
||||
|
||||
Non-consumable features don't reset. Instead, they support **proration** when quantities change mid-billing cycle.
|
||||
|
||||
### Credit Systems
|
||||
|
||||
A [credit system](/documentation/pricing/credits) lets multiple features draw from a single shared balance.
|
||||
|
||||
When you check or track usage, you use the underlying feature ID (e.g., `premium_message`), but the balance is deducted from the credit system.
|
||||
|
||||
When you track usage for a feature in a credit system, Autumn:
|
||||
1. Looks up the credit cost for that feature that you defined
|
||||
2. Multiplies the usage value by the credit cost
|
||||
3. Deducts from the credit system balance
|
||||
|
||||
For example, if you have a credit system with a credit cost of 2 credits per API request, and a customer uses 10 API requests, Autumn will deduct 20 credits from the balance.
|
||||
|
||||
|
||||
## Positive and Negative Balances
|
||||
|
||||
A balance can be positive or negative:
|
||||
|
||||
- **Positive balance**: Customer has unused allowance remaining
|
||||
- **Negative balance**: Customer has used more than their allowance (only possible if [overage](/documentation/pricing/plan-features#priced-features) is enabled)
|
||||
|
||||
<Note>
|
||||
Features can only have a negative balance if they have a usage-based price that allows overage. Otherwise, tracking stops when balance reaches 0.
|
||||
</Note>
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: "Accepting Payments"
|
||||
description: "How to handle the Stripe payment flow with Autumn"
|
||||
---
|
||||
|
||||
Accepting payments is a two-step process:
|
||||
|
||||
1. **`checkout`** - Gets checkout information (either a Stripe Checkout URL or purchase confirmation data)
|
||||
2. **`attach`** - Enables the product and charges a saved payment method
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A(("checkout")) -->|"url"| B["Stripe Checkout"]
|
||||
A -->|"preview"| C["Display preview info"]
|
||||
B --> D["Payment complete"]
|
||||
D --> E["Plan enabled"]
|
||||
C --> F["User confirms"]
|
||||
F --> G(("attach"))
|
||||
G --> D
|
||||
```
|
||||
|
||||
## Checkout
|
||||
|
||||
Call `checkout` when a customer wants to purchase a product. If no payment method is on file, a Stripe Checkout URL is returned. Otherwise, preview data (prices, proration info) is returned for the customer to confirm.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```tsx React
|
||||
import { useCustomer, CheckoutDialog } from "autumn-js/react";
|
||||
|
||||
const { checkout } = useCustomer();
|
||||
|
||||
<Button onClick={() => checkout({ productId: "pro", dialog: CheckoutDialog })} />
|
||||
```
|
||||
|
||||
```typescript Node.js
|
||||
import { Autumn } from "autumn-js";
|
||||
|
||||
const autumn = new Autumn({ secretKey: "am_sk_..." });
|
||||
|
||||
const { data } = await autumn.checkout({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
|
||||
if (data.url) {
|
||||
// Redirect to Stripe Checkout
|
||||
} else {
|
||||
// Show confirmation UI with preview data
|
||||
}
|
||||
```
|
||||
|
||||
```python Python
|
||||
from autumn import Autumn
|
||||
|
||||
autumn = Autumn("am_sk_...")
|
||||
|
||||
response = await autumn.checkout(
|
||||
customer_id="user_123",
|
||||
product_id="pro",
|
||||
)
|
||||
|
||||
if response.url:
|
||||
# Redirect to Stripe Checkout
|
||||
else:
|
||||
# Show confirmation UI with preview data
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST 'https://api.useautumn.com/v1/checkout' \
|
||||
-H 'Authorization: Bearer am_sk_...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"product_id": "pro"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Attach
|
||||
|
||||
If `checkout` returned preview data (no URL), call `attach` after the customer confirms to charge their saved payment method and enable the product.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```tsx React
|
||||
import { useCustomer } from "autumn-js/react";
|
||||
|
||||
const { attach } = useCustomer();
|
||||
|
||||
<Button onClick={() => attach({ productId: "pro" })} />
|
||||
```
|
||||
|
||||
```typescript Node.js
|
||||
const { data } = await autumn.attach({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = await autumn.attach(
|
||||
customer_id="user_123",
|
||||
product_id="pro",
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST 'https://api.useautumn.com/v1/attach' \
|
||||
-H 'Authorization: Bearer am_sk_...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"product_id": "pro"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## 3DS and Payment Failures
|
||||
|
||||
When calling `attach`, the payment may require additional action. Autumn will return:
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| `3ds_required` | Payment requires 3D Secure authentication |
|
||||
| `payment_failed` | Payment was declined (e.g., insufficient funds) |
|
||||
|
||||
Both cases include an invoice URL. Direct the customer to this URL to complete authentication or update their payment method. Once resolved, the payment processes and the subscription activates.
|
||||
|
||||
## Past Due Subscriptions
|
||||
|
||||
If a recurring payment fails (e.g., card expired), the subscription status becomes `past_due`. To resolve this:
|
||||
|
||||
1. Direct the customer to the [billing portal](/api-reference/customers/open-billing-portal) to update their payment method
|
||||
2. Once updated, Stripe will automatically retry the failed invoice
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```tsx React
|
||||
import { useCustomer } from "autumn-js/react";
|
||||
|
||||
const { openBillingPortal } = useCustomer();
|
||||
|
||||
<Button onClick={() => openBillingPortal({ returnUrl: window.location.href })} />
|
||||
```
|
||||
|
||||
```typescript Node.js
|
||||
const { data } = await autumn.customers.billingPortal("user_123", {
|
||||
return_url: "https://your-app.com/billing",
|
||||
});
|
||||
// Redirect to data.url
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = await autumn.customers.billing_portal(
|
||||
"user_123",
|
||||
return_url="https://your-app.com/billing",
|
||||
)
|
||||
# Redirect to response.url
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
If you'd like to block feature access when a subscription is `past_due`, please contact us. We can enable a configuration flag to do this for you.
|
||||
</Note>
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: "Managing Subscriptions"
|
||||
description: "Handle upgrades, downgrades, and cancellations"
|
||||
---
|
||||
|
||||
## Upgrades
|
||||
|
||||
Upgrades happen when you attach a product with a higher price than the customer's current product. Use the same `attach` method—Autumn handles the rest.
|
||||
|
||||
<Warning>
|
||||
If a payment method exists, attaching the product will immediately charge the customer. If upgrading from a free to a paid product, a checkout URL is generated instead.
|
||||
</Warning>
|
||||
|
||||
**Pricing behavior:**
|
||||
|
||||
- **Fixed prices** are prorated based on time remaining in the billing period
|
||||
- **Usage-based prices** bill outstanding usage at the old rate immediately, then apply the new rate going forward
|
||||
|
||||
## Downgrades
|
||||
|
||||
Downgrades happen when you attach a product with a lower price. Unlike upgrades, downgrades are **scheduled** to take effect at the end of the current billing period.
|
||||
|
||||
The new product will have status `scheduled` until it activates. Customers can cancel a scheduled downgrade by re-attaching their current product.
|
||||
|
||||
<Note>
|
||||
If you've set a [`group`](/documentation/pricing/plans#plan-properties) when creating products, upgrades and downgrades only apply between products in the same group. Attaching a product from a different group adds it alongside the existing product.
|
||||
</Note>
|
||||
|
||||
## Cancellations
|
||||
|
||||
Cancel a subscription using the `cancel` method. By default, cancellations take effect at the end of the billing period.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```tsx React
|
||||
import { useCustomer } from "autumn-js/react";
|
||||
|
||||
const { cancel } = useCustomer();
|
||||
|
||||
// Cancel at end of billing period
|
||||
await cancel({ productId: "pro" });
|
||||
|
||||
// Cancel immediately
|
||||
await cancel({ productId: "pro", cancelImmediately: true });
|
||||
```
|
||||
|
||||
```typescript Node.js
|
||||
import { Autumn } from "autumn-js";
|
||||
|
||||
const autumn = new Autumn({ secretKey: "am_sk_..." });
|
||||
|
||||
// Cancel at end of billing period
|
||||
await autumn.cancel({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
|
||||
// Cancel immediately
|
||||
await autumn.cancel({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
cancel_immediately: true,
|
||||
});
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Cancel at end of billing period
|
||||
curl -X POST 'https://api.useautumn.com/v1/cancel' \
|
||||
-H 'Authorization: Bearer am_sk_...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"product_id": "pro"
|
||||
}'
|
||||
|
||||
# Cancel immediately
|
||||
curl -X POST 'https://api.useautumn.com/v1/cancel' \
|
||||
-H 'Authorization: Bearer am_sk_...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"customer_id": "user_123",
|
||||
"product_id": "pro",
|
||||
"cancel_immediately": true
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
If you have a default product (with `auto-enable` set), it will be activated after the cancellation takes effect.
|
||||
|
||||
## Usage reset behavior
|
||||
|
||||
When a new product is enabled, you can control what happens to existing feature usage with the `reset_usage_when_enabled` property on the product item:
|
||||
|
||||
- `true`: Usage resets to 0 (typical for consumable features like credits)
|
||||
- `false`: Usage carries over to the new product (typical for continuous features like seats)
|
||||
|
||||
<Info>
|
||||
**Example:** A customer on Free has used 20 of their 100 credits. They upgrade to Pro which includes 500 credits.
|
||||
|
||||
- If `reset_usage_when_enabled = true`: They get 500 credits
|
||||
- If `reset_usage_when_enabled = false`: They get 480 credits (500 - 20 used)
|
||||
</Info>
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Subscriptions"
|
||||
description: "How Autumn manages customer subscriptions"
|
||||
---
|
||||
|
||||
Autumn uses Stripe subscriptions under the hood to handle recurring billing. When you attach a plan to a customer, Autumn creates the Stripe subscription and provisions feature balances automatically.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P[Plan] -->|attach| C[Customer]
|
||||
C -->|creates| S[Stripe Subscription]
|
||||
S -->|provisions| B[Balances]
|
||||
```
|
||||
|
||||
When a subscription is created, Autumn provisions [balances](/documentation/customers/balances) for each feature in the plan. Balances determine what the customer can access and track how much they've used. For example, a Pro plan might grant 1,000 API requests per month—this becomes a balance that decrements as the customer uses your product.
|
||||
|
||||
Balances can also be created for [credit systems](/documentation/pricing/credits) (eg, $10 credits per month) and boolean toggle features (eg, access to a premium analytics dashboard).
|
||||
|
||||
## Subscription statuses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `active` | Subscription is in good standing |
|
||||
| `trialing` | Customer is in a free trial period |
|
||||
| `past_due` | Payment failed, subscription needs attention |
|
||||
| `scheduled` | Product will activate at end of current billing period |
|
||||
| `expired` | Subscription has ended |
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Accepting Payments" icon="credit-card" href="/documentation/subscriptions/accepting-payments">
|
||||
Learn about the checkout and payment flow
|
||||
</Card>
|
||||
<Card title="Managing Subscriptions" icon="sliders" href="/documentation/subscriptions/managing-subscriptions">
|
||||
Handle upgrades, downgrades and cancellations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: "Vercel Marketplace"
|
||||
description: "Set up the Vercel Marketplace integration in Autumn"
|
||||
---
|
||||
|
||||
When you use Autumn, you can also add your product to [Vercel's Marketplace](https://vercel.com/marketplace) without any additional code. Follow these steps to connect the Autumn partner API and webhooks to Vercel.
|
||||
|
||||
<Note>
|
||||
This is currently in beta, please reach out to us on [Discord](https://discord.gg/STqxY92zuS) or email us at hey@useautumn.com to get access.
|
||||
</Note>
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Step 1: Gather integration credentials and IDs
|
||||
|
||||
In your Vercel Integration Console, open your integration entry.
|
||||
|
||||
- Copy the **Client Integration ID**.
|
||||
- Copy the **Client Integration Secret**.
|
||||
|
||||
In Stripe:
|
||||
|
||||
- Open **Settings > Custom payment methods**.
|
||||
- Create a custom payment method named **Vercel Marketplace**.
|
||||
- Upload the Vercel logo.
|
||||
- Copy the resulting **Custom Payment Method ID**.
|
||||
|
||||
In the Autumn Dashboard:
|
||||
|
||||
- Open **Developer > Vercel Webhook**.
|
||||
- Add a new endpoint.
|
||||
- Set the endpoint URL to your production API endpoint plus `/autumn/webhooks/vercel`.
|
||||
- Confirm the router path is current before saving.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Step 2: Configure values in Autumn
|
||||
|
||||
In the Autumn Dashboard, open **Developer > Vercel** and set:
|
||||
|
||||
- `Client Integration ID`
|
||||
- `Client Integration Secret`
|
||||
- `Custom Payment Method ID`
|
||||
|
||||
Also save the **Base URL** shown in this section.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Step 3: Configure values in Vercel
|
||||
|
||||
In the Vercel Integration Console, paste the Autumn **Base URL** into:
|
||||
|
||||
- **Partner API Base URL**
|
||||
- **Webhooks URL**
|
||||
|
||||
This ensures Vercel can call Autumn when onboarding users and when key lifecycle events occur.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Step 4: Validate the webhook
|
||||
|
||||
Confirm webhook delivery in both systems:
|
||||
|
||||
- Trigger a test event flow in Vercel.
|
||||
- Verify Vercel receives callback requests for **key create/delete** events.
|
||||
- Verify Autumn logs/receives the payload and updates API keys as expected.
|
||||
|
||||
If events are not delivered, confirm the exact webhook route in your deployment (for example `.../autumn/webhooks/vercel`) and update both sides if it has changed.
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: "Migrating to Autumn"
|
||||
description: "How to migrate your existing Stripe customers to Autumn"
|
||||
---
|
||||
|
||||
It's easy to move your existing customers to Autumn. The Autumn team will help you move your subscriptions and purchases over without any disruption. The main reasons teams migrate are:
|
||||
- **Speed** - Team-based billing, multi-interval usage limits, auto-topups, timeseries charts: all handled by Autumn out of the box.
|
||||
- **Flexibility** — Plan versioning, custom deals, and pricing changes without code deploys
|
||||
- **Reliability** — No webhook edge cases, race conditions, or state sync issues to debug
|
||||
|
||||
## Migration Steps
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Replace your existing billing code with Autumn
|
||||
|
||||
Start by integrating Autumn in your development environment. Replace your existing Stripe billing logic with Autumn's SDK:
|
||||
|
||||
- Set up your pricing plans in the [Autumn dashboard](https://app.useautumn.com)
|
||||
- Install the Autumn SDK and configure your API keys
|
||||
- Replace Stripe checkout, subscription management, and usage tracking with Autumn equivalents
|
||||
|
||||
See our [setup guides](/documentation/getting-started/setup/react) for detailed integration instructions.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Link your production Stripe account
|
||||
|
||||
Connect your existing Stripe account to Autumn in your production environment. This gives us access to your active subscriptions so we can link them during migration.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Prepare your customer mapping CSV
|
||||
|
||||
When you're ready to move to production, prepare a CSV file with the following columns:
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| `autumn_id` | The customer ID you'll use in Autumn (typically your internal user/org ID from auth) |
|
||||
| `stripe_id` | The customer's existing Stripe customer ID (e.g., `cus_xxx`) |
|
||||
| `plan` | The Autumn product ID the customer should be on |
|
||||
|
||||
You can also optionally include user's names and emails as separate columns.
|
||||
|
||||
**Example CSV:**
|
||||
|
||||
```csv
|
||||
autumn_id,stripe_id,plan
|
||||
user_123,cus_ABC123,pro
|
||||
user_456,cus_DEF456,enterprise
|
||||
user_789,cus_GHI789,starter
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Submit your CSV
|
||||
|
||||
Send your CSV to the Autumn team via the [Discord](https://discord.gg/STqxY92zuS) support channel or email at hey@useautumn.com. We'll import the data into your production account within 8 hours.
|
||||
|
||||
We will reuse your existing Stripe products and subscriptions — **there will be no change or disruption to your customers' billing**. We're simply linking what's already there so Autumn can manage it going forward. We'll also make sure **all your active subscriptions and purchases are accounted for**, in case customers made payments after you exported your CSV.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
### Deploy your Autumn integration
|
||||
|
||||
Once the import is complete, you can deploy your Autumn integration to production. Your existing customers will be seamlessly linked to their Stripe subscriptions through Autumn.
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
**Usage balances will reset mid-cycle**
|
||||
|
||||
With this migration method, customers' usage balances will be reset when they're imported. This means they may get some extra usage during their current billing cycle.
|
||||
|
||||
If preserving exact usage counts is critical for your business, reach out to us and we can work with you on a rolling deploy strategy.
|
||||
</Note>
|
||||
|
||||
<Info>
|
||||
**Forward deploy service**
|
||||
|
||||
If you're processing $1M+ ARR, we can handle the migration and deployment for you at no extra charge. We'll work directly with your engineering team to ensure a smooth transition.
|
||||
|
||||
Contact us on [Discord](https://discord.gg/STqxY92zuS) or at hey@useautumn.com to learn more.
|
||||
</Info>
|
||||
129
apps/docs/mintlify/documentation/webhooks.mdx
Normal file
129
apps/docs/mintlify/documentation/webhooks.mdx
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
title: "Webhooks"
|
||||
description: "Receive real-time notifications when customer billing events occur"
|
||||
---
|
||||
|
||||
With Autumn, you don't need webhooks for managing billing — subscription state, usage tracking, and access control are all synchronized automatically.
|
||||
|
||||
However, webhooks can still be useful for specific use cases where you want to trigger actions in your own systems.
|
||||
|
||||
<Note>
|
||||
Webhooks are currently in beta. Please reach out to us on [Discord](https://discord.gg/STqxY92zuS) or email us at support@useautumn.com to enable webhooks for your account.
|
||||
</Note>
|
||||
|
||||
## Use Cases
|
||||
|
||||
While Autumn handles billing complexity for you, webhooks are helpful for:
|
||||
|
||||
- **Sending activation emails** — Welcome new subscribers or notify users when their plan changes
|
||||
- **Triggering workflows** — Start onboarding sequences, provision resources, or update CRM records
|
||||
- **Syncing with external systems** — Keep your database, analytics, or other tools in sync with subscription changes
|
||||
- **Deprovisioning access to services** — Shut off access to downstream services when a customer cancels their subscription
|
||||
|
||||
## Available Events
|
||||
|
||||
### customer.products.updated
|
||||
|
||||
Fired when a customer's product or plan changes. The `scenario` field indicates what type of change occurred.
|
||||
|
||||
| Scenario | Description |
|
||||
|----------|-------------|
|
||||
| `new` | Customer subscribed to a new product |
|
||||
| `upgrade` | Customer upgraded to a higher-tier plan |
|
||||
| `downgrade` | Customer downgraded to a lower-tier plan |
|
||||
| `renew` | Subscription renewed for another billing period |
|
||||
| `cancel` | Subscription was canceled |
|
||||
| `expired` | Subscription has expired |
|
||||
| `past_due` | Payment is past due |
|
||||
| `scheduled` | A plan change has been scheduled |
|
||||
|
||||
**Example payload:**
|
||||
|
||||
```json expandable
|
||||
{
|
||||
"type": "customer.products.updated",
|
||||
"data": {
|
||||
"scenario": "new",
|
||||
"customer": {
|
||||
"id": "user_123",
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com",
|
||||
"balances": { ... },
|
||||
"subscriptions": [ ... ]
|
||||
},
|
||||
"updated_product": {
|
||||
"id": "pro_plan",
|
||||
"name": "Pro Plan",
|
||||
"features": [ ... ]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### customer.threshold_reached
|
||||
|
||||
Fired when a customer reaches a usage threshold for a feature. This is useful for notifying users before they hit hard limits.
|
||||
|
||||
| Threshold Type | Description |
|
||||
|----------------|-------------|
|
||||
| `limit_reached` | Customer has reached their usage limit |
|
||||
| `allowance_used` | Customer has exhausted their allowance |
|
||||
|
||||
In most cases, these events will fire at the same time, as the included allowance is the same as the user's usage limit. However, you may have a feature with a different included allowance and a different "max purchase" limit.
|
||||
|
||||
Eg: 100 API calls included, then 0.1 per API call, with a maximum purchase limit of 1000 API calls.
|
||||
|
||||
**Example payload:**
|
||||
|
||||
```json expandable
|
||||
{
|
||||
"type": "customer.threshold_reached",
|
||||
"data": {
|
||||
"threshold_type": "limit_reached",
|
||||
"customer": {
|
||||
"id": "user_123",
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com",
|
||||
"balances": { ... }
|
||||
},
|
||||
"feature": {
|
||||
"id": "api_calls",
|
||||
"name": "API Calls",
|
||||
"type": "metered"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
Once webhooks are enabled for your account, you can configure your webhook endpoints in the Autumn dashboard:
|
||||
|
||||
<Steps>
|
||||
<Step title="Navigate to Developer Settings">
|
||||
Go to the **Developer** section in your Autumn dashboard and select the **Webhooks** tab.
|
||||
</Step>
|
||||
<Step title="Add an Endpoint">
|
||||
Click **Add Endpoint** and enter the URL where you want to receive webhook events.
|
||||
</Step>
|
||||
<Step title="Select Events">
|
||||
Choose which events you want to subscribe to. You can select all events or specific ones.
|
||||
</Step>
|
||||
<Step title="Save and Test">
|
||||
Save your endpoint configuration. You can use the **Send Test Event** button to verify your endpoint is receiving events correctly.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Webhook Security
|
||||
|
||||
Autumn uses [Svix](https://www.svix.com/) for reliable webhook delivery. Each webhook request includes signature headers that you can use to verify the request is genuinely from Autumn:
|
||||
|
||||
- `svix-id` — Unique message identifier
|
||||
- `svix-timestamp` — Timestamp of when the message was sent
|
||||
- `svix-signature` — Signature for verifying authenticity
|
||||
|
||||
You can use the [Svix libraries](https://docs.svix.com/receiving/verifying-payloads/how) to easily verify webhook signatures in your application.
|
||||
|
||||
## Retry Policy
|
||||
|
||||
If your endpoint returns an error or is unavailable, Autumn will automatically retry the webhook with exponential backoff. You can view delivery attempts and retry failed webhooks from the dashboard.
|
||||
@@ -1,19 +1,60 @@
|
||||
---
|
||||
title: Welcome to Autumn
|
||||
sidebarTitle: Introduction
|
||||
description: "Open-source billing infrastructure that manages webhooks, usage limits and credits."
|
||||
description: "Open source, drop-in system of record for AI billing and monetization."
|
||||
---
|
||||
|
||||
## What is Autumn?
|
||||
|
||||
Autumn handles your billing flows and makes sure your customers have the access to the right features and limits.
|
||||
Autumn is an infrastructure layer between your application and Stripe. It acts as your source of truth for subscription status, usage metering and credit balances.
|
||||
|
||||
It sits between your server and Stripe billing, and acts as your managed database for subscription status, usage metering and credit balances.
|
||||
Your app queries Autumn in real-time to check if a customer is allowed to do something (eg, send an AI message, access SSO, etc).
|
||||
|
||||
```mermaid actions={false}
|
||||
flowchart TD
|
||||
subgraph app["Your Application"]
|
||||
A["Frontend App"]
|
||||
B["Backend Server"]
|
||||
end
|
||||
|
||||
subgraph autumn["Autumn"]
|
||||
C["Autumn Server"]
|
||||
D["Dashboard or CLI"]
|
||||
E["Database & Cache"]
|
||||
end
|
||||
|
||||
F["Stripe"]
|
||||
|
||||
A -- "Autumn hooks (optional)" --> B
|
||||
B -- "Balance checks + usage tracking" --> C
|
||||
C -- "Customer state" --> E
|
||||
C -- "Payments" --> F
|
||||
F -- "Webhooks" --> C
|
||||
D -- "Configure Pricing" --> C
|
||||
```
|
||||
|
||||
## Why use Autumn?
|
||||
|
||||
AI made pricing and billing significantly harder for engineers to build and maintain. For reference, OpenAI wrote a [blog post](https://openai.com/index/beyond-rate-limits/) about the system they built in-house. Some of the things you will need to build and maintain are:
|
||||
|
||||
| Feature | Requirements |
|
||||
|-----------------------|--------------------------------------------------------------------------------------------------|
|
||||
| Subscription logic | Checkouts, prorated upgrades, scheduled downgrades, add-ons, trials. 10+ webhook cases to handle. |
|
||||
| Credit system | Monthly limits, rollovers, promotional grants with exipry, waterfall deduction rules, real-time enforcement |
|
||||
| Spend controls | Auto top ups, spend caps, per-seat allowances, usage analytics, observability |
|
||||
| Enterprise plans | Tiered pricing, custom credit grants, pilots, expansion logic |
|
||||
| Edge cases | Plan switching, failed payments, 3DS, race conditions, refunds |
|
||||
|
||||
At some point you or your GTM team will want to change your pricing, and you will need to rebuild everything.
|
||||
|
||||
Autumn offloads all this logic out of your codebase. After you set it up, everything about your pricing can be managed through our dashboard.
|
||||
|
||||
It gives you easier setup, saves months of engineering time, more flexibility and more reliability.
|
||||
|
||||
## Core concepts
|
||||
|
||||
1000s of founders and fast-growing startups use Autumn to make billing easier and more reliable. No webhooks needed!
|
||||
|
||||
|
||||
## How it works
|
||||
|
||||
<Steps>
|
||||
<Step title="Model your pricing in Autumn">
|
||||
@@ -65,7 +106,6 @@ This gives you flexibility to make pricing changes, or define custom plans for i
|
||||
## What Autumn is not
|
||||
|
||||
- **A Stripe billing replacement**: although you don't need to deal with Stripe's APIs, you are still using (and paying for) Stripe's subscriptions, payments and invoicing. You bring your own Stripe account and are never "locked in" to our system.
|
||||
- **For fully sales-led companies**: Autumn is designed to be used by product-led, or hybrid product-sales teams with self-serve billing. If your customers only pay via custom invoices, Autumn is probably not for you yet.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user