Create your Autumn account and let’s create the pricing for a premium AI chatbot. We’re going to have:
  • A Free plan that gives users 5 chat messages per month for free
  • A Pro plan that gives users 100 chat messages per month for $20 per month.

1. Create your products

Create a product for each plan that your app offers. In our example we’ll create a “Free” and “Pro” product.
Run the following command in your root directory:
npx atmn init
This will create a autumn.config.ts file in your root directory and prompt you to login / create an account. Add the following code to your autumn.config.ts file.
autumn.config.ts
import {
  feature,
  product,
  featureItem,
  pricedFeatureItem,
  priceItem,
} from "atmn";

// Features
export const messages = feature({
  id: "messages",
  name: "Messages",
  type: "single_use",
});

// Products
export const free = product({
  id: "free",
  name: "Free",
  items: [
    // 5 messages per month
    featureItem({
      feature_id: messages.id,
      included_usage: 5,
      interval: "month",
    }),
  ],
});

export const pro = product({
  id: "pro",
  name: "Pro",
  items: [
    // 100 messages per month
    featureItem({
      feature_id: messages.id,
      included_usage: 100,
      interval: "month",
    }),
    // $20 per month
    priceItem({
      price: 20,
      interval: "month",
    }),
  ],
});
Then, push your changes to Autumn’s sandbox environment.
npx atmn push
If you already have products created in the dashboard, run npx atmn pull to pull them into your local config.

2. Setup Autumn

Install autumn-js

npm install autumn-js
If you’re using a separate backend and frontend, make sure to install the library in both.

Add your Autumn secret key

Create an Autumn Secret API key from the dashboard, and add it to your backend .env file.
.env
AUTUMN_SECRET_KEY=am_sk_1234567890

Add Server-Side Route

Server-side, mount the handler. This will create routes in the /api/autumn/* path, which will be called by Autumn’s frontend React library. These routes in turn call Autumn’s API. The handler takes in an identify function that should return a customerId. This is typically your internal user ID or organization ID from your auth provider.
// 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,
      customerData: {
        name: session?.user.name,
        email: session?.user.email,
      },
    };
  },
});
Autumn will automatically create a customer if the customer ID is new.

Add Client-Side Provider

Client side, wrap your application with the <AutumnProvider> component, and pass in your backend URL. This lets Autumn know how to reach the backend handler you mounted in the previous step.
If you’re using a fullstack framework like Next.js, your backend URL will be the same as your frontend URL (eg http://localhost:3000).
NEXT_PUBLIC_AUTUMN_BACKEND_URL=http://localhost:3000
import { AutumnProvider } from "autumn-js/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html>
      <body>
        <AutumnProvider backendUrl={process.env.NEXT_PUBLIC_AUTUMN_BACKEND_URL}>
          {children}
        </AutumnProvider>
      </body>
    </html>
  );
}
The Provider component can also take in a getBearerTokenfunction, which should be used for auth frameworks with separate backend and frontend, eg using Clerk with Express. This will pass in theAuthorizationheader from the request to the backend, which can be used in theautumnHandler` identify function.

3. Enable Stripe Payments

Call checkout to redirect the customer to a Stripe checkout page when they want to purchase the Pro plan. Once they’ve paid, Autumn will grant them access to the features we defined. If their payment method is already on file, CheckoutDialog will open instead to let the customer confirm their new subscription or purchase, then handle the payment. Alternatively, use our PricingTable component to show a pricing table that handles the checkout for you.
Make sure you’ve pasted in your Stripe test secret key sk_test_... in the Autumn dashboard.
React
import { useCustomer, CheckoutDialog } from "autumn-js/react";

export default function PurchaseButton() {
  const { checkout } = useCustomer();

  return (
    <button
      onClick={async () => {
        await checkout({
          productId: "pro",
          dialog: CheckoutDialog,
        });
      }}
    >
      Upgrade to Pro
    </button>
  );
}

4. Handle Pricing Logic

There are 3 key functions you need to handle the billing logic once the customer has purchased the Pro plan:
  • check for feature access to see if the customer is allowed to send a message.
  • track a usage event in Autumn (typically done server-side)
  • customer to display usage data in the UI.

Client-side

send-message.tsx
import { useCustomer } from "autumn-js/react";

export default function SendChatMessage() {
  const { customer, check, refetch } = useCustomer();

  return (
    <>
      <button
        onClick={async () => {
          const { data } = await check({ featureId: "messages" });

          if (data?.allowed) {
            //... send chatbot message server-side, then
            await refetch(); // refetch customer usage data
            alert(
              "Remaining messages: " + customer?.features.messages?.balance
            );
          } else {
            alert("You're out of messages");
          }
        }}
      >
        Send Message
      </button>
    </>
  );
}

Server-side

You should handle feature access checks on the backend too for security.
send-message.ts
import { Autumn as autumn } from "autumn-js";

const { data } = await autumn.check({
  customer_id: "user_123", // same user id from auth as in the autumn handler
  feature_id: "messages",
});

// server-side function to send the message
//then record the usage

await autumn.track({
  customer_id: "user_123",
  feature_id: "messages",
});

5. Next steps

Nice! You’ve now integrated Autumn into your application. Next, learn how to use Autumn’s components to show a pricing table, and handle upgrades, downgrades and paywalls.