Autumn Integration
Autumn fits apps that want product-led billing without building every plan, entitlement, and usage event by hand.
Install from the CLI
farm add integration autumn --ui
Config-first setup
import { autumn } from "@farm.js/integrations/autumn";export const integrations = { billing: autumn({ secretKey: process.env.AUTUMN_SECRET_KEY, billing: { resolveOwner(ctx) { const userId = ctx.req.get<string>("user.id"); return userId ? { id: userId, kind: "user" } : null; }, }, }),};
AUTUMN_WEBHOOK_SECRET is read from the environment when webhook routes are configured.
Choose SDK ownership
Let Farm construct Autumn
The config-first example is the default path. When instance is omitted, Farm creates the Autumn
SDK from secretKey and optional serverURL, supplied directly or through environment variables
where supported.
Provide an application-owned instance
import { Autumn } from "autumn-js";import { autumn } from "@farm.js/integrations/autumn";const autumnClient = new Autumn({ secretKey: process.env.AUTUMN_SECRET_KEY,});export const billing = autumn({ instance: autumnClient, billing: { resolveOwner: () => null, },});
The instance wins if a secret key is also supplied. Billing, webhook, route, product, meter, and storage settings remain integration options in either mode.
Usage
const checkout = await api.billing.checkout.post({ body: { productId: "pro", customerId: user.id, successPath: "/dashboard", },});
Database-backed billing
The integration can persist customer, plan, entitlement, and usage records through ctx.args.db, so the app keeps the same integration surface when the database client changes. This schema-backed path is separate from KV storage.
What Autumn adds
| Area | Details |
|---|---|
| Products | Public products for pricing pages. |
| Status | Current plan, subscription, trial, features, limits, and entitlements. |
| Checkout | Attach an Autumn product and redirect users when payment or confirmation is required. |
| Portal | Open the customer portal from a typed caller. |
| Usage | Meter usage, report usage, check balance, and read current charges. |
| Webhooks | Verify Autumn events and keep local billing state in sync. |
Common callers
const products = await api.billing.products.get();const status = await api.billing.status.get();const allowed = await api.billing.check.post({ body: { key: "ai-generations", amount: 1, },});
Checkout flow
const checkout = await api.billing.checkout.post({ body: { productId: "pro", successPath: "/dashboard", metadata: { source: "pricing", }, },});if (checkout.data?.redirectTo) { window.location.href = checkout.data.redirectTo;}
Owner and entitlements
Autumn needs a billing owner when it checks or attaches customer state. Use the owner resolver to connect Farm auth/session data with Autumn customers.
autumn({ secretKey: process.env.AUTUMN_SECRET_KEY, billing: { async resolveOwner(ctx) { const organizationId = ctx.req.get<string>("organization.id"); return organizationId ? { id: organizationId, kind: "organization", email: ctx.req.get<string>("user.email") ?? null, } : null; }, },});
Production notes
- Set
AUTUMN_SECRET_KEY,AUTUMN_WEBHOOK_SECRET, andAPP_BASE_URL. - Keep Farm product IDs separate from provider IDs when you want a stable app contract.
- Use
checkbefore expensive operations andreportUsageafter successful work. - Treat webhooks as the source of truth for subscription state.
- Test free-plan reads, checkout redirects, portal redirects, usage limits, and webhook sync.