---
title: "Autumn Integration"
description: "Add subscription and usage billing with Autumn while keeping Farm's integration and database APIs stable."
canonical_url: "https://mcp.farmjs.dev/docs/integrations/autumn"
markdown_url: "https://mcp.farmjs.dev/docs/integrations/autumn.md"
last_updated: "2026-10-20"
x_farming_labs_generated_preamble: true
---

# Autumn Integration
URL: /docs/integrations/autumn
LLM index: /llms.txt
Description: Add subscription and usage billing with Autumn while keeping Farm's integration and database APIs stable.

# Autumn Integration

Autumn fits apps that want product-led billing without building every plan, entitlement, and usage event by hand.

## Install from the CLI

**Terminal**

```bash
farm add integration autumn --ui
```

## Config-first setup

**src/lib/integrations.ts**

```ts
import { autumn } from "@farm.js/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. Use the
endpoint's signing secret exactly as Autumn provides it, including the `whsec_` prefix. Autumn
delivers webhooks through Svix, and the prefix tells Farm to decode the key the way Svix signed it.

## 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

```ts
import { Autumn } from "autumn-js";
import { autumn } from "@farm.js/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

**Checkout**

```ts
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

```ts
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

```ts
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;
}
```

Checkout and portal return paths must be same-origin, root-relative application paths. Protocol-relative paths such as `//example.com` are rejected.

## 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.

```ts
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`, and `APP_BASE_URL`.
- Keep Farm product IDs separate from provider IDs when you want a stable app contract.
- Use `check` before expensive operations and `reportUsage` after 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.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
