Skip to content
Gauge

ax-check.com

Autumn

useautumn.com

ax-check.com

Checked 19 September 2026

B

88/100

An agent completed setup

Autumn's quickstart link is broken, but pricing is upfront

The homepage and llms.txt both point to a Quickstart URL that 404s. Pricing tiers (Free, Pro $375/mo, Scale custom) are stated in plain text with no login needed.

4 fixes to start with

Concrete changes, backed by what we found.

Docs

Publish a quickstart with a working first example.

Quickstart link on homepage and llms.txt returns 404 at docs.useautumn.com/quickstart.

Docs

List every offered API, MCP, and skills surface in /llms.txt.

llms.txt lists docs and API reference but never mentions the offered MCP server.

Docs

Make the compact quickstart usable on its own.

Quickstart link on homepage and llms.txt returns 404; no actionable first steps fetched.

Linked from useautumn.com/

Docs

Add working installation and next-step links to the quickstart.

Homepage/llms.txt Quickstart link 404s; other install links (sign-in, docs) resolve.

Linked from useautumn.com/

Recorded coding sessions

Same task, 3 models, no useautumn.com account. Recorded 19 September 2026 on Pi.

3 recorded · 10m 15s

10m 15s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelDeepSeek V4 Procwd/sandbox/repo
Help me build a simple example using Autumn. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

Let me start by understanding what "Autumn" is. I need to figure out if there's a developer workflow I can act on. Let me search the web or look for SDK/API details. I'm in a coding agent with bash access. Let me first check what Autumn is.

Let me think about this. "Autumn" could be a pricing SaaS product. There's "Autumn" which is a usage-based billing / pricing tool. Let me search.

I should investigate. Let me use bash to check for curl to their docs.

Actually, let me be careful. I should find out what Autumn is. Let me search the internet via curl maybe. But I might not have internet. Let me try.

$ curl -s --max-time 15 https://raw.githubusercontent.com/useautumn/autumn/main/README.md | head -100; echo "---EXIT:$?---"{"content":[{"text":"# Autumn\n\n<img width=\"1983\" height=\"793\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f2b6271d-19af-4b16-be73-b55a3…ctrl+o
{"content":[{"text":"# Autumn\n\n<img width=\"1983\" height=\"793\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f2b6271d-19af-4b16-be73-b55a3303b7f1\" />\n\n\n[![Discord](https://img.shields.io/badge/Join%20Community-5865F2?logo=discord&logoColor=white)](https://discord.gg/53emPtY9tA)\n[![Follow](https://img.shields.io/twitter/follow/autumnpricing?style=social)](https://x.com/autumnpricing)\n[![Y Combinator](https://img.shields.io/badge/Y%20Combinator-F24-orange)](https://www.ycombinator.com/companies/autumn)\n[![Cloud](https://img.shields.io/badge/Cloud-☁️-blue)](https://app.useautumn.com)\n[![Documentation](https://img.shields.io/badge/Documentation-📕-blue)](https://docs.useautumn.com)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/useautumn/autumn)\n\n[Autumn](https://useautumn.com) is an open-source layer between Stripe and your application, allowing you to create any pricing model and embed it with a couple lines of code. On Autumn you can build:\n- Subscriptions\n- Credit systems & top ups\n- Usage-based models & overages\n- Custom plans for large customers\n\nAll this without having to handle webhooks, upgrades/downgrades, cancellations or payment fails.\n\n\n## Getting Started\n\n**Cloud**: The quickest way to start using Autumn is through our [cloud service](https://app.useautumn.com). \n\n**Self Hosted**: If you'd like to self-host Autumn:\n\n1. Make sure you have `bun` installed\n2. Install the project dependencies:\n```bash\nbun install\n```\n3. Run Autumn:\n```bash\nbun dev\n```\n\nThat's it! You should be able to see the Autumn dashboard on `http://localhost:3000`. \n\n> ℹ️ Autumn depends on a bunch of services. If you'd like help with self-hosting or running a local instance, contact the team on [Discord](https://discord.gg/53emPtY9tA).\n\n> ⚠️ To log in, enter an email at the sign in page, and an OTP should appear in your console / terminal. Normally, we use Resend to email an OTP or Google OAuth -- these can be set up by providing your credentials in `server/.env`\n\n> ℹ️ If you'd like to use your own Postgres instance, paste the connection string in the `DATABASE_URL` env variable at `server/.env`\n\n## Why Autumn\n\n**1️⃣ Billing infra gets complex fast**\n\nMore than payments: it's building permission management, metering, usage limits with cron jobs, and connecting it to upgrade, downgrade, cancellation and failed payments states. Race conditions, edge cases, and other bugs will slow you down.\n\n**2️⃣ Billing and app logic should be decoupled**\n\nGrowing companies iterate on pricing often: raising prices, experimenting with credits or charging for a new feature. DB migrations, rebuilding in-app flows, internal dashboards for custom pricing and grandfathering users on old pricing is a nightmare.\n\n\n## How it works\nFirst, create your products and plans on the dashboard. We support **any** pricing model. Some popular ones we've seen include:\n\n1. **Usage & Overage** ⚡: set real-time usage limits and choose when they reset. Charge users if they go over.\n2. **Credits** 💰: users can access monetary or arbitrary credits that many features can draw from\n3. **Seat-based with per-seat limits** 👥:: bill customers for their users (or other entities)\n4. **Pay upfront** 💳: let users purchase a fixed quantity of a feature upfront, which is used over time\n\n\nNext, all your billing logic can be implemented through just 3 functions:\n\n1. `/attach`: One function call for all purchase flows. We return a Stripe Checkout URL, or handle an upgrade/downgrade.\n\n```tsx\nconst { attach } = useAutumn();\n<button\n  onClick={async () => {\n    await attach({ productId: \"pro\" });\n  }}\n>\n  Upgrade to Pro\n</button>\n```\n\n2. `/check`: Check whether a customer has access to a product, feature or remaining usage.\n```ts\nconst { check } = useAutumn();\n\nconst { data } = await check({ featureId: \"ai_tokens\" })\n\n!data.allowed && alert(\"AI limit reached\")\n```\n\n3. `/track`: When a customer uses a usage-based feature, record a usage event.\n\n```ts\nconst { track } = useAutumn();\n\nawait track({\n  featureId: \"ai_tokens\",\n  value: 1312\n})\n```\n\n---EXIT:0---\n","type":"text"}]}
$ curl -s --max-time 15 https://autumn.run 2>&1 | head -50; echo "---EXIT:$?---"{"content":[{"text":"<html>\r\n<head><title>302 Found</title></head>\r\n<body>\r\n<center><h1>302 Found</h1></center>\r\n<hr><center>openresty</center>\r\n</bod…ctrl+o
{"content":[{"text":"<html>\r\n<head><title>302 Found</title></head>\r\n<body>\r\n<center><h1>302 Found</h1></center>\r\n<hr><center>openresty</center>\r\n</body>\r\n</html>\r\n---EXIT:0---\n","type":"text"}]}
Thinking…

I have internet access. Autumn is "useautumn" - open-source billing layer between Stripe and your app. Cloud service at app.useautumn.com. Let me read the full README and docs to understand SDK/API and pricing.

Let me continue reading the README and check docs.

$ curl -s --max-time 15 https://raw.githubusercontent.com/useautumn/autumn/main/README.md | sed -n '100,400p'{"content":[{"text":"\n## Others\n\n**Contributing** 🤝: If you're interested in contributing, you can check out our guide [here](/.github/CONTRIBUTING.md). All…ctrl+o
{"content":[{"text":"\n## Others\n\n**Contributing** 🤝: If you're interested in contributing, you can check out our guide [here](/.github/CONTRIBUTING.md). All types of help are appreciated :)\n\n**Support** 💬: If you need any type of support, we're typically most responsive on our [Discord channel](https://discord.gg/STqxY92zuS), but feel free to email us `hey@useautumn.com` too!\n\n\n\n<!-- ## Congratulations!\n\nYou've embedded a full billing system into your application within a few minutes. You can make any pricing model changes you need, or handle custom plans without needing to alter your codebase.\n\nFeel free to self-host Autumn, or use our hosted version at https://useautumn.com. And let us know any questions, thoughts or feedback at hey@useautumn.com. -->\n\n## Contributors\n\nThanks to all our contributors for helping make autumn a better product!\n\n<a href=\"https://github.com/useautumn/autumn/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=useautumn/autumn\" />\n</a>\n","type":"text"}]}
$ curl -s --max-time 15 https://docs.useautumn.com 2>&1 | head -100; echo "---EXIT:$?---"{"content":[{"text":"4\\\",\\\"dark\\\":\\\"https://mintcdn.com/autumn-b9b4c0fb/BOEMpWFJsAdGcii1/assets/logo/autumn-light.svg?fit=max\\u0026auto=format\\u0026n=…ctrl+o
{"content":[{"text":"4\\\",\\\"dark\\\":\\\"https://mintcdn.com/autumn-b9b4c0fb/BOEMpWFJsAdGcii1/assets/logo/autumn-light.svg?fit=max\\u0026auto=format\\u0026n=BOEMpWFJsAdGcii1\\u0026q=85\\u0026s=f700b862e5d0ada8c89a5976d27863fe\\\"},\\\"favicon\\\":\\\"https://mintcdn.com/autumn-b9b4c0fb/ihHX49Ug6NamJ10t/favicon.svg?fit=max\\u0026auto=format\\u0026n=ihHX49Ug6NamJ10t\\u0026q=85\\u0026s=b1fd8b3e3086e5a3855a8cf8c45dd57a\\\",\\\"api\\\":{\\\"playground\\\":{\\\"display\\\":\\\"interactive\\\"},\\\"examples\\\":{\\\"languages\\\":[\\\"typescript\\\",\\\"python\\\",\\\"bash\\\"]}},\\\"appearance\\\":\\\"$18:2:props:children:1:props:appearance\\\",\\\"background\\\":{\\\"color\\\":{\\\"light\\\":\\\"#FFFFFF\\\",\\\"dark\\\":\\\"#0A0A0A\\\"}},\\\"navbar\\\":{\\\"primary\\\":{\\\"type\\\":\\\"button\\\",\\\"label\\\":\\\"Dashboard\\\",\\\"href\\\":\\\"https://app.useautumn.com\\\"}},\\\"footer\\\":{\\\"socials\\\":{\\\"x\\\":\\\"https://x.com/autumnpricing\\\",\\\"github\\\":\\\"https://github.com/useautumn\\\",\\\"linkedin\\\":\\\"https://linkedin.com/company/useautumn\\\"}},\\\"fonts\\\":{\\\"heading\\\":{\\\"family\\\":\\\"Inter\\\"},\\\"body\\\":{\\\"family\\\":\\\"Inter\\\"}},\\\"contextual\\\":{\\\"options\\\":[\\\"copy\\\",\\\"cursor\\\",\\\"view\\\"],\\\"display\\\":\\\"header\\\"},\\\"interaction\\\":{\\\"drilldown\\\":true},\\\"styling\\\":{\\\"latex\\\":true,\\\"codeblocks\\\":\\\"system\\\"},\\\"navigation\\\":{\\\"global\\\":{\\\"anchors\\\":[{\\\"anchor\\\":\\\"Discord\\\",\\\"icon\\\":\\\"discord\\\",\\\"href\\\":\\\"https://discord.gg/STqxY92zuS\\\"},{\\\"anchor\\\":\\\"GitHub\\\",\\\"icon\\\":\\\"github\\\",\\\"href\\\":\\\"https://github.com/useautumn/autumn\\\"},{\\\"anchor\\\":\\\"Website\\\",\\\"icon\\\":\\\"globe\\\",\\\"href\\\":\\\"https://useautumn.com\\\"}]},\\\"pages\\\":[]}},\\\"docsNavWithMetadata\\\":\\\"$undefined\\\",\\\"anonymizedNav\\\":\\\"$undefined\\\",\\\"hasFullNav\\\":false},\\\"children\\\":\\\"$L2a\\\"}]}]}]}]]}]]}]]\\n\"])</script><script>self.__next_f.push([1,\"2b:I[604804,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"LoginButtonProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"2c:I[141180,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"SidebarLoginButtonProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"2d:I[343590,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"NavigationContextController\\\"]\\n\"])</script><script>self.__next_f.push([1,\"2e:I[378486,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"PageListProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"2f:I[742977,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"PrefetchProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"30:I[237978,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"PageModeOverrideProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"31:I[378896,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"ConfiguredVariationProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"32:I[557611,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"Fonts\\\"]\\n\"])</script><script>self.__next_f.push([1,\"33:I[330080,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/8048dcef7298cf99.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/526cb488b5bfc024.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/ab55877564076568.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/f3d21b56325afeb2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/34741e9da93fcfba.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/15da0bd8d2646d24.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7cb103ff122456f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/7fa450b5031b4866.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/5656ef4b9c65e1f2.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/2c09d2adf26e1020.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/e7b3b3d7bd4f285c.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/bf62f3a2927aa603.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\"],\\\"BannerProvider\\\"]\\n\"])</script><script>self.__next_f.push([1,\"34:I[864506,[\\\"/mintlify-assets/_next/static/chunks/7578c347033fb4c7.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b664fc8bb1e7ab0d.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/31aff92bfbdfee60.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/eefca33900b5dff8.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/761250e423ee7acf.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/mintlify-assets/_next/static/chunks/b9704a3de461ff8f.js?dpl=dpl_BYpasf3G22y6JYK4VkZSuUDDTV7V\\\",\\\"/m…
Thinking…

The docs site is Mintlify with markdown. I should fetch the docs markdown. Mintlify docs usually have a /docs.json or llms.txt. There's a hint "llms.txt v2". Let me try to get the docs in markdown format. Common approaches:

Let me try those.

$ for u in "https://docs.useautumn.com/llms.txt" "https://docs.useautumn.com/llms-full.txt" "https://docs.useautumn.com/sitemap.xml"; do echo "=== $u ==="; curl -s --max-time 15 "$u" | head -80; echo; d…{"content":[{"text":"=== https://docs.useautumn.com/llms.txt ===\n# Autumn\n\n- [Welcome to Autumn](https://docs.useautumn.com/welcome.md): Drop-in, open-source…ctrl+o
for u in "https://docs.useautumn.com/llms.txt" "https://docs.useautumn.com/llms-full.txt" "https://docs.useautumn.com/sitemap.xml"; do echo "=== $u ==="; curl -s --max-time 15 "$u" | head -80; echo; done

{"content":[{"text":"=== https://docs.useautumn.com/llms.txt ===\n# Autumn\n\n- [Welcome to Autumn](https://docs.useautumn.com/welcome.md): Drop-in, open-source control layer for AI and SaaS monetization.\n- [How It Works](https://docs.useautumn.com/documentation/concepts/overview.md): How features, plans, subscriptions and balances fit together\n- [Plans](https://docs.useautumn.com/documentation/concepts/plans.md): Learn about plans in Autumn and how to create them\n- [Features](https://docs.useautumn.com/documentation/concepts/features.md): Learn about features in Autumn and how to create them\n- [Plan Items](https://docs.useautumn.com/documentation/concepts/plan-items.md): Configure what customers get access to when they purchase a plan\n- [Subscriptions](https://docs.useautumn.com/documentation/concepts/subscriptions.md): How Autumn manages customer subscriptions\n- [Balances](https://docs.useautumn.com/documentation/concepts/balances.md): Understanding how feature balances work in Autumn\n- [Stripe Sync](https://docs.useautumn.com/documentation/concepts/stripe.md): How Autumn creates and manages Stripe objects under the hood\n- [Migrating to Autumn](https://docs.useautumn.com/documentation/getting-started/migration.md): How to migrate your existing Stripe customers to Autumn\n- [MCP Server](https://docs.useautumn.com/documentation/mcp.md): Connect Autumn's MCP server to AI assistants for billing actions, plan management, and request-log investigations.\n- [Setup and payments](https://docs.useautumn.com/documentation/getting-started/setup.md): Implement your app's payments and pricing model\n- [Checking and tracking](https://docs.useautumn.com/documentation/getting-started/gating.md): Give customers access to the right features and limits based on their plan\n- [Build your billing page](https://docs.useautumn.com/documentation/getting-started/display-billing.md): Display usage and billing data in your app for your users\n- [Deploy to production](https://docs.useautumn.com/documentation/getting-started/deploy.md): A checklist to go live with confidence\n- [Recurring Plans](https://docs.useautumn.com/documentation/modelling-pricing/recurring.md): Grant customers a recurring allowance of consumable features like messages, credits, or API calls\n- [Plan Variants](https://docs.useautumn.com/documentation/modelling-pricing/plan-variants.md): Group related plans under one base plan and keep their differences small\n- [One-Off Purchases](https://docs.useautumn.com/documentation/modelling-pricing/one-off-purchases.md): Configure one-time purchases and lifetime plans\n- [Free Plans](https://docs.useautumn.com/documentation/modelling-pricing/free-plans.md): Offer free tiers with usage limits to onboard customers\n- [Credit Systems](https://docs.useautumn.com/documentation/modelling-pricing/credit-systems.md): Learn how to create a credit system in Autumn\n- [Prepaid Pricing](https://docs.useautumn.com/documentation/modelling-pricing/prepaid-pricing.md): Charge customers upfront for a quantity of a feature, and draw from it as usage occurs\n- [Usage-Based Pricing](https://docs.useautumn.com/documentation/modelling-pricing/usage-based-pricing.md): Bill customers based on actual usage at the end of each billing period\n- [Per-Unit Pricing](https://docs.useautumn.com/documentation/modelling-pricing/per-unit-pricing.md): Charge customers based on the number of units they use, such as seats or workspaces\n- [Rollovers](https://docs.useautumn.com/documentation/modelling-pricing/rollovers.md): Allow unused balances to carry over to the next billing period\n- [Proration](https://docs.useautumn.com/documentation/modelling-pricing/proration.md): Handle mid-cycle plan changes with prorated billing\n- [Trials](https://docs.useautumn.com/documentation/modelling-pricing/trials.md): Let customers try paid plans before committing\n- [Auto Top-Ups](https://docs.useautumn.com/documentation/modelling-pricing/auto-top-ups.md): Automatically replenish customer balances when they run low\n- [Spend Limits & Usage Alerts](https://docs.useautumn.com/documentation/modelling-pricing/spend-limits.md): Cap overage spending and get notified when usage crosses thresholds\n- [Add-Ons](https://docs.useautumn.com/documentation/modelling-pricing/add-ons.md): Offer additional plans and features customers can purchase alongside their plan\n- [Graduated Pricing](https://docs.useautumn.com/documentation/modelling-pricing/graduated-pricing.md): Set tiered pricing where different usage ranges are charged at different rates\n- [Volume-Based Tiers](https://docs.useautumn.com/documentation/modelling-pricing/volume-based-tiers.md): Charge a single rate based on the total volume of usage\n- [Entity Plans](https://docs.useautumn.com/documentation/modelling-pricing/entity-plans.md): Give users, workspaces, or projects their own plans and balances under a parent customer\n- [Rewards and Referrals](https://docs.useautumn.com/documentation/modelling-pricing/rewards.md): Learn how to use rewards and referrals to incentivize your customers.\n- [Payment Flow](https://docs.useautumn.com/documentation/customers/payment-flow.md): Hosted checkout pages vs building your own payment flow\n- [Subscription Lifecycle](https://docs.useautumn.com/documentation/customers/subscription-lifecycle.md): Handle upgrades, downgrades, and cancellations\n- [Updating Subscriptions](https://docs.useautumn.com/documentation/customers/updating-subscriptions.md): Modify existing subscriptions - update quantities, cancel, or customize\n- [Custom Plans](https://docs.useautumn.com/documentation/customers/custom-plans.md): Create one-off plan variations for individual customers\n- [Versioning Plans](https://docs.useautumn.com/documentation/customers/versioning.md): How to update and migrate customers between product versions\n- [Billing Reliability](https://docs.useautumn.com/documentation/customers/edge-cases.md): How Autumn handles 3DS, payment failures, and other uncommon states\n- [Creating Customers](https://docs.useautumn.com/documentation/customers/creating-customers.md): Create customers via API or dashboard, link to Stripe, and pre-create for enterprise deals\n- [Managing Customers](https://docs.useautumn.com/documentation/customers/managing-customers.md): Learn how to view and manage customer information in Autumn\n- [Checking access](https://docs.useautumn.com/documentation/customers/check.md): Learn how to check feature access with the `check` endpoint\n- [Tracking usage](https://docs.useautumn.com/documentation/customers/tracking-usage.md): Keep track of your customer's feature usage with the `track` route\n- [Balance Locking](https://docs.useautumn.com/documentation/customers/balance-locking.md): Reserve balance upfront with locks, then confirm or release when the operation completes\n- [Managing Balances](https://docs.useautumn.com/documentation/customers/managing-balances.md): Create, update, and manage balances via the dashboard or API\n- [Billing Controls](https://docs.useautumn.com/documentation/customers/billing-controls.md): Configure overage behavior, spend limits, usage alerts, and auto top-ups per customer or entity\n- [Entities](https://docs.useautumn.com/documentation/customers/feature-entities.md): Learn how to use feature entities to track balances per separate entity, such as a user or a workspace\n- [Webhooks](https://docs.useautumn.com/documentation/webhooks.md): Receive real-time notifications when customer billing events occur\n- [Slack and Discord Notifications](https://docs.useautumn.com/documentation/slack-discord-notifications.md): Send Autumn webhook events to Slack or Discord channels with rich, formatted messages using Svix transformations.\n- [Fail-Open Defaults](https://docs.useautumn.com/documentation/fail-open.md): Keep your app running even when Autumn is unreachable\n- [Rate Limits](https://docs.useautumn.com/documentation/rate-limits.md): Default API rate limits and how to request increases\n- [Vercel AI SDK](https://docs.useautumn.com/documentation/external-providers/ai-sdk.md): Automatically track AI token usage with the Vercel AI SDK\n- [OpenRouter](https://docs.useautumn.com/documentation/external-providers/openrouter.md): Automatically track AI token usage with the OpenRouter SDK\n- [RevenueCat](https://docs.useautumn.com/documentation/external-providers/revenuecat.md): Integrate Autumn with RevenueCat for mobile app billing\n- [Vercel Marketplace](https://docs.useautumn.com/documentation/external-providers/vercel-marketplace.md): Set up the Vercel Marketplace integration in Autumn\n- [Lakehouse Overview](https://docs.useautumn.com/documentation/lakehouse/overview.md): Query your full Autumn dataset directly from your own data warehouse.\n- [Connecting](https://docs.useautumn.com/documentation/lakehouse/connecting.md): Attach ClickHouse or BigQuery to your Autumn Lakehouse catalog.\n- [Schema Reference](https://docs.useautumn.com/documentation/lakehouse/schema.md): Every Lakehouse table and column, with the keys to join on.\n- [Working with balances](https://docs.useautumn.com/documentation/lakehouse/balance-semantics.md): What v2_3_balances, v2_3_breakdowns, and v2_3_rollovers actually mean — and how to reconstruct the figures the API and dashboard show.\n- [Working with invoices](https://docs.useautumn.com/documentation/lakehouse/working-with-invoices.md): Revenue, and paying-customer metrics — the rows to drop and the column that actually carries truth.\n- [Querying](https://docs.useautumn.com/documentation/lakehouse/querying.md): How to address tables, convert types, join, and avoid footguns.\n- [Monetary credits](https://docs.useautumn.com/examples/monetary-credits.md): Grant your users a currency-based balance of credits, that various features can draw from\n- [One-time top ups](https://docs.useautumn.com/examples/prepaid.md): Let customers purchase a prepaid package to top up their balance when it falls low.\n- [Per-seat pricing](https://docs.useautumn.com/examples/per-seat.md): Implement per-seat pricing with free included seats and paid additional seats\n- [Pay-as-you-go overages](https://docs.useautumn.com/examples/pay-as-you-go-overages.md): Let free plan users optionally add a card to pay for usage overages instead of getting blocked\n- [Entity-level balances](https://docs.useautumn.com/examples/entity-balances.md): Grant usage limits per entity, such as 50 credits per user per month\n- [Trial - card required](https://docs.useautumn.com/examples/trial-card-required.md): Enable a trial period where customers must provide payment information upfront.\n- [Trial - card not required](https://docs.useautumn.com/examples/trial-card-not-required.md): Enable a trial period that customers can access without providing payment information\n- [Getting started](https://docs.useautumn.com/cli/getting-started.md): Set up the CLI, connect to Autumn, and sync your pricing config\n- [Configuration reference](https://docs.useautumn.com/cli/config.md): Define features, plans, rewards and settings in autumn.config.ts\n- [Command reference](https://docs.useautumn.com/cli/commands.md): All atmn CLI commands, flags and environment variables\n- [Attach](https://docs.useautumn.com/api-reference/billing/attach.md): Attaches a plan to a customer. Handles new subscriptions, upgrades and downgrades.\n- [Update Subscription](https://docs.useautumn.com/api-reference/billing/billingUpdate.md): Updates an existing subscription. Use to modify feature quantities, cancel, or change plan configuration.\n- [Preview Attach](https://docs.useautumn.com/api-reference/billing/previewAttach.md): Previews the billing changes that would occur when attaching a plan, without actually making any changes.\n- [Preview Update](https://docs.useautumn.com/api-reference/billing/previewUpdate.md): Previews the billing changes that would occur when updating a subscription, without actually making any changes.\n- [Open Customer Portal](https://docs.useautumn.com/api-reference/billing/openCustomerPortal.md): Create a billing portal session for a customer to manage their subscription.\n- [Setup Payment](https://docs.useautumn.com/api-reference/billing/setupPayment.md): Create a payment setup session for a customer to add or update their payment method.\n- [Preview Multi Attach](https://docs.useautumn.com/api-reference/billing/previewMultiAttach.md): Previews the billing changes that would occur when attaching multiple plans, without actually making any changes.\n- [Multi Attach](https://docs.useautumn.com/api-reference/billing/multiAttach.md): Attaches multiple plans to a customer in a single request. Creates a single Stripe subscription with all plans consolidated.\n\n=== https://docs.useautumn.com/llms-full.txt ===\n# Create Balance\nSource: https://docs.useautumn.com/api-reference/balances/createBalance\n\nopenapi POST /v1/balances.create\nCreate a balance for a customer feature.\n\n### Body Parameters\n\n<DynamicParamField type=\"string\">\n  The ID of the customer.\n</DynamicParamField>\n\n<DynamicParamField type=\"string\">\n  The ID of the feature.\n</DynamicParamField>\n\n<DynamicParamField type=\"string\">\n  The ID of the entity for entity-scoped balances (e.g., per-seat limits).\n</DynamicParamField>\n\n<DynamicParamField type=\"number\">\n  The initial balance amount to grant. For metered features, this is the number of units the customer can use.\n</DynamicParamField>\n\n<DynamicParamField type=\"boolean\">\n  If true, the balance has unlimited usage. Cannot be combined with 'included\\_grant'.\n</DynamicParamField>\n\n<DynamicParamField type=\"object\">\n  Reset configuration for the balance. If not provided, the balance is a one-time grant that never resets.\n\n  <Expandable title=\"properties\">\n    <DynamicParamField type=\"'one_off' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'semi_annual' | 'year'\">\n      The interval at which the balance resets (e.g., 'month', 'day', 'year').\n    </DynamicParamField>\n\n    <DynamicParamField type=\"number\">\n      Number of intervals between resets. Defaults to 1 (e.g., interval\\_count: 2 with interval: 'month' resets every 2 months).\n    </DynamicParamField>\n  </Expandable>\n</DynamicParamField>\n\n<DynamicParamField type=\"object\">\n  Rollover configuration for the balance.\n\n  <Expandable title=\"properties\">\n    <DynamicParamField type=\"number | null\" />\n\n    <DynamicParamField type=\"number | null\" />\n\n    <DynamicParamField type=\"'month' | 'forever'\" />\n\n    <DynamicParamField type=\"number\" />\n  </Expandable>\n</DynamicParamField>\n\n<DynamicParamField type=\"number\">\n  Unix timestamp (milliseconds) when the balance expires. Mutually exclusive with reset.\n</DynamicParamField>\n\n<DynamicParamField type=\"number\">\n  Unix timestamp (milliseconds) for the first reset boundary, allowing a custom (e.g. shorter) first period. Requires 'reset', and must occur before 'expires\\_at' if both are provided. Subsequent resets advance by one reset interval from this boundary.\n</DynamicParamField>\n\n<DynamicParamField type=\"string\">\n  A unique identifier for this balance. Use this to target the balance in future update / delete calls.\n</DynamicParamField>\n\n### Response\n\n<DynamicResponseField name=\"success\" type=\"boolean\" />\n\n\n# Delete Balance\nSource: https://docs.useautumn.com/api-reference/balances/deleteBalance\n\nopenapi POST /v1/balances.delete\nDelete a balance for a customer feature. Can only delete a balance that is not attached to a price (eg. you cannot delete messages that have an overage price).\n\n### Body Parameters\n\n=== https://docs.useautumn.com/sitemap.xml ===\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\" xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\">\n    \n  <url>\n    <loc>https://docs.useautumn.com/api-reference/balances/createBalance</loc>\n    <lastmod>2026-06-17T12:15:52.072Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/balances/deleteBalance</loc>\n    <lastmod>2026-03-25T17:15:46.543Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/balances/finalizeLock</loc>\n    <lastmod>2026-03-12T15:04:01.459Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/balances/trackTokens</loc>\n    <lastmod>2026-06-12T13:14:25.191Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/balances/updateBalance</loc>\n    <lastmod>2026-07-10T17:28:46.992Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/attach</loc>\n    <lastmod>2026-09-14T20:54:12.696Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/billingUpdate</loc>\n    <lastmod>2026-09-15T15:16:49.796Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/createSchedule</loc>\n    <lastmod>2026-09-14T20:54:12.702Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/import</loc>\n    <lastmod>2026-09-14T20:54:12.725Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/multiAttach</loc>\n    <lastmod>2026-09-14T20:54:12.677Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/multiUpdate</loc>\n    <lastmod>2026-08-27T18:10:27.481Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/openCustomerPortal</loc>\n    <lastmod>2026-02-20T11:43:53.631Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/previewAttach</loc>\n    <lastmod>2026-09-14T20:54:12.703Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/previewMultiAttach</loc>\n    <lastmod>2026-09-14T20:54:12.704Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/previewMultiUpdate</loc>\n    <lastmod>2026-09-14T20:54:12.702Z</lastmod>\n  </url>\n\n  <url>\n    <loc>https://docs.useautumn.com/api-reference/billing/previewUpdate</loc>\n\n","type":"text"}]}
Thinking…

This is very useful. Autumn is a hosted billing/monetization product (useautumn.com) with a cloud dashboard, REST API, SDKs, CLI, and MCP server. The user wants me to build a simple example, explain pricing, and briefly say whether it will be easy for me to manage.

Now I need to understand the developer workflow via SDK/API. I should read the "setup/payments" getting started docs, the API reference core (attach, check, track), and pricing docs.

Key concerns:

  1. Does Autumn have a server-side SDK for Node/Python? Let me check the getting-started/setup.md and the ai-sdk.md, and the welcome.md.
  2. Pricing: "how pricing works" - meaning Autumn's own pricing plans (for the customer of Autumn) OR how Autumn handles pricing for their product? The user says "Tell me how pricing works" in context of building an example using Autumn. Likely they want to know how the product's pricing model works (how you model pricing in Autumn). But could also mean how much Autumn costs. I should cover what can be determined: Autumn's pricing for modeling (features/plans/credits/usage-based), and also note the product's own commercial pricing if documented publicly.

Actually "Tell me how pricing works" — given we're building an example, likely "how Autumn's pricing engine works" (plans, features, metered/usage-based). I'll explain both briefly if I find Autumn's own pricing page. But primarily the pricing modeling.

  1. Whether this product will be easy for me (the agent) to manage: I need to assess. Autumn has a dashboard for config, but also an API to create products/plans/features? Let me check. There's an MCP server for billing actions. And a CLI with autumn.config.ts. The SDK (useAutumn) is for attach/check/track at runtime. But creating plans/features might be dashboard-only or via CLI/API.

Let me fetch the key docs:

  • welcome.md
  • documentation/concepts/overview.md, plans.md, features.md, plan-items.md, subscriptions.md, balances.md
  • getting-started/setup.md
  • api-reference/billing/attach.md
  • customers/check.md, tracking-usage.md, creating-customers.md

Let me use the .md URLs directly.

$ curl -s --max-time 20 "https://docs.useautumn.com/welcome.md"; echo "=====SETUP====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/getting-started/setup.md"{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Welcome to Autumn\n\n> Drop-in, open-source control layer for AI and SaaS monetization.\n\n## What is Autumn?\n\nAutumn is your source of truth for billing and entitlements between your application and Stripe.\n\nIt manages subscription state, credit balances, feature entitlements, and usage enforcement — the logic you'd otherwise build and maintain across your codebase, database, and Stripe webhooks.\n\nYour app can query Autumn inline to determine what a customer is allowed to do (send an AI message, access SSO, add a seat) and to track usage against their balance.\n\nBecause billing logic lives in Autumn, pricing changes and custom deals become a simple configuration change. No migrations or rebuild.\n\n## Why use Autumn?\n\nAI monetization is harder than what came before. For reference, OpenAI wrote a [post](https://openai.com/index/beyond-rate-limits/) about their in-house system.\n\n| Area             | What you'd build                                                                                 |\n| ---------------- | ------------------------------------------------------------------------------------------------ |\n| Subscriptions    | Checkouts, proration, schedules, add-ons, trials.                                                |\n| Credit ledgers   | Real-time enforcement, periodic and one-time grants, rollovers, expiration, concurrency control. |\n| Observability    | Usage history charts, groups and filters, logs, ClickHouse.                                      |\n| Entitlements     | Feature gating per plan, boolean and metered features, seat-based allowances.                    |\n| Billing Controls | Spend caps, auto top-ups, overage handling, usage alerts.                                        |\n| Pricing changes  | Versioning, grandfathering, migration scripts, backwards compatibility.                          |\n| Enterprise       | Custom contracts, tiered pricing, per-customer credit grants, expansion logic.                   |\n| Edge cases       | Plan switching, monthly↔annual changes, failed payments, 3DS, race conditions, refunds.          |\n\nBilling starts with a simple checkout flow, and balloons in complexity as you add more features and scale. And when you want to change your pricing, you need to rebuild everything. Yet, it's a critical part of your product that you cannot afford to get wrong.\n\nYou can choose to build this yourself, or use Autumn to offload all this logic out of your codebase. It's less work, more flexible, and more reliable.\n\n## How is this different?\n\nOther billing tools are designed for post-hoc invoicing: you send usage events, they generate invoices at end of period. Your app still owns access control, usage limits, and plan change logic.\n\nAutumn is a real-time system of record. You can query it for the current state of any customer (plan, entitlements, balances) inline, via cache, or via webhooks. Because Autumn owns the state (not your code or database), edge cases like proration, failed payments, and concurrency are handled automatically. Pricing changes become config, not code.\n\nAutumn builds on top of Stripe rather than replacing it. Your subscriptions, customers, and payment details stay in your own Stripe account.\n\n<Check>\n  While Autumn's core focus is credit-based AI monetization, it handles any SaaS pricing model. Many of our users have no usage-based features at all, and just prefer the developer experience (eg, no webhooks).\n</Check>\n\n## FAQ\n\n<AccordionGroup>\n  <Accordion title=\"Do I still need Stripe?\">\n    Yes. Autumn works with Stripe — it handles the billing logic that Stripe doesn't. You keep your Stripe account, your customer relationships, and your payment data. Autumn sits between your app and Stripe, managing webhooks, usage limits, and state.\n\n    Your subscriptions live in Stripe. You're never locked in.\n  </Accordion>\n\n  <Accordion title=\"Do I need to call Autumn before every action?\">\n    For latency-sensitive operations, you may not want to make an `autumn.check()` network call before every action.\n\n    You can either cache the Autumn customer data on your end, or use the `customer.products.updated` webhook to replicate Autumn state into your own system.\n  </Accordion>\n\n  <Accordion title=\"What if Autumn goes down?\">\n    Not being able to reach Autumn does not mean your app goes down. The SDKs default to fail-open and fail-fast, meaning in a worst case, some users get temporary additional access.\n\n    We can help reconcile usage tracking and balances afterward if needed.\n  </Accordion>\n\n  <Accordion title=\"How is Autumn different from Orb or Metronome?\">\n    Orb and Metronome focus on usage metering — tracking how much customers consume for end-of-period invoicing. You still build access control and state management separately.\n\n    Autumn is a complete system of record: usage metering, entitlements, feature gating, and billing state in one API.\n  </Accordion>\n\n  <Accordion title=\"Am I locked in?\">\n    Autumn is open source. You can self-host anytime, or export all your data. Your Stripe subscriptions, customers, and payment details remain yours.\n\n    You can migrate gradually: replicate customer state into your own system via webhooks, then make a full transition.\n  </Accordion>\n\n  <Accordion title=\"Can you do the implementation for us?\">\n    If you're setting up payments for the first time, most teams go live in under an hour. Migrating from an existing billing system typically takes 1–2 weeks depending on complexity.\n\n    For larger companies, we provide a forward-deployed service: dual-write to your internal system and Autumn, then migrate over.\n  </Accordion>\n\n  <Accordion title=\"Can you handle our event volume?\">\n    Autumn supports 10,000+ events per second per end customer. If you have specific throughput requirements, reach out and we'll walk through the architecture.\n  </Accordion>\n</AccordionGroup>\n\n<CardGroup cols={2}>\n  <Card title=\"Reach out to us\" icon=\"envelope\" href=\"mailto:hey@useautumn.com\">\n    We'll help you model your pricing and go live in a couple of days.\n  </Card>\n\n  <Card title=\"Join us on Discord\" icon=\"discord\" href=\"https://discord.gg/STqxY92zuS\">\n    Connect with us, other users, and get integration support within minutes.\n  </Card>\n</CardGroup>\n=====SETUP=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Setup and payments\n\n> Implement your app's payments and pricing model\n\nIn this example we'll create the pricing for a premium AI chatbot. We're going to have:\n\n* A <Badge color=\"green\">Free</Badge> plan that gives users 5 chat messages per month for free\n* A <Badge color=\"blue\">Pro</Badge> plan that gives users 100 chat messages per month for \\$20 per month.\n\n<Steps>\n  <Step title=\"Create your pricing plans\">\n    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.\n\n    <Tip>\n      Browse our [Examples](/examples) for guides on setting up credit systems, top ups and other common pricing models.\n    </Tip>\n\n    <Tabs>\n      <Tab title=\"CLI\">\n        Run the following command in your root directory:\n\n        <CodeGroup>\n          ```bash bun theme={null}\n          bunx atmn init\n          ```\n\n          ```bash npm theme={null}\n          npx atmn init\n          ```\n\n          ```bash pnpm theme={null}\n          pnpm dlx atmn init\n          ```\n        </CodeGroup>\n\n        This asks how you want to connect (sign in, or create a sandbox with no account), then creates an `autumn/` folder with an `autumn.config.ts` inside. Replace the contents of that file with the code below, or view our [config reference](/cli/config) to build your own.\n\n        ```typescript autumn.config.ts [expandable] theme={null}\n        import { atmn, feature, plan } from \"atmn\";\n\n        // Features\n        export const messages = feature({\n          featureId: \"messages\",\n          name: \"Messages\",\n          type: \"metered\",\n          consumable: true,\n        });\n\n        // Plans\n        export const free = plan({\n          planId: \"free\",\n          versionSlug: \"v1\",\n          active: true,\n          name: \"Free\",\n          autoEnable: true,\n          items: [\n            // 5 messages per month\n            {\n              featureId: messages.featureId,\n              included: 5,\n              reset: { interval: \"month\" },\n            },\n          ],\n        });\n\n        export const pro = plan({\n          planId: \"pro\",\n          versionSlug: \"v1\",\n          active: true,\n          name: \"Pro\",\n          price: {\n            amount: 20,\n            interval: \"month\",\n          },\n          items: [\n            // 100 messages per month\n            {\n              featureId: messages.featureId,\n              included: 100,\n              reset: { interval: \"month\" },\n            },\n          ],\n        });\n\n        export default atmn({ features: [messages], plans: [free, pro] });\n        ```\n\n        Then, preview your changes against Autumn's sandbox environment.\n\n        <CodeGroup>\n          ```bash bun theme={null}\n          bunx atmn push\n          ```\n\n          ```bash npm theme={null}\n          npx atmn push\n          ```\n\n          ```bash pnpm theme={null}\n          pnpm dlx atmn push\n          ```\n        </CodeGroup>\n\n        Once the preview looks right, apply it:\n\n        <CodeGroup>\n          ```bash bun theme={null}\n          bunx atmn push --yes\n          ```\n\n          ```bash npm theme={null}\n          npx atmn push --yes\n          ```\n\n          ```bash pnpm theme={null}\n          pnpm dlx atmn push --yes\n          ```\n        </CodeGroup>\n\n        <Tip>\n          If you already have plans created in the dashboard, `atmn init` pulls them\n          into your config for you. Run `atmn pull` at any time to do it again.\n        </Tip>\n      </Tab>\n\n      <Tab title=\"Dashboard\">\n        Create your [Autumn account](https://app.useautumn.com/), and the Free and Pro plans in the [Plans](https://app.useautumn.com/products) tab.\n\n        <AccordionGroup>\n          <Accordion title=\"Free Plan\">\n            * On the [Plans](https://app.useautumn.com/products) page, click **Create Plan**.\n            * Name the plan (eg, \"Free\") and select plan type `Free`\n            * Toggle the `auto-enable` flag, so that the plan is assigned whenever customers are created\n            * In the plan editor, click **Add Feature to Plan**, and create a `Metered`, `Consumable` feature for \"messages\"\n            * Configure the plan to grant `5` messages, and set the interval to `per month`\n            * Click **Save**\n\n            <Frame hint=\"Your Free plan should look like this\">\n              <img className=\"block dark:hidden\" src=\"https://mintcdn.com/autumn-b9b4c0fb/df8oGyhsA_ngL7c4/assets/getting-started/free-plan-light.png?fit=max&auto=format&n=df8oGyhsA_ngL7c4&q=85&s=40b1906694ed200d91ddfbd9b972c294\" width=\"1476\" height=\"1284\" data-path=\"assets/getting-started/free-plan-light.png\" />\n\n              <img className=\"hidden dark:block\" src=\"https://mintcdn.com/autumn-b9b4c0fb/df8oGyhsA_ngL7c4/assets/getting-started/free-plan-dark.png?fit=max&auto=format&n=df8oGyhsA_ngL7c4&q=85&s=2eab7a285e28f85e188136ae2308ecee\" width=\"1468\" height=\"1266\" data-path=\"assets/getting-started/free-plan-dark.png\" />\n            </Frame>\n          </Accordion>\n\n          <Accordion title=\"Pro Plan\">\n            * On the [Plans](https://app.useautumn.com/products) page, click **Create Plan**.\n            * Name the plan (eg, \"Pro\") and select plan type `Paid`, `Recurring`, and set the price to `$20` per month\n            * In the plan editor, click **Add Feature to Plan**, and add the `messages` feature that you created in the Free plan\n            * Configure the plan to grant `100` messages, and set the interval to `per month`\n            * Click **Save**\n\n            <Frame hint=\"Your Pro plan should look like this\">\n              <img className=\"block dark:hidden\" src=\"https://mintcdn.com/autumn-b9b4c0fb/df8oGyhsA_ngL7c4/assets/getting-started/pro-plan-light.png?fit=max&auto=format&n=df8oGyhsA_ngL7c4&q=85&s=729fd52cd39deab4741ea88f90917e2f\" width=\"1448\" height=\"1338\" data-path=\"assets/getting-started/pro-plan-light.png\" />\n\n              <img className=\"hidden dark:block\" src=\"https://mintcdn.com/autumn-b9b4c0fb/df8oGyhsA_ngL7c4/assets/getting-started/pro-plan-dark.png?fit=max&auto=format&n=df8oGyhsA_ngL7c4&q=85&s=7a27b31f42870bfdd8aed3f87084ae28\" width=\"1452\" height=\"1344\" data-path=\"assets/getting-started/pro-plan-dark.png\" />\n            </Frame>\n          </Accordion>\n        </AccordionGroup>\n      </Tab>\n    </Tabs>\n  </Step>\n\n  <Step title=\"Installation\">\n    [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.\n\n    ```bash .env theme={null}\n    AUTUMN_SECRET_KEY=am_sk_test_42424242...\n    ```\n\n    <CodeGroup>\n      ```bash bun theme={null}\n      bun add autumn-js\n      ```\n\n      ```bash npm theme={null}\n      npm install autumn-js\n      ```\n\n      ```bash pnpm theme={null}\n      pnpm add autumn-js\n      ```\n\n      ```bash yarn theme={null}\n      yarn add autumn-js\n      ```\n\n      ```bash pip theme={null}\n      pip install autumn-sdk\n      ```\n    </CodeGroup>\n  </Step>\n\n  <Step title=\"Create an Autumn customer\">\n    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.\n\n    <CodeGroup>\n      ```typescript TypeScript theme={null}\n      import { Autumn } from \"autumn-js\";\n\n      const autumn = new Autumn({\n          secretKey: \"am_sk_42424242\",\n      });\n\n      const customer = await autumn.customers.getOrCreate({\n          customerId: \"user_or_org_id_from_auth\",\n          name: \"John Doe\",\n          email: \"john@example.com\",\n      });\n      ```\n\n      ```python Python theme={null}\n      import asyncio\n      from autumn_sdk import Autumn\n\n      autumn = Autumn('am_sk_42424242')\n\n      async def main():\n          customer = await autumn.customers.get_or_create(\n              customer_id=\"user_or_org_id_from_auth\",\n              name=\"John Doe\",\n              email=\"john@example.com\",\n          )\n\n      asyncio.run(main())\n      ```\n\n      ```bash cURL theme={null}\n      curl --request POST \\\n        --url https://api.useautumn.com/v1/customers \\\n        --header 'Authorization: Bearer am_sk_42424242' \\\n        --header 'Content-Type: application/json' \\\n        --data '{\n        \"customer_id\": \"user_or_org_id_from_auth\",\n        \"name\": \"John Doe\",\n        \"email\": \"john@example.com\"\n      }'\n      ```\n    </CodeGroup>\n\n    <Check>\n      Autumn's customer ID is the same as your internal user or org ID generated\n      from your auth provider. No need to store any extra IDs.\n    </Check>\n\n    In the Autumn dashboard, you will see your user under the [customers](https://app.useautumn.com/customers) page.\n  </Step>\n\n  <Step title=\"Stripe Payment Flow\">\n    Call `attach` when the customer wants to purchase the <Badge color=\"blue\">Pro</Badge> plan. This will return a Stripe payment URL. Once they've paid, Autumn will grant access to \"100 messages per month\" defined in Step 1.\n\n    <CodeGroup>\n      ```typescript TypeScript theme={null}\n      import { Autumn } from \"autumn-js\";\n\n      const autumn = new Autumn({\n          secretKey: \"am_sk_42424242\",\n      });\n\n      const response = await autumn.billing.attach({\n          customerId: \"user_or_org_id_from_auth\",\n          planId: \"pro\",\n          redirectMode: \"always\",\n      });\n\n      // Redirect customer to complete payment or confirm plan change\n      redirect(response.paymentUrl);\n      ```\n\n      ```python Python theme={null}\n      import asyncio\n      from autumn_sdk import Autumn\n\n      autumn = Autumn('am_sk_42424242')\n\n      async def main():\n        response = await autumn.billing.attach(\n            customer_id='user_or_org_id_from_auth',\n            plan_id='pro',\n            redirect_mode='always',\n        )\n\n      asyncio.run(main())\n      ```\n\n      ```bash cURL theme={null}\n      curl -X POST 'https://api.useautumn.com/v1/attach' \\\n      -H 'Authorization: Bearer am_sk_42424242' \\\n      -H 'Content-Type: application/json' \\\n      -d '{\n        \"customer_id\": \"user_or_org_id_from_auth\",\n        \"plan_id\": \"pro\",\n        \"redirect_mode\": \"always\"\n      }'\n      ```\n    </CodeGroup>\n\n    <Note>\n      Use Stripe's test card `4242 4242 4242 4242` to make a purchase in sandbox.\n      You can enter any Expiry and CVV.\n    </Note>\n\n    This can be used for any plan changes scenario (upgrades, downgrades, one-time topups, renewals, etc).\n\n    Upgrades will happen immediately, and downgrades will be scheduled for the next billing cycle.\n\n    <Note>\n      The **`redirectMode: \"always\"`** flag will always return a payment URL.\n\n      New purchases redirect to Stripe Checkout to enter payment details, and subsequent charges redirect to an Autumn hosted, one-click confirmation page.\n\n      You can build your own billing confirmation flows by using the [previewAttach](/api-reference/billing/previewAttach) function.\n    </Note>\n  </Step>\n</Steps>\n\n**Next: Track and limit usage**\n\nNow 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.\n\n<Card title=\"Track and limit usage\" href=\"/documentation/getting-started/gating\">\n  Enforce usage limits and feature permissions using Autumn's `check` and\n  `track` functions\n</Card>\n","type":"text"}]}
$ curl -s --max-time 20 "https://docs.useautumn.com/documentation/concepts/overview.md"; echo "=====PLANS====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/concepts/plans.md"; echo …{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
curl -s --max-time 20 "https://docs.useautumn.com/documentation/concepts/overview.md"; echo "=====PLANS====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/concepts/plans.md"; echo "=====FEATURES====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/concepts/features.md"

{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# How It Works\n\n> How features, plans, subscriptions and balances fit together\n\nAutumn's data model has a clear pipeline: you define **features**, bundle them into **plans** with pricing, and when a plan is attached to a customer, it creates a **subscription** and provisions **balances** that you can check and track in real-time.\n\n```mermaid actions={false} theme={null}\n%%{init: {'flowchart': {'padding': 6, 'nodeSpacing': 10, 'rankSpacing': 20, 'subGraphTitleMargin': {'top': 4, 'bottom': 12}}} }%%\nflowchart LR\n    subgraph features[\"**Features**\"]\n        F3[\"AI Credits\"]:::credit\n    end\n\n    subgraph plan[\"**Plan**\"]\n        direction TB\n        subgraph price[\"Price\"]\n            P1[\"$200/year\"]:::pricing\n        end\n        subgraph planItems[\"Plan items\"]\n            PI1[\"200 AI credits/month\"]:::credit\n        end\n        price ~~~ planItems\n    end\n\n    subgraph customer[\"**Customer**\"]\n        direction TB\n        subgraph customerPlans[\"Subscription\"]\n            C1[\"$200/year\"]:::pricing\n        end\n        subgraph balances[\"Balances\"]\n            B1[\"146/200 AI credits left\"]:::credit\n        end\n        customerPlans ~~~ balances\n    end\n\n\n    features ~~~ plan ~~~ customer\n\n    classDef credit fill:#22c55e30,stroke:#22c55e\n    classDef pricing fill:#ec489930,stroke:#ec4899\n\n    style features fill:#eab30820,stroke:#eab308\n    style plan fill:#7c3aed10,stroke:#7c3aed\n    style customer fill:#0ea5e910,stroke:#0ea5e9\n\n    style price fill:none,stroke:none\n    style planItems fill:none,stroke:none\n    style customerPlans fill:none,stroke:none\n    style balances fill:none,stroke:none\n```\n\n## Features\n\nFeatures represent the parts of your product you want to control access to. There are three types: **boolean** (on/off flags like premium analytics), **consumable** (usage that resets, like API requests or credits), and **non-consumable** (persistent quantities like seats or storage).\n\nFeatures are the atomic building blocks — everything else is built on top of them.\n\n<Card title=\"Features\" icon=\"puzzle-piece\" href=\"/documentation/concepts/features\">\n  Learn about feature types and how to create them\n</Card>\n\n## Plans\n\nPlans bundle features together with a base price. Each plan represents a distinct pricing tier or package you offer — free, pro, enterprise, or any add-on. You define which features are included, how they're priced, and any properties like trials or auto-enable.\n\n<Card title=\"Plans\" icon=\"layer-group\" href=\"/documentation/concepts/plans\">\n  Learn about plan pricing, properties and groups\n</Card>\n\n## Plan Items\n\nWhen you add a feature to a plan, it becomes a **plan item** with its own configuration. Included items grant a usage amount at no extra cost. Priced items add billing — either prepaid or usage-based — with options for billing units, tiers, and proration.\n\nPlan items are where the \"what\" (features) meets the \"how much\" (pricing).\n\n<Card title=\"Plan Items\" icon=\"sliders\" href=\"/documentation/concepts/plan-items\">\n  Configure grants, pricing and usage models\n</Card>\n\n## Subscriptions\n\nWhen you attach a plan to a customer, Autumn creates a Stripe subscription under the hood and provisions balances for each feature in the plan. Subscriptions track status (active, trialing, past\\_due, etc.) and handle the payment lifecycle.\n\n<Card title=\"Subscriptions\" icon=\"arrows-repeat\" href=\"/documentation/concepts/subscriptions\">\n  How Autumn manages Stripe subscriptions\n</Card>\n\n## Balances\n\nBalances are the customer-facing result of everything above. Each plan item becomes a balance that tracks what the customer has been granted, what they've used, and what remains. Balances from multiple sources (plans, add-ons, top-ups) stack together, with shorter-interval balances consumed first.\n\nYour app interacts with Autumn primarily through balances — calling `/check` to gate access and `/track` to record usage.\n\n<Card title=\"Balances\" icon=\"scale-balanced\" href=\"/documentation/concepts/balances\">\n  Understand balance stacking, resets and deduction order\n</Card>\n\n## Runtime\n\nOnce your features, plans and pricing are configured, your app interacts with Autumn through a few core endpoints.\n\n<Steps>\n  <Step title=\"Model your pricing in Autumn\">\n    Model your pricing plans in the Autumn UI, or through a config file. Define your free, paid and any add-on pricing tiers.\n\n    You can link features to these plans and define their usage limits: both recurring (monthly, yearly), one-time top ups, rollovers, etc.\n  </Step>\n\n  <Step title=\"Handle payments\">\n    The [attach](/api-reference/billing/attach) endpoint subscribes a customer to a plan or purchases a one-time product. It handles new subscriptions, upgrades, downgrades and add-ons — creating the Stripe subscription and provisioning balances automatically.\n\n    Once paid, Autumn grants access to the features on their plan.\n  </Step>\n\n  <Step title=\"Check permissions and limits\">\n    When a customer tries to do something (eg, use a credit), [check](/api-reference/core/check) in real-time whether they're allowed to based on their active plans and remaining balance.\n\n    Set `send_event` to atomically deduct usage while checking.\n  </Step>\n\n  <Step title=\"Track usage\">\n    If the customer is allowed access, let them use the feature. Afterwards, [track](/api-reference/core/track) the usage to update their balance, or bill them for any usage-pricing.\n  </Step>\n</Steps>\n\nAutumn also provides endpoints to [get customer billing data](/api-reference/customers/getOrCreateCustomer) (subscriptions, balances, invoices, payment methods), open Stripe billing portal, display usage analytics, handle org billing, and more.\n=====PLANS=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Plans\n\n> Learn about plans in Autumn and how to create them\n\nPlans are the separate packages that define what your customers get and how much they should be billed for it. Each plan you create is a distinct combination of these features and prices.\n\nFor example, you can define a separate plan for all the pricing tiers (eg free plan, team plan, enterprise tier) you offer, or all your different price variations (annual billing, monthly billing, usage-based billing)\n\n## Plan Price\n\nWhen you create a plan, you can set its price:\n\n* **Free** - no price, free to use\n* **Paid, one-off** - a fixed amount a user will be charged. This is often used for one-time topups.\n* **Paid, recurring** - a fixed amount a user will be charged per unit of time. This is often used for subscriptions.\n* **Variable** - there is no fixed price for this plan. The plan is priced purely based on feature usage or quantity purchased.\n\n## Multiple Currencies\n\nMulti-currency pricing is currently in preview - contact us to enable it for your organization.\n\nPlan prices are in your organization's default currency. To sell the same plan in other currencies, add `additional_currencies` wherever a price is defined - the base price, a priced feature, or each tier of a tiered price:\n\n```json theme={null}\n{\n  \"plan_id\": \"pro\",\n  \"price\": {\n    \"amount\": 20,\n    \"interval\": \"month\",\n    \"additional_currencies\": [\n      { \"currency\": \"eur\", \"amount\": 18 },\n      { \"currency\": \"gbp\", \"amount\": 16 }\n    ]\n  }\n}\n```\n\nEach amount is set explicitly per currency - Autumn does not apply exchange rates. Tier boundaries stay the same across currencies; only the amounts differ.\n\nEach customer is billed in a single currency. You can set it when creating the customer, pass it on their first `attach`, or let it default to your organization's currency. Once a customer has paid in a currency, they're locked to it (Stripe requires this), and attaching a plan that doesn't offer a price in their currency fails with a `currency_mismatch` error.\n\nUnder the hood, Autumn creates a separate Stripe price per currency under the same Stripe product, on demand when a customer first attaches in that currency.\n\n## Plan Features\n\nPlans are made up of a list of [features](/documentation/concepts/features). These can be:\n\n* **Included Features** - features that come with the plan for no additional cost. These can be boolean flags, or metered features with a limit.\n* **Priced Features** - features that are billable based on usage of a feature. These can also have an included amount, and a prepaid or usage-based price.\n\nWhen a plan is enabled for a customer, they will be granted access to the features defined in the plan.\n\n## Plan Properties\n\n**Auto-enable**\n\nSet this is the plan should be automatically applied to a customer when they're created. This is typically for free plans that give customers access to a limited set of features without paying.\n\n**Add ons**\n\nSet this if the plan is an add on. This will mean it can be purchased together with other plans. If this flag is not set, then enabling a plan will replace the existing plan.\n\n**Plan Groups**\n\nIf you have multiple groups of plans, and customers can have an active plan from each of these subscription groups at the same time, group the plans together. All plan tiers from the same group should have the same value.\n\n<Info>\n  **Example**\n\n  Let's say you have two different types of chatbots - one for customer support and one for sales. You want customers to be able to have both types of chatbots at the same time, but only one tier from each type.\n\n  You would create two plan groups:\n\n  1. \"Customer Support Chatbots\" (group: \"support\")\n\n     * Basic (\\$49/month - 1,000 tickets)\n     * Advanced (\\$149/month - 5,000 tickets)\n     * Enterprise (\\$399/month - Unlimited tickets)\n\n  2. \"Sales Chatbots\" (group: \"sales\")\n     * Starter (\\$79/month - 500 leads)\n     * Growth (\\$199/month - 2,000 leads)\n     * Enterprise (\\$499/month - Unlimited leads)\n\n  This way, a customer could have both the \"Advanced Support\" chatbot and the \"Starter Sales\" chatbot active at the same time, but they couldn't have both \"Basic Support\" and \"Advanced Support\" active together.\n</Info>\n\n## Trials\n\nUnder plan settings, you can set a free trial for a plan. This will give customers a set amount of days to try the plan for free.\n\nYou can set whether a card is required for the free trial. If a card is not required, you can `attach` the plan to a customer without them having to go through a checkout flow or have a card on file. It will be automatically expired after the free trial period.\n\nEach customer can only have access to a plan's trial **once**. If they try to attach the plan again, the trial will be ignored.\n\nFor a step-by-step guide on enabling, cancelling and ending trials, see our examples:\n\n* [Trial - card required](/examples/trial-card-required)\n* [Trial - card not required](/examples/trial-card-not-required)\n\n<Tip>\n  When creating an Autumn customer, you can set the `customer.fingerprint` field (eg. device ID, browser fingerprint). This will limit the customer to one trial of the plan per fingerprint to prevent abuse.\n</Tip>\n\n## Plan Variants\n\nPlan variants are named alternatives of a base plan. They inherit the base plan and store only the differences, such as a different billing interval, a different experiment package, or a different included usage ladder.\n\nFor example, an annual Pro plan can be modeled as a variant of monthly Pro:\n\n```json theme={null}\n{\n  \"variant_plan_id\": \"pro_annual\",\n  \"name\": \"Pro Annual\",\n  \"customize\": {\n    \"price\": { \"amount\": 200, \"interval\": \"year\" }\n  }\n}\n```\n\nVariants are useful for monthly/annual pricing, A/B testing plan packages, and volume-based offers that share most of the same features.\n=====FEATURES=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Features\n\n> Learn about features in Autumn and how to create them\n\nFeatures represent the parts of your product that you want to control access to, based on the pricing plan a customer is on. There are 2 key types of features you can create:\n\n* **Metered features**: features that require you to keep track of a usage balance (eg, credits, API requests)\n* **Boolean features**: features that can be either enabled or disabled (eg, access to a premium analytics dashboard).\n\nWhen you create a feature, you can set a display name, and it's ID. This will be used to identify the feature when you make API calls to Autumn, to check or tracking usage of the feature.\n\n## Metered features\n\nMetered features can either be `consumable` or `non-consumable`.\n\n* **Consumable**: features that can be used up and replenished, either by recurring resets or purchases. For example, credits, API requests.\n* **Non-consumable**: features that are used persistently. For example, seats, storage, workspaces.\n\nWhen adding features to a plan, you will be able to set reset cycles for `consumable` features, and proration behavior for `non-consumable` features.\n\nUnder the \"advanced\" section of the feature creation sheet, you can also define [event names](/documentation/customers/tracking-usage#using-event-names). This gives you more control over how events interact with customer balances in Autumn.\n\nMetered features can each act as their own, standlone balance, or be added to a [credit system](/documentation/modelling-pricing/credit-systems). This lets you define credit costs per feature, and let many features draw from a common credit balance.\n\n## Boolean features\n\nBoolean features are for your features that can be either enabled or disabled. Think of them like feature flags to gate specific parts of your application based on what product a user has (eg, access to a premium analytics dashboard).\n\nFor these features, there is no configuration needed to be set. If you add them to a product, users on that product will be granted [access to the feature](/documentation/customers/check#checking-boolean-features).\n","type":"text"}]}
Thinking…

I have a good picture. Now I need to check:

  1. The hidden "gating" doc for check/track.
  2. The attach API reference for parameters and response schema.
  3. The check/track API reference.
  4. The CLI docs (config).
  5. Pricing (the product's own pricing) — maybe on useautumn.com/pricing.

Let me also check the MCP doc, since it might be relevant for "will this product be easy for me to manage." MCP server for AI assistants could be the way I'd manage it. Also the CLI. Let me fetch gating.md, check.md, tracking-usage.md, attach.md, and the pricing page.

$ curl -s --max-time 20 "https://docs.useautumn.com/documentation/getting-started/gating.md"; echo "=====CHECK====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/customers/check.md";…{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
curl -s --max-time 20 "https://docs.useautumn.com/documentation/getting-started/gating.md"; echo "=====CHECK====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/customers/check.md"; echo "=====TRACK====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/customers/tracking-usage.md"

{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Checking and tracking\n\n> Give customers access to the right features and limits based on their plan\n\nTypically, your users should get access to different features and usage limits, depending on their plan.\n\nAutumn handles your customer's payments and grants them the features defined in your plan configuration. There are 2 functions you need to enforce limits and gating:\n\n* `check` for feature access, before allowing a user to do something\n* `track` the usage in Autumn afterwards (if needed)\n\nThis example will continue from before: a 2-tier pricing model for a chatbot.\n\n<Note>\n  This guide shows an asynchronous approach to checking and tracking. You can also [check and reserve](/documentation/customers/check#checking-and-reserving-usage) balance in a single, atomic API call for concurrent events.\n</Note>\n\n### Checking feature access\n\nCheck if a user has enough remaining balance of messages, before executing the action. The `feature_id` used here is defined by you when you create the feature in Autumn.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({\n    secretKey: 'am_sk_42424242',\n  });\n\n  // Check if user can send 1 message\n  const { allowed } = await autumn.check({\n    customerId: \"user_or_org_id_from_auth\",\n    featureId: \"messages\",\n    requiredBalance: 1,\n  });\n\n  if (!allowed) {\n    console.log(\"User has run out of messages\");\n    return;\n  }\n  ```\n\n  ```python Python theme={null}\n  import asyncio\n  from autumn_sdk import Autumn\n\n  autumn = Autumn('am_sk_42424242')\n\n  async def main():\n      # Check feature access\n      response = await autumn.check(\n          customer_id='user_or_org_id_from_auth',\n          feature_id='messages',\n          required_balance=1,\n      )\n\n  asyncio.run(main())\n  ```\n\n  ```bash cURL theme={null}\n  # Check feature access\n  curl -X POST 'https://api.useautumn.com/v1/check' \\\n    -H 'Authorization: Bearer am_sk_42424242' \\\n    -H 'Content-Type: application/json' \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"messages\",\n      \"required_balance\": 1\n    }'\n  ```\n</CodeGroup>\n\n<Tip>\n  You can also use `check` to [gate boolean features](/documentation/customers/check#checking-boolean-features) (non-metered features), such as access to \"premium AI models\".\n</Tip>\n\n### Tracking usage\n\nAfter the user has successfully used a chatbot message, you can record the usage in Autumn. This will decrement the user's message balance.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  // Your own function to send the chat message\n\n  // Then record 1 message used\n  await autumn.track({\n    customerId: \"user_or_org_id_from_auth\",\n    featureId: \"messages\",\n    value: 1,\n  });\n  ```\n\n  ```python Python theme={null}\n  import asyncio\n  from autumn_sdk import Autumn\n\n  autumn = Autumn('am_sk_42424242')\n\n  # Your own function to send the chat message\n\n  # Then record 1 message used\n  async def main():\n      await autumn.track(\n          customer_id='user_or_org_id_from_auth',\n          feature_id='messages',\n          value=1,\n      )\n\n  asyncio.run(main())\n  ```\n\n  ```bash cURL theme={null}\n  # Your own function to send the chat message\n\n  # Then record 1 message used\n  curl -X POST 'https://api.useautumn.com/v1/track' \\\n    -H 'Authorization: Bearer am_sk_42424242' \\\n    -H 'Content-Type: application/json' \\\n    -d '{\n      \"customer_id\": \"user_or_org_id_from_auth\",\n      \"feature_id\": \"messages\",\n      \"value\": 1\n    }'\n  ```\n</CodeGroup>\n\nOnce you send usage events, you can verify their receipt in the Autumn dashboard, on the [customer](https://app.useautumn.com/customers) detail page.\n\n<Warning>\n  You should always handle access checks and usage tracking server-side for security. Users can manipulate client-side code using devtools.\n</Warning>\n\n***\n\n**Next: Build your billing page**\n\nNow, whenever your customers change their plan, they will automatically have the correct access and limits. Next, build a billing page for your customers.\n\n<Card title=\"Build your billing page\" href=\"/documentation/getting-started/display-billing\">\n  Display plan, balance and usage information to your customers using Autumn's `customer` state\n</Card>\n=====CHECK=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Checking access\n\n> Learn how to check feature access with the `check` endpoint\n\nWhen you create a plan in Autumn, you define what features your customers on that plan get access to.\n\nThe `check` method returns the `allowed` field in real-time to check if a customer should have access to a feature. You can use this to block access and prompt an upsell.\n\n## The `allowed` field\n\nThe `allowed` field will return `true` for a given feature if:\n\n* The customer has an active plan with this feature\n* The customer has an active plan with a `credit_system` that grants this feature\n* The plan feature is <Badge>included</Badge> or <Badge>prepaid</Badge>, and the current balance is greater than the `required_balance` parameter\n* The plan feature is <Badge>usage-based</Badge>, and the user has not exceeded their max spend limit\n* The plan feature is <Badge>unlimited</Badge> or a <Badge>boolean</Badge> feature\n\nUnder these conditions, you should allow your customer to use the feature. You can then [record the usage event](/documentation/customers/tracking-usage/) so Autumn can update the `allowed` field as necessary.\n\n<Note>\n  The customer must already exist before calling `check`. If the `customer_id` doesn't match an existing customer, the API returns a `customer_not_found` error. Create customers using [`customers.getOrCreate`](/documentation/customers/creating-customers) during signup or login.\n</Note>\n\n## Checking metered features\n\nBefore your customer uses a feature, you can check if the customer is allowed to use it and their current usage.\n\n<Info>\n  **Example**\n\n  Let's imagine you have a free plan for a chatbot that allows 5 messages per month. Before your customer sends an AI message, you can check if they have any left.\n\n  If they still have messages remaining, they'll be allowed to send an AI message.\n</Info>\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  const response = await autumn.check({\n    customerId: \"user_123\",\n    featureId: \"messages\",\n  });\n\n  console.log(response.allowed);\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  response = await autumn.check(\n      customer_id=\"user_123\",\n      feature_id=\"messages\",\n  )\n  print(response.allowed)\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/check\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"messages\"\n    }'\n  ```\n</CodeGroup>\n\n<Expandable title=\"check response\">\n  ```json theme={null}\n  {\n    \"allowed\": true,\n    \"customerId\": \"user_123\",\n    \"requiredBalance\": 1,\n    \"balance\": {\n      \"featureId\": \"messages\",\n      \"granted\": 5,\n      \"remaining\": 5,\n      \"usage\": 0,\n      \"unlimited\": false,\n      \"overageAllowed\": false,\n      \"nextResetAt\": 1767610960519\n    }\n  }\n  ```\n</Expandable>\n\n<Tip>\n  Even if your product doesn't have usage limits (ie your feature is purely usage-based), you can still use the above method to prevent usage if a customer's payment fails.\n</Tip>\n\n## Checking for a required balance\n\nIf you know the balance a user will consume in advance, you can specify it with the `requiredBalance` parameter. This means you can prevent a user from starting a process that would consume more than their current balance.\n\nBy default, `requiredBalance` is 1, so not passing this parameter will return `allowed: true` as long as the customer has a feature balance of 1 or more.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  const response = await autumn.check({\n    customerId: \"user_123\",\n    featureId: \"messages\",\n    requiredBalance: 3,\n  });\n\n  console.log(response.allowed);\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  response = await autumn.check(\n      customer_id=\"user_123\",\n      feature_id=\"messages\",\n      required_balance=3,\n  )\n  print(response.allowed)\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/check\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"messages\",\n      \"required_balance\": 3\n    }'\n  ```\n</CodeGroup>\n\n## Checking and reserving usage\n\nWhen you don't know the final cost upfront — like AI completions or long-running jobs — reserve balance with a `lock` on the check call, then finalize it once the operation completes.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  const response = await autumn.check({\n    customerId: \"user_123\",\n    featureId: \"api_calls\",\n    requiredBalance: 3,\n    sendEvent: true,\n    lock: {\n      enabled: true,\n      lockId: \"request_abc123\",\n      expiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes\n    },\n  });\n\n  console.log(response.allowed);\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  response = await autumn.check(\n      customer_id=\"user_123\",\n      feature_id=\"api_calls\",\n      required_balance=3,\n      send_event=True,\n      lock={\n          \"enabled\": True,\n          \"lock_id\": \"request_abc123\",\n          \"expires_at\": int(time.time() * 1000) + 5 * 60 * 1000,\n      },\n  )\n  print(response.allowed)\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/check\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"api_calls\",\n      \"required_balance\": 3,\n      \"send_event\": true,\n      \"lock\": {\n        \"enabled\": true,\n        \"lock_id\": \"request_abc123\",\n        \"expires_at\": 1735689600000\n      }\n    }'\n  ```\n</CodeGroup>\n\nOnce the operation completes, finalize the lock — `confirm` it to keep the deduction, or `release` it if the operation failed.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  await autumn.balances.finalize({\n    lockId: \"request_abc123\",\n    action: \"confirm\",\n  });\n  ```\n\n  ```python Python theme={null}\n  await autumn.balances.finalize(\n      lock_id=\"request_abc123\",\n      action=\"confirm\",\n  )\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/balances.finalize\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"lock_id\": \"request_abc123\",\n      \"action\": \"confirm\"\n    }'\n  ```\n</CodeGroup>\n\n<Tip>\n  See [Balance Locking](/documentation/customers/balance-locking) for the full guide, including releasing a lock and adjusting the final amount when actual usage differs from what you reserved.\n</Tip>\n\n## Checking boolean features\n\nFor simple on/off features, use the check method to determine if a customer has access:\n\n```typescript TypeScript theme={null}\nimport { Autumn } from \"autumn-js\";\n\nconst autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\nconst response = await autumn.check({\n  customerId: \"user_123\",\n  featureId: \"premium-dashboard\",\n});\n\nif (response.allowed) {\n  // Show premium dashboard\n}\n```\n\n### Feature flags in customer responses\n\nBoolean features are also returned as a `flags` object on customer and entity API responses. This lets you check on/off feature access directly from the customer object without calling the `check` endpoint separately.\n\n```json theme={null}\n{\n  \"balances\": {\n    \"credits\": { \"featureId\": \"credits\", \"granted\": 1000, \"remaining\": 800, \"usage\": 200 }\n  },\n  \"flags\": {\n    \"premiumDashboard\": {\n      \"id\": \"cus_ent_abc123\",\n      \"planId\": \"pro_plan\",\n      \"expiresAt\": null,\n      \"featureId\": \"premiumDashboard\"\n    }\n  }\n}\n```\n\n* **Flags** are separate from **balances** — boolean features appear under `flags`, while metered and credit system features remain under `balances`\n* Each flag shows which `planId` it originates from and when it expires\n* Use `expand: [\"flags.feature\"]` to include the full feature object on each flag\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  const customer = await autumn.customers.getOrCreate({\n    customerId: \"user_123\",\n    expand: [\"flags.feature\"],\n  });\n\n  if (customer.flags?.[\"premiumDashboard\"]) {\n    // Customer has the premium dashboard feature\n  }\n  ```\n\n  ```python Python theme={null}\n  customer = await autumn.customers.get_or_create(\n      customer_id=\"user_123\",\n      expand=[\"flags.feature\"],\n  )\n\n  if customer.flags and \"premium_dashboard\" in customer.flags:\n      # Customer has the premium dashboard feature\n      pass\n  ```\n</CodeGroup>\n=====TRACK=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Tracking usage\n\n> Keep track of your customer's feature usage with the `track` route\n\nWhen customers use features in your product, you'll need to record their usage so Autumn can track it against their limits or bill them for usage.\n\nThere are two ways to record usage: sending events or setting usage directly.\n\n<Note>\n  The customer must already exist before calling `track`. If the `customer_id` doesn't match an existing customer, the API returns a `customer_not_found` error. Create customers using [`customers.getOrCreate`](/documentation/customers/creating-customers) during signup or login.\n</Note>\n\n## Sending Events\n\nThe track route is recommended for tracking consumable features, like AI messages, credits or API calls. Each time a customer uses a feature, send an event to count their usage.\n\n<Tip>\n  Before recording usage, you may want to check if the customer is [allowed to\n  use the feature](/documentation/customers/check). This prevents them from exceeding usage\n  limits defined in the product.\n</Tip>\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  await autumn.track({\n    customerId: \"user_123\",\n    featureId: \"ai-messages\",\n    value: 1,\n  });\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  await autumn.track(\n      customer_id=\"user_123\",\n      feature_id=\"ai-messages\",\n      value=1,\n  )\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/track\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"ai-messages\",\n      \"value\": 1\n    }'\n  ```\n</CodeGroup>\n\n<Expandable title=\"track response\">\n  ```json theme={null}\n  {\n    \"customerId\": \"user_123\",\n    \"value\": 1,\n    \"balance\": {\n      \"featureId\": \"ai-messages\",\n      \"granted\": 100,\n      \"remaining\": 99,\n      \"usage\": 1,\n      \"unlimited\": false,\n      \"overageAllowed\": false,\n      \"nextResetAt\": 1767610960519\n    }\n  }\n  ```\n</Expandable>\n\n<Check>\n  You can also send a negative `value` to increase the balance counter, which is\n  useful for increasing a feature limit (eg, if a customer removes a seat).\n</Check>\n\n## Setting Usage Directly\n\nFor non-consumable features (such as seats or workspaces), you may prefer to set usage directly, rather than incrementing Autumn's feature balance. This enables you to sync a source of truth up on your side with Autumn, preventing any discrepancies.\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  await autumn.balances.update({\n    customerId: \"user_123\",\n    featureId: \"seats\",\n    usage: 3,\n  });\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  await autumn.balances.update(\n      customer_id=\"user_123\",\n      feature_id=\"seats\",\n      usage=3,\n  )\n  ```\n\n  ```bash cURL theme={null}\n  curl -X POST \"https://api.useautumn.com/v1/balances/update\" \\\n    -H \"Authorization: Bearer am_sk_test_1234\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\n      \"customer_id\": \"user_123\",\n      \"feature_id\": \"seats\",\n      \"usage\": 3\n    }'\n  ```\n</CodeGroup>\n\n<Warning>\n  The usage route overwrites the current usage value. Use this carefully, as it\n  can reset or override incremental usage recorded through events.\n</Warning>\n\n## Tracking AI Token Usage\n\nIf you're using an [AI credit system](/examples/monetary-credits), you can track token usage directly with `trackTokens`. This automatically converts token counts to a dollar cost using [Models.dev](https://models.dev) pricing and your configured markup, then deducts from the customer's credit balance.\n\nThe `modelId` must be in `provider/model` format, matching the provider and model keys from [Models.dev](https://models.dev). For example:\n\n* `anthropic/claude-sonnet-4-5-20250514`\n* `openai/gpt-4o`\n* `google/gemini-2.5-pro`\n\nFor providers with nested model paths (like OpenRouter), include the full path after the provider: `openrouter/anthropic/claude-opus-4.6`.\n\nToken counts are **exclusive pools**: `inputTokens` should exclude cached tokens (pass those as `cacheReadTokens` / `cacheWriteTokens`) and `outputTokens` should exclude reasoning tokens (pass those as `reasoningTokens`). Audio tokens go in `audioInputTokens` / `audioOutputTokens`. See the [API reference](/api-reference/balances/trackTokens) for the full parameter list.\n\n<Note>\n  `autumn.balances.trackTokens` requires an autumn-js release that includes\n  the method. On older versions, call the REST endpoint directly — see the\n  cURL tab below.\n</Note>\n\n<CodeGroup>\n  ```typescript TypeScript theme={null}\n  import { Autumn } from \"autumn-js\";\n\n  const autumn = new Autumn({ secretKey: \"am_sk_test_1234\" });\n\n  await autumn.balances.trackTokens({\n    customerId: \"user_123\",\n    modelId: \"anthropic/claude-opus-4-6\",\n    inputTokens: 1000,\n    outputTokens: 500,\n  });\n  ```\n\n  ```python Python theme={null}\n  from autumn_sdk import Autumn\n\n  autumn = Autumn(\"am_sk_test_1234\")\n\n  await autumn.balances.track_tokens(\n      customer_id=\"user_123\",\n      model_id=\"anthropic/claude-opus…
$ curl -s --max-time 20 "https://docs.useautumn.com/api-reference/billing/attach.md" | head -250; echo "=====MCP====="; curl -s --max-time 20 "https://docs.useautumn.com/documentation/mcp.md" | head -20…{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Attach\n\n> Attaches a plan to a customer. Handles new subscriptions, upgrades and downgrades.\n\nUse this endpoint to subscribe a customer to a plan, upgrade/downgrade between plans, or add an add-on product.\n\nexport const DynamicResponseExample = ({json, statusCode = \"200\"}) => {\n  const toCamelCase = str => {\n    return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n  };\n  const convertKeysToCamelCase = obj => {\n    if (Array.isArray(obj)) {\n      return obj.map(item => convertKeysToCamelCase(item));\n    }\n    if (obj !== null && typeof obj === \"object\") {\n      return Object.keys(obj).reduce((acc, key) => {\n        const camelKey = toCamelCase(key);\n        acc[camelKey] = convertKeysToCamelCase(obj[key]);\n        return acc;\n      }, {});\n    }\n    return obj;\n  };\n  const [isTypeScript, setIsTypeScript] = useState(() => {\n    if (typeof window !== \"undefined\") {\n      try {\n        const lang = localStorage.getItem(\"code\");\n        return JSON.parse(lang) === \"typescript\";\n      } catch {\n        return true;\n      }\n    }\n    return true;\n  });\n  useEffect(() => {\n    const onMintlifyStorage = event => {\n      if (event.detail?.key === \"code\") {\n        try {\n          const value = JSON.parse(event.detail.value);\n          setIsTypeScript(value === \"typescript\");\n        } catch {}\n      }\n    };\n    const pollInterval = setInterval(() => {\n      try {\n        const lang = localStorage.getItem(\"code\");\n        const value = JSON.parse(lang);\n        setIsTypeScript(value === \"typescript\");\n      } catch {}\n    }, 300);\n    document.addEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n    return () => {\n      document.removeEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n      clearInterval(pollInterval);\n    };\n  }, []);\n  const camelCaseJson = useMemo(() => convertKeysToCamelCase(json), [json]);\n  const snakeCaseString = JSON.stringify(json, null, 2);\n  const camelCaseString = JSON.stringify(camelCaseJson, null, 2);\n  return <ResponseExample>\n\t\t\t{isTypeScript ? <CodeBlock language=\"json\" filename={statusCode}>\n\t\t\t\t\t{camelCaseString}\n\t\t\t\t</CodeBlock> : <CodeBlock language=\"json\" filename={statusCode}>\n\t\t\t\t\t{snakeCaseString}\n\t\t\t\t</CodeBlock>}\n\t\t</ResponseExample>;\n};\n\nexport const DynamicResponseField = ({children, name, ...props}) => {\n  const convertToCamelCase = str => {\n    if (typeof str !== \"string\") return str;\n    return str.replace(/[_-](\\w)/g, (_, c) => c.toUpperCase());\n  };\n  const [lang, setLang] = useState(() => {\n    if (typeof window !== \"undefined\") {\n      const stored = localStorage.getItem(\"code\");\n      return stored || '\"typescript\"';\n    }\n    return '\"typescript\"';\n  });\n  useEffect(() => {\n    const onMintlifyStorage = event => {\n      const key = event.detail?.key;\n      if (key === \"code\") {\n        setLang(event.detail.value);\n      }\n    };\n    const pollInterval = setInterval(() => {\n      const current = localStorage.getItem(\"code\");\n      if (current && current !== lang) {\n        setLang(current);\n      }\n    }, 500);\n    document.addEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n    return () => {\n      document.removeEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n      clearInterval(pollInterval);\n    };\n  }, [lang]);\n  const resolvedName = useMemo(() => {\n    try {\n      const value = JSON.parse(lang);\n      const useCamelCase = value === \"typescript\";\n      return useCamelCase ? convertToCamelCase(name) : name;\n    } catch {\n      return name;\n    }\n  }, [name, lang]);\n  return <ResponseField name={resolvedName} {...props}>\n\t\t\t{children}\n\t\t</ResponseField>;\n};\n\nexport const DynamicParamField = ({children, body, path, ...props}) => {\n  const convertToCamelCase = str => {\n    if (typeof str !== \"string\") return str;\n    return str.replace(/[_-](\\w)/g, (_, c) => c.toUpperCase());\n  };\n  const [lang, setLang] = useState(() => {\n    if (typeof window !== \"undefined\") {\n      const stored = localStorage.getItem(\"code\");\n      return stored || '\"typescript\"';\n    }\n    return '\"typescript\"';\n  });\n  useEffect(() => {\n    const onMintlifyStorage = event => {\n      const key = event.detail?.key;\n      if (key === \"code\") {\n        setLang(event.detail.value);\n      }\n    };\n    const pollInterval = setInterval(() => {\n      const current = localStorage.getItem(\"code\");\n      if (current && current !== lang) {\n        setLang(current);\n      }\n    }, 500);\n    document.addEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n    return () => {\n      document.removeEventListener(\"mintlify-localstorage\", onMintlifyStorage);\n      clearInterval(pollInterval);\n    };\n  }, [lang]);\n  const resolvedBody = useMemo(() => {\n    try {\n      const value = JSON.parse(lang);\n      const useCamelCase = value === \"typescript\";\n      return useCamelCase ? convertToCamelCase(body) : body;\n    } catch {\n      return body;\n    }\n  }, [body, lang]);\n  const resolvedPath = useMemo(() => {\n    try {\n      const value = JSON.parse(lang);\n      const useCamelCase = value === \"typescript\";\n      return useCamelCase ? convertToCamelCase(path) : path;\n    } catch {\n      return path;\n    }\n  }, [path, lang]);\n  return <ParamField body={resolvedBody} path={resolvedPath} {...props}>\n\t\t\t{children}\n\t\t</ParamField>;\n};\n\n<Note>\n  The attach endpoint subscribes a customer to a plan. It handles new\n  subscriptions, upgrades, and downgrades automatically. For modifying an\n  existing subscription (like changing quantities or canceling), use\n  [update](/api-reference/billing/billingUpdate) instead.\n</Note>\n\n### Common Use Cases\n\n<CodeGroup>\n  ```typescript Subscribe to a plan theme={null}\n  const response = await autumn.billing.attach({\n      customerId: \"cus_123\",\n      planId: \"pro_plan\",\n  });\n\n  if (response.paymentUrl) {\n      // Redirect customer to checkout\n      window.location.href = response.paymentUrl;\n  }\n  ```\n\n  ```typescript Custom pricing theme={null}\n  const response = await autumn.billing.attach({\n      customerId: \"cus_123\",\n      planId: \"enterprise_plan\",\n      customize: {\n          price: {\n              amount: 999, // $999\n              interval: \"month\",\n          },\n      },\n  });\n  ```\n\n  ```typescript Attach plan with prepaid quantities theme={null}\n  const response = await autumn.billing.attach({\n      customerId: \"cus_123\",\n      planId: \"team_plan\",\n      featureQuantities: [{ featureId: \"seats\", quantity: 5 }],\n  });\n  ```\n\n  ```typescript Pass metadata to Stripe subscription theme={null}\n  const response = await autumn.billing.attach({\n      customerId: \"cus_123\",\n      planId: \"pro_plan\",\n      checkoutSessionParams: {\n          subscriptionData: {\n              metadata: {\n                  userId: \"internal-user-id\",\n                  source: \"upgrade-flow\",\n              },\n          },\n      },\n  });\n  ```\n</CodeGroup>\n\n### Stripe checkout session params\n\nUse `checkoutSessionParams` to pass additional data to the Stripe checkout session. Values you provide are deep-merged with Autumn's internal parameters, so your fields are preserved alongside ones Autumn sets automatically (like `trial_end` or internal metadata).\n\nThis is useful for attaching custom metadata to the Stripe subscription created during checkout — for example, linking subscriptions to internal user IDs or tracking the source of the purchase.\n\n### Currency\n\nPass `currency` to bill the attach in a specific currency the plan offers via [`additional_currencies`](/documentation/concepts/plans#multiple-currencies). If omitted, Autumn uses the customer's currency, falling back to your organization's default.\n\nA customer who has paid is locked to their currency: passing a different one, or attaching a plan that doesn't offer a paid price in their currency, fails with a `currency_mismatch` error before any billing happens.\n\n### Body Parameters\n\n<DynamicParamField body=\"customer_id\" type=\"string\" required>\n  The ID of the customer to attach the plan to.\n</DynamicParamField>\n\n<DynamicParamField body=\"entity_id\" type=\"string\">\n  The ID of the entity to attach the plan to.\n=====MCP=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# MCP Server\n\n> Connect Autumn's MCP server to AI assistants for billing actions, plan management, and request-log investigations.\n\n## Intro\n\nAutumn MCP connects AI assistants to Autumn's billing, customer, plan, balance,\nand log tools.\n\n### Starter prompt\n\n```text theme={null}\nUse Autumn MCP for this request.\n\n- Always start with autumn://docs/concepts to understand Autumn's data model.\n- Use autumn://docs/plan-management for pricing setup, plan creation, plan updates, and plan modeling.\n- Use autumn://docs/billing for attaching plans, updating subscriptions, cancellations, schedules, trials, and billing state changes.\n- Use autumn://docs/logs for API request logs, Stripe webhook timelines, customer request histories, and log analytics.\n- Use https://docs.useautumn.com/llms.txt to find product docs if the MCP resources do not answer something.\n- Preview billing changes before applying them, and ask for approval before any destructive write.\n```\n\n## Setup\n\nAutumn MCP can be installed in any MCP client with the server URL:\n\n```text theme={null}\nhttps://mcp.useautumn.com/mcp\n```\n\nYou do not need an API key. By default, your MCP client opens an Autumn sign-in\nflow and connects to your organization.\n\nFor a long-lived setup, you can also use an Autumn secret key with Bearer auth:\n\n```json theme={null}\n{\n  \"headers\": {\n    \"Authorization\": \"Bearer am_sk_test_...\"\n  }\n}\n```\n\n<Tabs>\n  <Tab title=\"Claude Code\">\n    Run in terminal:\n\n    ```bash theme={null}\n    claude mcp add --transport http autumn https://mcp.useautumn.com/mcp\n    ```\n\n    Or add to your project's `.mcp.json`:\n\n    ```json theme={null}\n    {\n      \"mcpServers\": {\n        \"autumn\": {\n          \"type\": \"http\",\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"Codex\">\n    Run in terminal:\n\n    ```bash theme={null}\n    codex mcp add autumn --url https://mcp.useautumn.com/mcp\n    ```\n\n    Or add to `~/.codex/config.toml`:\n\n    ```toml theme={null}\n    [mcp_servers.autumn]\n    url = \"https://mcp.useautumn.com/mcp\"\n    ```\n  </Tab>\n\n  <Tab title=\"Cursor\">\n    [![Install with one click](https://img.shields.io/badge/Install_with_one_click-Cursor-000000?style=flat-square\\&logoColor=white)](https://cursor.com/en/install-mcp?name=autumn\\&config=eyJuYW1lIjoiYXV0dW1uIiwidHlwZSI6Imh0dHAiLCJ1cmwiOiJodHRwczovL21jcC51c2VhdXR1bW4uY29tL21jcCJ9)\n\n    Or add to `~/.cursor/mcp.json`:\n\n    ```json theme={null}\n    {\n      \"mcpServers\": {\n        \"autumn\": {\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"Claude Desktop\">\n    1. Open Claude Desktop settings.\n    2. Go to **Connectors**.\n    3. Click **Add custom connector**.\n    4. Paste `https://mcp.useautumn.com/mcp` and sign in.\n\n    Or add to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n    ```json theme={null}\n    {\n      \"mcpServers\": {\n        \"autumn\": {\n          \"type\": \"http\",\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"OpenCode\">\n    Add to `~/.config/opencode/opencode.json`:\n\n    ```json theme={null}\n    {\n      \"mcp\": {\n        \"autumn\": {\n          \"type\": \"remote\",\n          \"url\": \"https://mcp.useautumn.com/mcp\",\n          \"enabled\": true\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"Zed\">\n    Add to `~/.config/zed/settings.json`:\n\n    ```json theme={null}\n    {\n      \"context_servers\": {\n        \"autumn\": {\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"VS Code\">\n    [![Install with one click](https://img.shields.io/badge/Install_with_one_click-VS_Code-0098FF?style=flat-square\\&logo=visualstudiocode\\&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=autumn\\&config=%7B%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.useautumn.com%2Fmcp%22%7D)\n\n    Or add to `.vscode/mcp.json`:\n\n    ```json theme={null}\n    {\n      \"servers\": {\n        \"autumn\": {\n          \"type\": \"http\",\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n  </Tab>\n\n  <Tab title=\"Other\">\n    For other MCP clients that support remote MCP:\n\n    ```json theme={null}\n    {\n      \"mcpServers\": {\n        \"autumn\": {\n          \"url\": \"https://mcp.useautumn.com/mcp\"\n        }\n      }\n    }\n    ```\n\n    If your client does not support remote MCP servers directly:\n\n    ```json theme={null}\n    {\n      \"mcpServers\": {\n        \"autumn\": {\n          \"command\": \"npx\",\n          \"args\": [\"-y\", \"mcp-remote\", \"https://mcp.useautumn.com/mcp\"]\n        }\n      }\n    }\n    ```\n  </Tab>\n</Tabs>\n\n## Using MCP\n\nAutumn MCP exposes tools and resources. Ask your agent to read the relevant Autumn MCP resource before it acts:\n\n* Start with `autumn://docs/concepts` to understand Autumn's data model.\n","type":"text"}]}
Thinking…

I now have a strong understanding of Autumn. Let me also quickly find the product's own pricing (useautumn.com/pricing) and the CLI config reference to assess manageability. Also check the full llms list for api-reference core check/track and customers getOrCreate schema. But I have plenty.

Let me check useautumn.com pricing page. And maybe the CLI configuration reference to explain pricing config approach. Then I can decide whether to actually build an example.

The user asks: "Help me build a simple example using Autumn. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop."

So the workflow:

  1. Determine if Autumn has a developer workflow I can act on. Yes: hosted cloud + SDK/API (autumn-js / REST at api.useautumn.com). Also CLI (atmn) for config-as-code, and MCP.
  2. Build a simple example using SDK/API against the hosted product.
  3. Explain pricing.
  4. Assess manageability.

I need to actually build an example. But I need an API key (AUTUMN_SECRET_KEY) to run real code. I don't have credentials. I could:

  • Write a small example project (e.g., a Node script using autumn-js) with clear instructions, but I can't run live calls without a key. Alternatively, I can test SDK availability without a key (npm install, import, construct - but constructing requires key). I could create a sample that reads AUTUMN_SECRET_KEY from env and demonstrates check/track/getOrCreate/attach; but running it would fail without a key.

  • I could use the CLI atmn init which "create a sandbox with no account" — interesting! The setup doc says atmn init "asks how you want to connect (sign in, or create a sandbox with no account)". That could give me a sandbox without an account, allowing me to actually run config push against a sandbox. But it's interactive, and "create a sandbox" might need interactive prompts. The user said stay light and don't wait for long-running commands. Interactive CLI could block.

Actually, let me check the CLI docs to see if there's a non-interactive way to init with a sandbox. There may be atmn init --sandbox or env vars. Let me read cli/getting-started.md and cli/config.md.

Also check if there is a publicly accessible sandbox API that doesn't need a key. Probably not; the API requires Bearer key.

Given constraints: "use the hosted product through its SDK or API", "Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop."

The quickstart (atmn init) is a CLI that connects to the hosted product (not local). It doesn't require local service stacks. It might be interactive but fast. However "wait for long-running commands" — init/push should be fast (network calls). Interactive prompts could be an issue in a non-interactive shell.

Let me check the CLI docs to understand atmn init options.

Let me also check pricing page.

$ curl -s --max-time 20 "https://docs.useautumn.com/cli/getting-started.md"; echo "=====CONFIG====="; curl -s --max-time 20 "https://docs.useautumn.com/cli/config.md" | head -200{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Getting started\n\n> Set up the CLI, connect to Autumn, and sync your pricing config\n\nThe `atmn` CLI keeps your pricing in code. You write your features and plans in an `autumn.config.ts` file, preview what would change, and push it to Autumn with one command.\n\n<Note>\n  This page covers `atmn` 2. If you have a config from `atmn` 1.x, see [upgrading from 1.x](#upgrading-from-1x).\n</Note>\n\n## Set up a project\n\nRun `atmn init` in the root folder of your project:\n\n<CodeGroup>\n  ```bash bun theme={null}\n  bunx atmn init\n  ```\n\n  ```bash npm theme={null}\n  npx atmn init\n  ```\n\n  ```bash pnpm theme={null}\n  pnpm dlx atmn init\n  ```\n</CodeGroup>\n\n`init` does the whole setup in one go:\n\n1. **Connects you to Autumn.** If you don't have a key yet, it asks how you want to connect: sign in (opens your browser), or go keyless (creates a sandbox for you right away, no account needed).\n2. **Creates your config folder.** By default that's `autumn/`, holding `autumn.config.ts` next to `features.ts`, `plans.ts` and `rewards.ts`. In a monorepo it asks where the folder should go (default `packages/autumn`) and what to call the package.\n3. **Adds `atmn` to your `package.json`** and installs it, because the config imports from it. It also adds an `atmn` script and a small `\"atmn\"` field to your root `package.json`, so every command can find the config from anywhere in your repo.\n4. **Pulls what's already in Autumn** into the config files.\n5. **Installs the Autumn skills** next to the config, so your coding agent knows how to work with the CLI.\n\nYour keys end up in a `.env` file at the root of your repo:\n\n```bash .env theme={null}\nAUTUMN_SECRET_KEY=am_sk_test_...\nAUTUMN_PROD_SECRET_KEY=am_sk_live_...\n```\n\n<Tip>\n  Went keyless? Your sandbox has no owner yet. Link it to an account within a few days with `bunx atmn login --claim you@example.com`. The key you already have keeps working.\n</Tip>\n\n<Check>\n  You can check your setup at any time with `bunx atmn env`. It shows which organization, environment and key your commands will use.\n</Check>\n\n## Log in on its own\n\nYou don't need `init` to connect. `atmn login` opens your browser, lets you pick an organization, and writes both keys to your `.env`:\n\n```bash theme={null}\nbunx atmn login\n```\n\nAdd `--keyless` to create a sandbox without an account instead.\n\n## Push and pull\n\nOnce you have a config, sync it with Autumn:\n\n```bash theme={null}\n# Preview what would change\nbunx atmn push\n\n# Apply the changes\nbunx atmn push --yes\n\n# Pull what's in Autumn into your local files\nbunx atmn pull\n```\n\n`push` reads your config, compares it with what's in Autumn, and shows what would be created, updated or deleted. Nothing changes until you add `--yes`. If a change affects a plan that already has customers, Autumn drafts a migration for you and `push` prints the link to run it.\n\nAfter a push, the CLI writes an `internalId` into each feature and plan in your config. Leave it there. It's how the CLI knows to rename something instead of deleting and recreating it.\n\n`pull` fetches your features, plans and rewards from Autumn and writes them into `features.ts`, `plans.ts` and `rewards.ts`, keeping your formatting where it can. If you don't have a config yet, it asks where to create one.\n\n<Tip>\n  Already made plans in the dashboard? Run `bunx atmn pull` to turn them into a config.\n</Tip>\n\n## Environments\n\nAll commands use your **sandbox** by default. Add `-p` to target production:\n\n```bash theme={null}\n# Push to production\nbunx atmn push -p --yes\n\n# Pull from production\nbunx atmn pull -p\n```\n\n<Warning>\n  `push -p` only previews the changes. Add `--yes` to apply them to production.\n</Warning>\n\nYou can also create extra sandboxes for testing, each with its own plans and customers:\n\n```bash theme={null}\nbunx atmn sandbox create staging --use   # create one and switch to it\nbunx atmn sandbox use --clear            # switch back to your main sandbox\n```\n\nSee the [command reference](/cli/commands#sandboxes) for the full list.\n\n## Upgrading from 1.x\n\n`atmn` 2 uses a new config format. If you run a 1.x config, the CLI stops and tells you so instead of guessing. To move over:\n\n1. Note any changes you made to your config that aren't in Autumn yet.\n\n2. Rebuild the config from your organization. This rewrites `autumn.config.ts` and the `features.ts`, `plans.ts` and `rewards.ts` beside it. Other files are left alone.\n\n   ```bash theme={null}\n   bunx atmn pull --overwrite --yes\n   ```\n\n3. Re-apply your pending changes in the new format, then `bunx atmn push`.\n\nWhat changed:\n\n| 1.x                                                            | 2.x                                                                                                  |\n| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |\n| `feature({ id: \"messages\" })`                                  | `feature({ featureId: \"messages\" })`                                                                 |\n| `plan({ id: \"pro\" })`                                          | `plan({ planId: \"pro\", versionSlug: \"v1\", active: true })`                                           |\n| `item({ ... })` inside `items`                                 | Plain objects inside `items`. There is no `item()` helper.                                           |\n| Named exports only                                             | The file ends with `export default atmn({ features, plans })`                                        |\n| Plan versions handled by the CLI on push                       | Each version is its own `plan()` entry with the same `planId`. See [versions](/cli/config#versions). |\n| `atmn push` applied straight away                              | `atmn push` only previews. `atmn push --yes` applies.                                                |\n| `atmn pull --force`                                            | `atmn pull --overwrite --yes`                                                                        |\n| `atmn nuke`                                                    | `atmn reset --yes`                                                                                   |\n| `atmn customers`, `atmn plans`, `atmn features`, `atmn events` | Removed. Use [`atmn api`](/cli/commands#api) to call any endpoint.                                   |\n| `atmn preview`, `atmn logout`, `atmn config`                   | Removed.                                                                                             |\n\n**Next: Configuration reference**\n\nLearn how to define features, plans and pricing in your `autumn.config.ts`.\n\n<Card title=\"Configuration reference\" href=\"/cli/config\">\n  Every builder and field available in autumn.config.ts\n</Card>\n=====CONFIG=====\n> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Configuration reference\n\n> Define features, plans, rewards and settings in autumn.config.ts\n\nYour `autumn.config.ts` file is the source of truth for your pricing. It builds features, plans and rewards with helper functions from the `atmn` package, and hands them to `atmn()` as the default export.\n\n```ts autumn.config.ts theme={null}\nimport { atmn, feature, plan } from \"atmn\";\n\nexport const messages = feature({ ... });\nexport const pro = plan({ ... });\n\nexport default atmn({ features: [messages], plans: [pro] });\n```\n\nPreview changes with `atmn push`, apply them with `atmn push --yes`, or pull what's in Autumn with `atmn pull`.\n\n## File layout\n\n`atmn init` and `atmn pull` create a folder with one file per kind of thing, and a root config that imports them:\n\n```\nautumn/\n  autumn.config.ts   # export default atmn({ features, plans, rewards, referralPrograms, settings })\n  features.ts        # export const features = [feature({ ... }), ...]\n  plans.ts           # export const plans = [plan({ ... }), ...]\n  rewards.ts         # export const rewards = [...]; export const referralPrograms = [...]\n```\n\n`atmn pull` writes into these files and keeps your formatting. A single `autumn.config.ts` with everything in it works too. Any file that imports from `atmn` is treated as part of your config.\n\n## `atmn(config)`\n\nThe root of your config. Each list you include is the **complete** list: anything in Autumn that isn't in it gets deleted on push. Leave a list out to leave that part of Autumn alone.\n\n<ParamField body=\"features\" type=\"Feature[]\">\n  Every feature, from `feature()`.\n</ParamField>\n\n<ParamField body=\"plans\" type=\"Plan[]\">\n  Every plan and every version of it, from `plan()`.\n</ParamField>\n\n<ParamField body=\"rewards\" type=\"Reward[]\">\n  Coupons and feature grants, from `coupon()` and `featureGrant()`. See [rewards](#rewards).\n</ParamField>\n\n<ParamField body=\"referralPrograms\" type=\"ReferralProgram[]\">\n  Referral programs, from `referralProgram()`. See [referral programs](#referral-programs).\n</ParamField>\n\n<ParamField body=\"settings\" type=\"object\">\n  Organization settings. Only the flags you state are changed. See [settings](#settings).\n</ParamField>\n\nThe CLI checks the whole config before sending anything and reports every problem at once, with the file and line to fix.\n\n## Features\n\nFeatures define what can be gated, metered or billed in your app.\n\n### `feature(config)`\n\n<ParamField body=\"featureId\" type=\"string\" required>\n  Unique identifier used in API calls (`check`, `track`, etc).\n</ParamField>\n\n<ParamField body=\"name\" type=\"string\" required>\n  Display name shown in the dashboard and billing UI.\n</ParamField>\n\n<ParamField body=\"type\" type=\"enum\" required>\n  `\"boolean\"` | `\"metered\"` | `\"credit_system\"` | `\"ai_credit_system\"`\n</ParamField>\n\n<ParamField body=\"consumable\" type=\"boolean\">\n  **Required for `metered` features.**\n\n  * `true`: usage is used up and refilled (messages, API calls, credits)\n  * `false`: usage is ongoing (seats, storage, workspaces)\n</ParamField>\n\n<ParamField body=\"creditSchema\" type=\"array\">\n  **Required for `credit_system` features.** The rate card: one entry per metered feature that draws from the credit balance.\n\n  Flat rate: `{ meteredFeatureId: string, creditCost: number, billingUnits?: number }`: `creditCost` credits per `billingUnits` units (default 1).\n\n  Graduated rate: `{ meteredFeatureId, billingUnits?, tierBehavior: \"graduated\", tiers: [{ to: number | \"inf\", creditCost: number }] }`: the credit cost steps as usage in the cycle grows. The last tier must be `\"inf\"`.\n\n  Each entry may also carry `dimensions` and `multipliers` to price by event properties. See [Rate cards and dimensions](/documentation/modelling-pricing/credit-systems#rate-cards-and-dimensions).\n</ParamField>\n\n<ParamField body=\"defaultMarkup\" type=\"number\">\n  **For `ai_credit_system` features.** Percentage added on top of the model's cost, eg `30`. Use `-100` to make usage free.\n</ParamField>\n\n<ParamField body=\"providerMarkups\" type=\"object\">\n  **For `ai_credit_system` features.** Markup per provider, keyed by the first part of the model ID: `{ openrouter: { markup: 25 } }`.\n</ParamField>\n\n<ParamField body=\"modelMarkups\" type=\"object\">\n  **For `ai_credit_system` features.** Markup per model, keyed by model ID: `{ \"openai/gpt-4o-mini\": { markup: 20 } }`. For your own models, add `inputCost` and `outputCost` in dollars per million tokens. See [AI credit systems](/documentation/modelling-pricing/credit-systems#ai-credit-systems).\n</ParamField>\n\n<ParamField body=\"archived\" type=\"boolean\">\n  Archive the feature. Leave it out to keep it as is.\n</ParamField>\n\n<ParamField body=\"internalId\" type=\"string\">\n  Written by the CLI after a push. Leave it there. Changing `featureId` next to it renames the feature.\n</ParamField>\n\n<ParamField body=\"processors\" type=\"object\">\n  Stripe mapping: `{ stripe: { productId, meterId } }`. Only pulled with `atmn pull --include-mappings`.\n</ParamField>\n\n### Feature types\n\n**Boolean**: simple on/off flag.\n\n```ts theme={null}\nexport const sso = feature({\n  featureId: \"sso\",\n  name: \"SSO Authentication\",\n  type: \"boolean\",\n});\n```\n\n**Metered, consumable**: used up and refilled (messages, API calls).\n\n```ts theme={null}\nexport const messages = feature({\n  featureId: \"messages\",\n  name: \"Messages\",\n  type: \"metered\",\n  consumable: true,\n});\n```\n\n**Metered, non-consumable**: ongoing usage (seats, storage).\n\n```ts theme={null}\nexport const seats = feature({\n  featureId: \"seats\",\n  name: \"Seats\",\n  type: \"metered\",\n  consumable: false,\n});\n```\n\n**Credit system**: maps several metered features to credit costs.\n\n```ts theme={null}\nexport const basicModel = feature({\n  featureId: \"basic_model\",\n  name: \"Basic Model\",\n  type: \"metered\",\n  consumable: true,\n});\n\nexport const premiumModel = feature({\n  featureId: \"premium_model\",\n  name: \"Premium Model\",\n  type: \"metered\",\n  consumable: true,\n});\n\nexport const credits = feature({\n  featureId: \"credits\",\n  name: \"AI Credits\",\n  type: \"credit_system\",\n  creditSchema: [\n    { meteredFeatureId: basicModel.featureId, creditCost: 1 },\n    { meteredFeatureId: premiumModel.featureId, creditCost: 5 },\n  ],\n});\n```\n\n<Tip>\n  If you set the price per credit to 1 cent, credits become monetary credits (eg, 5 credits = \\$0.05 per premium message).\n</Tip>\n\n**AI credit system**: bills LLM usage at the model's real cost plus a markup. Track usage with [`track_tokens`](/api-reference/balances/trackTokens).\n\n```ts theme={null}\nexport const aiCredits = feature({\n  featureId: \"ai_credits\",\n  name: \"AI Credits\",\n  type: \"ai_credit_system\",\n  defaultMarkup: 30,\n});\n```\n\n## Plans\n\nPlans combine features with pricing to create your subscription tiers, add-ons and top-ups.\n","type":"text"}]}
$ curl -s -L --max-time 20 "https://useautumn.com/pricing" | sed 's/</\n</g' | grep -iE "price|pricing|/mo|month|free|tier|per |usage|charge|seat" | head -60; echo "---EXIT:$?---"{"content":[{"text":"<title>Pricing | Autumn\n<meta name=\"description\" content=\"Autumn pricing. Start free with 8K monthly billing volume, scale to Pro from …ctrl+o
{"content":[{"text":"<title>Pricing | Autumn\n<meta name=\"description\" content=\"Autumn pricing. Start free with 8K monthly billing volume, scale to Pro from $375/month, or talk to us about volume discounts.\"/>\n<meta name=\"keywords\" content=\"AI billing,usage-based billing,subscription management,AI startups,billing infrastructure,payment integration,usage limits,credit system\"/>\n<link rel=\"canonical\" href=\"https://useautumn.com/pricing\"/>\n<meta property=\"og:description\" content=\"The drop-in billing layer for AI startups. Stop rebuilding usage limits, credit systems, and subscription logic.\"/>\n<meta name=\"twitter:description\" content=\"The drop-in billing layer for AI startups. Stop rebuilding usage limits, credit systems, and subscription logic.\"/>\n<script type=\"application/ld+json\">[{\"@context\":\"https://schema.org\",\"@type\":\"Organization\",\"@id\":\"https://useautumn.com/#organization\",\"name\":\"Autumn\",\"url\":\"https://useautumn.com\",\"logo\":\"https://useautumn.com/icon-192.png\",\"description\":\"Billing infrastructure for AI startups: usage-based billing, credits, entitlements, and subscription state in one API.\",\"sameAs\":[\"https://x.com/autumnpricing\",\"https://www.linkedin.com/company/useautumn\",\"https://discord.com/invite/STqxY92zuS\"]},{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"@id\":\"https://useautumn.com/#website\",\"name\":\"Autumn\",\"alternateName\":\"useautumn.com\",\"url\":\"https://useautumn.com\",\"publisher\":{\"@id\":\"https://useautumn.com/#organization\"}},{\"@context\":\"https://schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"Do I still need Stripe?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. Autumn works with Stripe—it handles the billing logic that Stripe doesn't. You keep your Stripe account, your customer relationships, and your payment data. Autumn sits between your app and Stripe, managing webhooks, usage limits, and state. You're never locked in. Your subscriptions live in Stripe.\"}},{\"@type\":\"Question\",\"name\":\"Do I need to call Autumn before every action?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"For latency-sensitive operations, you may not want to make an autumn.check() network call before every action. Instead, you can either cache the Autumn customer data on your end, or use our single customer.products.updated webhook to replicate the Autumn state into your own system.\"}},{\"@type\":\"Question\",\"name\":\"What if Autumn goes down? Will my app go down?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"We run on redundant infrastructure and high availability is our priority. However, not being able to reach Autumn does not mean that your app will go down. Our app and SDKs default to fail open and fail fast, meaning that in a worst case scenario, some users may get temporary additional access. We can work with you to reconcile usage tracking and balances afterward if needed.\"}},{\"@type\":\"Question\",\"name\":\"How is Autumn different from Orb or Metronome?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Orb and Metronome focus on usage metering—tracking how much customers consume, suitable for end of month invoicing. You still have to build access control and state management separately, meaning you'll wire together your own logic, Stripe billing and a metering provider. Autumn is a complete system of record. We handle usage metering + entitlements + feature gating + billing state in one API. check() tells you if a user can access a feature in \n<50ms.\"}},{\"@type\":\"Question\",\"name\":\"What if I need to move off Autumn? Am I locked in?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Autumn is open source. You can self-host anytime, or export all your data. Your Stripe subscriptions, customers and payment details remain yours. Moving off Autumn is simply a case of building what you would have built in-house anyway (but this has never happened, touch wood!). You can even do this gradually: first by replicating customer state into your own system via our webhooks, then making a full transition after.\"}},{\"@type\":\"Question\",\"name\":\"Can you do the implementation for us?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"If you're setting up payments for the first time, most teams go live in under an hour. Migrating from an existing billing system typically takes 1–2 weeks, depending on complexity. For Series A+ companies, we provide a forward deployed service to work with your team, dual-write to your internal system and Autumn, then smoothly migrate over. Minimal work needed on your part.\"}},{\"@type\":\"Question\",\"name\":\"Can you handle our event volume?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. Autumn supports 10,000+ events per second per end customer. We've processed millions of billing events daily for AI companies at scale. If you have specific requirements, reach out—we'll walk through our architecture.\"}}]}]\n<a class=\"group inline-flex items-center py-2 text-[#FFFFFF99] hover:text-white transition-colors\" href=\"/pricing\">\n<span class=\"font-mono text-[14px] uppercase tracking-widest transition-colors group-hover:text-white\">Pricing\n<a class=\"flex items-center gap-4 px-4 py-3.5 border-b border-[#292929] active:bg-[#141414ea] text-[#ffffff99] hover:text-white active:text-white transition-colors text-sm tracking-[-1%]\" href=\"/pricing\">\n<span>Pricing\n<span class=\"tracking-[-2%] text-sm\">Start for free\n<!-- -->PRICING\n<section id=\"pricing\" class=\"bg-[#000000] w-full scroll-mt-16\">\n<h1 class=\"text-[30px] leading-[32px] md:leading-[40px] md:text-3xl lg:text-[40px] tracking-[-4%] text-white font-normal w-full text-center font-sans\">Start free. Scale with confidence.\n<span class=\"block mb-4 font-mono text-[12px] md:text-[14px] uppercase tracking-[-1%] text-[#FFFFFF99]\">Monthly billing volume\n<input type=\"range\" min=\"0\" max=\"4\" step=\"1\" aria-label=\"Monthly billing volume\" class=\"volume-slider\" style=\"--slider-progress:0.25\" value=\"1\"/>\n<span class=\"inline-block px-3 py-1 bg-[#8752FA]/20 text-[#9564FF] text-[12px] md:text-[13px] lg:text-[16px] font-mono tracking-[-2%] uppercase mb-3 md:mb-2\">FREE\n<span class=\"text-[#FFFFFF99] font-light self-end text-[13px] md:text-sm lg:text-base tracking-[-2%] mb-1.5 md:mb-0\">/month\n<span class=\"md:text-white font-light text-[14px] md:text-[16px]\">8K monthly billing volume\n<span class=\"text-[#FFFFFF99] font-light self-end text-[13px] md:text-sm lg:text-base tracking-[-2%] mb-1.5 md:mb-0\">/month\n<p class=\"md:text-white font-light md:font-extralight text-[13px] md:text-[16px] tracking-[-2%] leading-[18px] md:leading-5 w-full md:w-[95%] text-pretty\">For teams scaling with real usage-based pricing.\n<span class=\"md:text-white font-light text-[14px] md:text-[16px]\">50K monthly billing volume\n<span class=\"block text-[#FFFFFF99] font-light text-[13px] md:text-[15px]\">then $5 per 1M requests\n<span class=\"md:text-white font-light text-[14px] md:text-[16px]\">Usage event aggregation\n<script>self.__next_f.push([1,\"[{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"Organization\\\",\\\"@id\\\":\\\"https://useautumn.com/#organization\\\",\\\"name\\\":\\\"Autumn\\\",\\\"url\\\":\\\"https://useautumn.com\\\",\\\"logo\\\":\\\"https://useautumn.com/icon-192.png\\\",\\\"description\\\":\\\"Billing infrastructure for AI startups: usage-based billing, credits, entitlements, and subscription state in one API.\\\",\\\"sameAs\\\":[\\\"https://x.com/autumnpricing\\\",\\\"https://www.linkedin.com/company/useautumn\\\",\\\"https://discord.com/invite/STqxY92zuS\\\"]},{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"WebSite\\\",\\\"@id\\\":\\\"https://useautumn.com/#website\\\",\\\"name\\\":\\\"Autumn\\\",\\\"alternateName\\\":\\\"useautumn.com\\\",\\\"url\\\":\\\"https://useautumn.com\\\",\\\"publisher\\\":{\\\"@id\\\":\\\"https://useautumn.com/#organization\\\"}},{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"FAQPage\\\",\\\"mainEntity\\\":[{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"Do I still need Stripe?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"Yes. Autumn works with Stripe—it handles the billing logic that Stripe doesn't. You keep your Stripe account, your customer relationships, and your payment data. Autumn sits between your app and Stripe, managing webhooks, usage limits, and state. You're never locked in. Your subscriptions live in Stripe.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"Do I need to call Autumn before every action?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"For latency-sensitive operations, you may not want to make an autumn.check() network call before every action. Instead, you can either cache the Autumn customer data on your end, or use our single customer.products.updated webhook to replicate the Autumn state into your own system.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"What if Autumn goes down? Will my app go down?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"We run on redundant infrastructure and high availability is our priority. However, not being able to reach Autumn does not mean that your app will go down. Our app and SDKs default to fail open and fail fast, meaning that in a worst case scenario, some users may get temporary additional access. We can work with you to reconcile usage tracking and balances afterward if needed.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"How is Autumn different from Orb or Metronome?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"Orb and Metronome focus on usage metering—tracking how much customers consume, suitable for end of month invoicing. You still have to build access control and state management separately, meaning you'll wire together your own logic, Stripe billing and a metering provider. Autumn is a complete system of record. We handle usage metering + entitlements + feature gating + billing state in one API. check() tells you if a user can access a feature in \\u003c50ms.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"What if I need to move off Autumn? Am I locked in?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"Autumn is open source. You can self-host anytime, or export all your data. Your Stripe subscriptions, customers and payment details remain yours. Moving off Autumn is simply a case of building what you would have built in-house anyway (but this has never happened, touch wood!). You can even do this gradually: first by replicating customer state into your own system via our webhooks, then making a full transition after.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"Can you do the implementation for us?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"If you're setting up payments for the first time, most teams go live in under an hour. Migrating from an existing billing system typically takes 1–2 weeks, depending on complexity. For Series A+ companies, we provide a forward deployed service to work with your team, dual-write to your internal system and Autumn, then smoothly migrate over. Minimal work needed on your part.\\\"}},{\\\"@type\\\":\\\"Question\\\",\\\"name\\\":\\\"Can you handle our event volume?\\\",\\\"acceptedAnswer\\\":{\\\"@type\\\":\\\"Answer\\\",\\\"text\\\":\\\"Yes. Autumn supports 10,000+ events per second per end customer. We've processed millions of billing events daily for AI companies at scale. If you have specific requirements, reach out—we'll walk through our architecture.\\\"}}]}]\"])\n<script>self.__next_f.push([1,\"0:{\\\"P\\\":null,\\\"c\\\":[\\\"\\\",\\\"pricing\\\"],\\\"q\\\":\\\"\\\",\\\"i\\\":false,\\\"f\\\":[[[\\\"\\\",{\\\"children\\\":[\\\"pricing\\\",{\\\"children\\\":[\\\"__PAGE__\\\",{}]}]},\\\"$undefined\\\",\\\"$undefined\\\",16],[[\\\"$\\\",\\\"$1\\\",\\\"c\\\",{\\\"children\\\":[[[\\\"$\\\",\\\"link\\\",\\\"0\\\",{\\\"rel\\\":\\\"stylesheet\\\",\\\"href\\\":\\\"/_next/static/chunks/013pj4c4x_pll.css?dpl=dpl_7EKZXsdAPAtBqNiDLg2z7zhgUeLN\\\",\\\"precedence\\\":\\\"next\\\",\\\"crossOrigin\\\":\\\"$undefined\\\",\\\"nonce\\\":\\\"$undefined\\\"}],[\\\"$\\\",\\\"link\\\",\\\"1\\\",{\\\"rel\\\":\\\"stylesheet\\\",\\\"href\\\":\\\"/_next/static/chunks/15drt0_k~kb_p.css?dpl=dpl_7EKZXsdAPAtBqNiDLg2z7zhgUeLN\\\",\\\"precedence\\\":\\\"next\\\",\\\"crossOrigin\\\":\\\"$undefined\\\",\\\"nonce\\\":\\\"$undefined\\\"}],[\\\"$\\\",\\\"script\\\",\\\"script-0\\\",{\\\"src\\\":\\\"/_next/static/chunks/09le~3odpw_os.js?dpl=dpl_7EKZXsdAPAtBqNiDLg2z7zhgUeLN\\\",\\\"async\\\":true,\\\"nonce\\\":\\\"$undefined\\\"}],[\\\"$\\\",\\\"script\\\",\\\"script-1\\\",{\\\"src\\\":\\\"/_next/static/chunks/0oy4mrxkqbi2g.js?dpl=dpl_7EKZXsdAPAtBqNiDLg2z7zhgUeLN\\\",\\\"async\\\":true,\\\"nonce\\\":\\\"$undefined\\\"}]],[\\\"$\\\",\\\"html\\\",null,{\\\"lang\\\":\\\"en\\\",\\\"suppressHydrationWarning\\\":true,\\\"className\\\":\\\"geist_deef94d5-module__Sms4YG__variable geist_mono_1bf8cbf6-module__FlyLvG__variable h-full max-w-full overflow-x-clip overscroll-x-none bg-black antialiased\\\",\\\"children\\\":[[\\\"$\\\",\\\"head\\\",null,{\\\"children\\\":[\\\"$\\\",\\\"script\\\",null,{\\\"dangerouslySetInnerHTML\\\":{\\\"__html\\\":\\\"!function(key) {if (window.reb2b) return;window.reb2b = {loaded: true};var s = document.createElement(\\\\\\\"script\\\\\\\");s.async = true;s.src = \\\\\\\"https://ddwl4m2hdecbv.cloudfront.net/b/\\\\\\\" + key + \\\\\\\"/\\\\\\\" + key + \\\\\\\".js.gz\\\\\\\";document.getElementsByTagName(\\\\\\\"script\\\\\\\")[0].parentNode.insertBefore(s, document.getElementsByTagName(\\\\\\\"script\\\\\\\")[0]);}(\\\\\\\"4N210HX5V56Z\\\\\\\");\\\"}}]}],[\\\"$\\\",\\\"body\\\",null,{\\\"className\\\":\\\"min-h-full max-w-full overflow-x-clip overscroll-x-none flex flex-col\\\",\\\"children\\\":[\\\"$\\\",\\\"$L2\\\",null,{\\\"parallelRouterKey\\\":\\\"children\\\",\\\"error\\\":\\\"$undefined\\\",\\\"errorStyles\\\":\\\"$undefined\\\",\\\"errorScripts\\\":\\\"$undefined\\\",\\\"template\\\":[\\\"$\\\",\\\"$L3\\\",null,{}],\\\"templateStyles\\\":\\\"$undefined\\\",\\\"templateScripts\\\":\\\"$undefined\\\",\\\"notFound\\\":[[\\\"$\\\",\\\"$L4\\\",null,{}],[]],\\\"forbidden\\\":\\\"$undefined\\\",\\\"unauthorized\\\":\\\"$undefined\\\"}]}]]}]]}],{\\\"children\\\":[[\\\"$\\\",\\\"$1\\\",\\\"c\\\",{\\\"children\\\":[null,[\\\"$\\\",\\\"$L2\\\",null,{\\\"parallelRouterKey\\\":\\\"children\\\",\\\"error\\\":\\\"$undefined\\\",\\\"errorStyles\\\":\\\"$undefined\\\",\\\"errorScripts\\\":\\\"$undefined\\\",\\\"template\\\":[\\\"$\\\",\\\"$L3\\\",null,{}],\\\"templateStyles\\\":\\\"$undefined\\\",\\\"templateScripts\\\":\\\"$undefined\\\",\\\"notFound\\\":\\\"$undefined\\\",\\\"forbidden\\\":\\\"$undefined\\\",\\\"unauthorized\\\":\\\"$undefined\\\"}]]}],{\\\"children\\\":[[\\\"$\\\",\\\"$1\\\",\\\"c\\\",{\\\"children\\\":[[\\\"$\\\",\\\"div\\\",null,{\\\"className\\\":\\\"w-full overflow-x-clip\\\",\\\"style\\\":{\\\"--page-pad\\\":\\\"max(2.5rem, calc((100vw - 1440px) / 2))\\\"},\\\"children\\\":[[\\\"$\\\",\\\"script\\\",null,{\\\"type\\\":\\\"application/ld+json\\\",\\\"dangerouslySetInnerHTML\\\":{\\\"__html\\\":\\\"$5\\\"}}],\\\"$L6\\\"]}],[\\\"$L7\\\",\\\"$L8\\\",\\\"$L9\\\",\\\"$La\\\"],\\\"$Lb\\\"]}],{},null,false,null]},null,false,\\\"$@c\\\"]},null,false,null],\\\"$Ld\\\",false]],\\\"m\\\":\\\"$undefined\\\",\\\"G\\\":[\\\"$e\\\",[\\\"$Lf\\\",\\\"$L10\\\"]],\\\"S\\\":true,\\\"h\\\":null,\\\"s\\\":\\\"$undefined\\\",\\\"l\\\":\\\"$undefined\\\",\\\"p\\\":\\\"$undefined\\\",\\\"d\\\":\\\"$undefined\\\"}\\n\"])\n<script>self.__next_f.push([1,\"1b:[[\\\"$\\\",\\\"title\\\",\\\"0\\\",{\\\"children\\\":\\\"Pricing | Autumn\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"1\\\",{\\\"name\\\":\\\"description\\\",\\\"content\\\":\\\"Autumn pricing. Start free with 8K monthly billing volume, scale to Pro from $375/month, or talk to us about volume discounts.\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"2\\\",{\\\"name\\\":\\\"application-name\\\",\\\"content\\\":\\\"Autumn\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"3\\\",{\\\"name\\\":\\\"author\\\",\\\"content\\\":\\\"Autumn\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"4\\\",{\\\"name\\\":\\\"keywords\\\",\\\"content\\\":\\\"AI billing,usage-based billing,subscription management,AI startups,billing infrastructure,payment integration,usage limits,credit system\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"5\\\",{\\\"name\\\":\\\"creator\\\",\\\"content\\\":\\\"Autumn\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"6\\\",{\\\"name\\\":\\\"robots\\\",\\\"content\\\":\\\"index, follow\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"7\\\",{\\\"name\\\":\\\"googlebot\\\",\\\"content\\\":\\\"index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1\\\"}],[\\\"$\\\",\\\"link\\\",\\\"8\\\",{\\\"rel\\\":\\\"canonical\\\",\\\"href\\\":\\\"https://useautumn.com/pricing\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"9\\\",{\\\"property\\\":\\\"og:title\\\",\\\"content\\\":\\\"Autumn — Billing Infrastructure for AI Startups\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"10\\\",{\\\"property\\\":\\\"og:description\\\",\\\"content\\\":\\\"The drop-in billing layer for AI startups. Stop rebuilding usage limits, credit systems, and subscription logic.\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"11\\\",{\\\"property\\\":\\\"og:url\\\",\\\"content\\\":\\\"https://useautumn.com\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"12\\\",{\\\"property\\\":\\\"og:site_name\\\",\\\"content\\\":\\\"Autumn\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"13\\\",{\\\"property\\\":\\\"og:locale\\\",\\\"content\\\":\\\"en_US\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"14\\\",{\\\"property\\\":\\\"og:image\\\",\\\"content\\\":\\\"https://useautumn.com/images/og-image.png\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"15\\\",{\\\"property\\\":\\\"og:image:width\\\",\\\"content\\\":\\\"1200\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"16\\\",{\\\"property\\\":\\\"og:image:height\\\",\\\"content\\\":\\\"630\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"17\\\",{\\\"property\\\":\\\"og:image:alt\\\",\\\"content\\\":\\\"Autumn — Billing Infrastructure for AI Startups\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"18\\\",{\\\"property\\\":\\\"og:type\\\",\\\"content\\\":\\\"website\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"19\\\",{\\\"name\\\":\\\"twitter:card\\\",\\\"content\\\":\\\"summary_large_image\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"20\\\",{\\\"name\\\":\\\"twitter:title\\\",\\\"content\\\":\\\"Autumn — Billing Infrastructure for AI Startups\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"21\\\",{\\\"name\\\":\\\"twitter:description\\\",\\\"content\\\":\\\"The drop-in billing layer for AI startups. Stop rebuilding usage limits, credit systems, and subscription logic.\\\"}],[\\\"$\\\",\\\"meta\\\",\\\"22\\\",{\\\"name\\\":\\\"twitter:image\\\",\\\"content\\\":\\\"https://useautumn.com/images/og-image.png\\\"}],[\\\"$\\\",\\\"link\\\",\\\"23\\\",{\\\"rel\\\":\\\"icon\\\",\\\"href\\\":\\\"/favicon.ico\\\",\\\"sizes\\\":\\\"48x48\\\",\\\"type\\\":\\\"image/x-icon\\\"}],[\\\"$\\\",\\\"link\\\",\\\"24\\\",{\\\"rel\\\":\\\"icon\\\",\\\"href\\\":\\\"/favicon-48x48.png\\\",\\\"sizes\\\":\\\"48x48\\\",\\\"type\\\":\\\"image/png\\\"}],[\\\"$\\\",\\\"link\\\",\\\"25\\\",{\\\"rel\\\":\\\"icon\\\",\\\"href\\\":\\\"/icon-192.png\\\",\\\"sizes\\\":\\\"192x192\\\",\\\"type\\\":\\\"image/png\\\"}],[\\\"$\\\",\\\"link\\\",\\\"26\\\",{\\\"rel\\\":\\\"apple-touch-icon\\\",\\\"href\\\":\\\"/apple-touch-icon.png\\\",\\\"sizes\\\":\\\"180x180\\\"}],[\\\"$\\\",\\\"$L1c\\\",\\\"27\\\",{}]]\\n\"])\n---EXIT:0---\n","type":"text"}]}
Thinking…

I now have pricing info for Autumn itself:

  • Free: 8K monthly billing volume
  • Pro: from $375/month, 50K monthly billing volume, then $5 per 1M requests. There's a volume slider with tiers.

Let me get a bit more detail from the pricing page about tiers. Let me extract the visible text more cleanly. Actually the page is Next.js with data embedded. Let me grep for "K monthly billing volume" and dollar amounts.

$ curl -s -L --max-time 20 "https://useautumn.com/pricing" | python3 -c "{"content":[{"text":"Start free. Scale with confidence.\nMonthly billing volume\n8K\n50K\n200K\n400K\n500K+\nFREE\n$\n0\n/month\nPerfect while finding PMF. Ever…ctrl+o
curl -s -L --max-time 20 "https://useautumn.com/pricing" | python3 -c "
import sys, re, html
t = sys.stdin.read()
# strip scripts/styles
t = re.sub(r'<script.*?</script>', ' ', t, flags=re.S)
t = re.sub(r'<style.*?</style>', ' ', t, flags=re.S)
t = re.sub(r'<[^>]+>', '\n', t)
t = html.unescape(t)
lines = [l.strip() for l in t.splitlines() if l.strip()]
# find the pricing section
out=[]
cap=False
for l in lines:
    if l.startswith('Start free'):
        cap=True
    if cap:
        out.append(l)
print('\n'.join(out[:200]))
"

{"content":[{"text":"Start free. Scale with confidence.\nMonthly billing volume\n8K\n50K\n200K\n400K\n500K+\nFREE\n$\n0\n/month\nPerfect while finding PMF. Everything you need to start.\n8K monthly billing volume\n10,000 customers and entities\n10M API requests included\nCLI and MCP\nCommunity support\nGet started\nRECOMMENDED\nPRO\n$\n375\n/month\nFor teams scaling with real usage-based pricing.\n50K monthly billing volume\n20M API requests included\nthen $5 per 1M requests\nUnlimited customers and entities\nUsage event aggregation\nData warehouse integration\nMultiple billing sources\nStripe, RevenueCat, Vercel\nDedicated Slack support\nStart with Pro\nSCALE\nCustom\nFor high throughput, compliance, or custom requirements.\nEverything in Pro\nUnlimited billing volume\nEvent volume discount\nEnd-to-end implementation\nDedicated cache infrastructure\nContact us\nAutumn is built on top of Stripe billing, so Stripe fees (0.7% and 2.9% + 30¢) still apply.\n//\nFAQ\n","type":"text"}]}
Thinking…

Now I have Autumn's own pricing:

  • Free: $0/month, 8K monthly billing volume, 10K customers/entities, 10M API requests included, CLI and MCP, community support.
  • Pro: $375/month, 50K monthly billing volume, 20M API requests included then $5 per 1M requests, unlimited customers/entities, usage event aggregation, data warehouse integration, multiple billing sources (Stripe, RevenueCat, Vercel), dedicated Slack support.
  • Scale: Custom, everything in Pro, unlimited billing volume, event volume discount, E2E implementation, dedicated cache infra.
  • Stripe fees still apply: 0.7% and 2.9% + 30¢.

"Billing volume" likely means monthly revenue processed (the slider values 8K, 50K, 200K, 400K, 500K+ = monthly billing volume tiers).

Now, the user asked to "help me build a simple example using Autumn." I need to actually build something. The product has a clear developer workflow: SDK (autumn-js), REST API, CLI (atmn), and MCP. I can build an example without API key by writing a working sample and possibly a keyless sandbox via atmn init/login --keyless.

Let me consider whether I can actually run a live example. The constraint: "Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop."

The CLI atmn init is interactive (asks questions). atmn login --keyless creates a sandbox without an account — but I'd need to run the CLI which downloads via npx. That's not a "local service stack" and it's not long-running, but it may be interactive. However, there might be a non-interactive approach with env vars or flags. Let me check the CLI commands reference for login --keyless and whether there's a way to script it (e.g., CI=true, or a --yes). Also atmn api can call any endpoint.

Actually, my goal is just to "build a simple example" — that can be a workable example project (code) rather than a live end-to-end run. But the user says "use the hosted product through its SDK or API." So I should produce code that uses autumn-js / REST, plus a CLI config. I can attempt to actually run it if I can obtain a key quickly (keyless sandbox). If the keyless path requires interactivity or browser, I'll note it and provide the example code with instructions.

Let me check the CLI commands doc for keyless flags.

$ curl -s --max-time 20 "https://docs.useautumn.com/cli/commands.md" | sed -n '1,260p'{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all…ctrl+o
{"content":[{"text":"> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt\n> Use this file to discover all available pages before exploring further.\n\n# Command reference\n\n> All atmn CLI commands, flags and environment variables\n\nRun `atmn --help` or `atmn <command> --help` to see the latest options.\n\n## Global flags\n\nThese work with every command.\n\n| Flag                   | Description                                                                                                                                                        |\n| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `-p, --prod`           | Target production instead of sandbox                                                                                                                               |\n| `--sandbox <id>`       | Target a specific [sandbox](#sandboxes)                                                                                                                            |\n| `-c, --config <path>`  | Your `autumn.config.ts`, or the folder holding it. By default the CLI looks in the current folder, then at the path `atmn init` saved in your root `package.json`. |\n| `--headless`           | Never prompt. When a command needs an answer, it prints which flag to pass and stops. This is the default outside a terminal, eg in CI or when run by an agent.    |\n| `-l, --local`          | Send requests to a local Autumn server on `localhost:8080`                                                                                                         |\n| `--port <port>`        | Port of the local server. Implies `--local`.                                                                                                                       |\n| `-b, --base-url <url>` | Send requests to this URL instead                                                                                                                                  |\n| `-v, -V, --version`    | Print the CLI version                                                                                                                                              |\n\n## Environment variables\n\nThe CLI reads `.env.local` and then `.env` from your repo root, your config folder and the current folder. Anything already set in your shell wins over the files.\n\n| Variable                         | Description                                                           |\n| -------------------------------- | --------------------------------------------------------------------- |\n| `AUTUMN_SECRET_KEY`              | Your sandbox key. Written by `atmn login`.                            |\n| `AUTUMN_PROD_SECRET_KEY`         | Your production key, used with `-p`. Written by `atmn login`.         |\n| `AUTUMN_SANDBOX_ID`              | Pins every command to a named sandbox. Written by `atmn sandbox use`. |\n| `AUTUMN_SANDBOX_<ID>_SECRET_KEY` | The key for one named sandbox. Written by `atmn sandbox create`.      |\n| `AUTUMN_BASE_URL`                | Send requests to this URL instead of `https://api.useautumn.com`.     |\n\nIn CI, set the key as a secret, install your dependencies, and push:\n\n```yaml theme={null}\n- name: Deploy pricing\n  run: npx atmn push --prod --yes\n  env:\n    AUTUMN_PROD_SECRET_KEY: ${{ secrets.AUTUMN_PROD_SECRET_KEY }}\n```\n\n## Setup\n\n### `atmn init`\n\nSet up your repo end to end: connect to Autumn, create the config folder, pull what's already in your organization, and install the agent skills. See [getting started](/cli/getting-started#set-up-a-project) for what it creates.\n\n```bash theme={null}\natmn init\n```\n\n| Flag            | Description                                                                  |\n| --------------- | ---------------------------------------------------------------------------- |\n| `--login`       | Connect by signing in on the web                                             |\n| `--keyless`     | Connect by creating a sandbox with no account                                |\n| `--path <dir>`  | Folder for the config. Default `autumn`, or `packages/autumn` in a monorepo. |\n| `--name <name>` | Name of the config package (monorepos only)                                  |\n\nWith no key on disk, `init` asks how you want to connect. In headless mode it prints the two flags and stops; run it again with one of them to continue. Running `init` again on a repo that's already set up is safe: it keeps your config and only fills in what's missing.\n\n### `atmn login`\n\nConnect to Autumn and write your organization's keys to `.env`. Opens your browser and lets you pick an organization. Outside a terminal it prints the URL for you to open.\n\n```bash theme={null}\natmn login\n```\n\n| Flag              | Description                                                                                             |\n| ----------------- | ------------------------------------------------------------------------------------------------------- |\n| `--keyless`       | Create a sandbox with no account, and write its key to `.env`                                           |\n| `--claim <email>` | Link a keyless sandbox to an account. Prints and emails a sign-in link. The key you have keeps working. |\n\n### `atmn env`\n\nShow which organization, environment and key your commands will use:\n\n```bash theme={null}\natmn env\n```\n\n```\nOrganization  Acme (acme)\nEnvironment   Sandbox\nUser          you@acme.com\nKey           AUTUMN_SECRET_KEY\n```\n\n| Flag     | Description                                                           |\n| -------- | --------------------------------------------------------------------- |\n| `--json` | Print the same facts as JSON, with notes on anything that looks wrong |\n\n## Config\n\n### `atmn push`\n\nCompare your config with what's in Autumn, and apply the difference.\n\n```bash theme={null}\natmn push          # preview\natmn push --yes    # apply\n```\n\n| Flag            | Description                         |\n| --------------- | ----------------------------------- |\n| `-y, --yes`     | Apply the changes the preview shows |\n| `-d, --dry-run` | Preview only, even with `--yes`     |\n\nA plain `push` is always a preview. It shows what would be created, updated or deleted, and nothing is sent until you add `--yes`. Deletions work the same way: a plan you remove from the config is removed from Autumn on the next `push --yes`.\n\nIf a change affects a plan version that has customers, Autumn drafts a migration and `push` prints the link to run it. After applying, the CLI writes the `internalId` of each new feature and plan back into your config files.\n\n### `atmn pull`\n\nWrite what's in Autumn back into your config files.\n\n```bash theme={null}\natmn pull\n```\n\n| Flag                 | Description                                                                    |\n| -------------------- | ------------------------------------------------------------------------------ |\n| `--overwrite`        | Rewrite the config from Autumn instead of updating it in place. Needs `--yes`. |\n| `-y, --yes`          | Confirm the overwrite                                                          |\n| `--include-mappings` | Keep Stripe and RevenueCat mappings in the pulled config                       |\n\nBy default, `pull` updates in place: it adds new features and plans, updates existing ones, and removes deleted ones, keeping your formatting. If you have no config yet, it asks where to create one (pass `-c <dir>` to skip the question).\n\n`--overwrite --yes` rewrites `autumn.config.ts` and the `features.ts`, `plans.ts` and `rewards.ts` beside it from Autumn. Use it after switching organizations, or to move a 1.x config to the new format. Nothing is deleted, and files that don't import from `atmn` are left alone.\n\n### `atmn reset`\n\nWipe a sandbox: every customer, plan, feature and migration draft. Keys and settings stay.\n\n```bash theme={null}\natmn reset --yes\n```\n\n| Flag        | Description                                                |\n| ----------- | ---------------------------------------------------------- |\n| `-y, --yes` | Wipe it. Without this, `reset` only says what it would do. |\n\n`reset` refuses to run against a production key. Run `atmn push --yes` afterwards to rebuild the sandbox from your config.\n\n## API\n\n### `atmn api`\n\nCall any public API endpoint from the terminal. The command name matches the endpoint: `atmn api <group> <method>`.\n\n```bash theme={null}\natmn api customers get_or_create customer_id=user_123 name=\"Ada Lovelace\"\natmn api balances check customer_id=user_123 feature_id=messages\natmn api billing attach customer_id=user_123 plan_id=pro\natmn api plans list\n```\n\n| Flag                    | Description                                                     |\n| ----------------------- | --------------------------------------------------------------- |\n| `--body <json>`         | The whole request body as JSON. Pass `-` to read it from stdin. |\n| `-H, --header <header>` | An extra request header, as `\"name: value\"`. Repeatable.        |\n| `--curl`                | Print the request as a `curl` command instead of sending it     |\n\nBody fields are passed as `key=value`. Numbers and booleans are converted for you, and fields that take an object or array are parsed as JSON:\n\n```bash theme={null}\natmn api customers update customer_id=user_123 metadata='{\"tier\":\"gold\"}'\n```\n\nYou can combine `--body` with `key=value` pairs; the pairs override fields in the body. Responses are printed as JSON. On an error, the status line goes to stderr, the response body goes to stdout, and the command exits with code 1.\n\n`atmn api` uses the same key as every other command, so `-p` and `--sandbox` work with it. Run `atmn api --help` to list the groups, and `atmn api <group> <method> --help` to see an endpoint's fields.\n\nGroups: `balances`, `billing`, `customers`, `entities`, `events`, `features`, `invoices`, `keys`, `licenses`, `plans`, `platform`, `referral_programs`, `referrals`, `rewards`, `sandboxes`.\n\n## Sandboxes\n\nSandboxes are separate copies of your organization, each with its own plans, customers and API key. Use them to test changes without touching your main sandbox.\n\n```bash theme={null}\natmn sandbox list                          # show your sandboxes\natmn sandbox create staging --use          # create one and switch to it\natmn sandbox use staging                   # switch to one by name or id\natmn sandbox use --clear                   # go back to your main sandbox\natmn sandbox delete <id> --yes             # delete one, with its plans and customers\n```\n\n### `atmn sandbox list`\n\n| Flag     | Description                             |\n| -------- | --------------------------------------- |\n| `--json` | Print the response instead of the table |\n\n### `atmn sandbox create <name>`\n\nCreates the sandbox and writes its key to `.env` as `AUTUMN_SANDBOX_<ID>_SECRET_KEY`.\n\n| Flag              | Description                               |\n| ----------------- | ----------------------------------------- |\n| `--use`           | Switch to it right away                   |\n| `--color <color>` | Color the dashboard labels it with        |\n| `--icon <icon>`   | Icon the dashboard labels it with         |\n| `--json`          | Print the response instead of the summary |\n\n### `atmn sandbox use [name or id]`\n\nWrites `AUTUMN_SANDBOX_ID` to your `.env`, so every later command targets that sandbox. With no name it asks which one. Add `-p` to any command to target production regardless of the pin.\n\n| Flag      | Description                                                |\n| --------- | ---------------------------------------------------------- |\n| `--clear` | Remove the pin, so commands target your main sandbox again |\n| `--json`  | Print the result as JSON                                   |\n\n### `atmn sandbox delete <id>`\n\n| Flag        | Description                             |\n| ----------- | --------------------------------------- |\n| `-y, --yes` | Delete it, plans and customers included |\n\n<Note>\n  `sandbox list`, `create` and `delete` always use your main key (`AUTUMN_SECRET_KEY`), even when a sandbox is pinned. If you want to target a sandbox for one command without pinning it, pass `--sandbox <id>`.\n</Note>\n\n## Skills\n\nThe CLI ships with skills that teach coding agents how to set up Autumn, model pricing, and integrate the API: `autumn-setup`, `autumn-catalog`, `autumn-integrate` and `autumn-concepts`.\n\n### `atmn skills [name]`\n\nList the bundled skills, or print one:\n\n```bash theme={null}\natmn skills\natmn skills autumn-catalog\n```\n\n| Flag           | Description                                      |\n| -------------- | ------------------------------------------------ |\n| `--ref <path>` | Print one of the skill's reference files instead |\n| `--json`       | Print the skill as JSON                          |\n\n### `atmn skills install`\n\nWrite the skills into a `skills/` folder next to your config, so your agent can use them. `atmn init` does this for you.\n\n| Flag          | Description                                                                  |\n| ------------- | ---------------------------------------------------------------------------- |\n| `--dir <dir>` | Write them somewhere else                                                    |\n| `--link`      | Run `npx skills add <dir> --all` afterwards to register them with your agent |\n\n### `atmn skills update`\n\nBring installed skills up to the version bundled with this CLI. `push` and `pull` tell you when yours are out of date.\n\n| Flag          | Description                                                   |\n","type":"text"}]}
Thinking…

This is great. The CLI supports --headless and --keyless. So I can run:

npx atmn login --keyless in headless mode? Actually login --keyless "Create a sandbox with no account, and write its key to .env". This should be non-interactive. The global flag --headless is default outside a terminal (in CI or agent). So npx atmn login --keyless should work non-interactively and write a AUTUMN_SECRET_KEY to .env.

Then I can run atmn api ... calls (e.g., customers get_or_create, check, track, plans list) against the hosted API — this would be a real live example. And I can write a config and atmn push --yes to create the Free/Pro pricing (as documented). This is exactly "use the hosted product through its SDK or API" via the CLI. Also atmn init --keyless sets up a keyless sandbox and config folder, but init also installs atmn into package.json and runs installs (could be heavier). Maybe simpler: npx atmn login --keyless, then manually write config and npx atmn push --yes.

But wait — does npx atmn exist as a package? The docs say npx atmn init, bunx atmn init. So the npm package is atmn. Good.

Potential blockers:

  1. npx may take time to download the package (first run). That's fine, not "long-running service stacks". But could be a bit slow. I should set a reasonable timeout.
  2. login --keyless may still prompt even in headless? It says headless: "Never prompt. When a command needs an answer, it prints which flag to pass and stops." login --keyless doesn't need answers. So should work.
  3. Network egress to api.useautumn.com must be allowed. Let me verify with a quick curl to the API base.

Let me check connectivity and whether npx/atmn is available. Also check node/npm availability.

Let me first check the environment: node, npm, bun. And connectivity to api.useautumn.com.

$ node --version 2>&1; npm --version 2>&1; bun --version 2>&1; echo "---"; curl -s -o /dev/null -w "%{http_code}\n" --max-time 10 https://api.useautumn.com/ ; echo "---"; curl -s -o /dev/null -w "%{http…{"content":[{"text":"v22.23.2\n10.9.8\n1.3.14\n---\n200\n---\n401\n","type":"text"}]}ctrl+o
node --version 2>&1; npm --version 2>&1; bun --version 2>&1; echo "---"; curl -s -o /dev/null -w "%{http_code}\n" --max-time 10 https://api.useautumn.com/ ; echo "---"; curl -s -o /dev/null -w "%{http_code}\n" --max-time 10 https://api.useautumn.com/v1/customers

Thinking…

Node 22, npm 10, bun 1.3.14 available. api.useautumn.com reachable; /v1/customers returns 401 without auth (as expected). Good.

Plan:

  1. Run npx atmn login --keyless to create a keyless sandbox and get a key in .env. This uses hosted product, no local stack.
  2. Verify with npx atmn env --json.
  3. Create a minimal project: write autumn/autumn.config.ts (or features.ts/plans.ts). Actually for a "simple example", I'll create a small Node (TypeScript) example plus config. But to keep it light and actually runnable, I'll:
    • Use CLI to push the pricing config (Free/Pro with messages feature).
    • Then use atmn api to demonstrate the runtime: get_or_create a customer, check, track. This proves the SDK/API workflow live.
  4. Also write an example file using autumn-js (the actual SDK) as a deliverable the user can use in their app — but I can't run the JS SDK without installing the package. I could npm install autumn-js and write a tiny script that reads AUTUMN_SECRET_KEY and calls check/track. That would be a "simple example using Autumn" through the SDK. That's a legitimate deliverable.

But wait: the keyless sandbox is created via CLI and its key is written to .env. I can then use that key with autumn-js or REST directly.

Let me be careful with the user's instructions: "Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop."

npx atmn login --keyless is a network command, no local stack. Should be quick-ish (npx download). Let me run it with a timeout. I'll work in /sandbox/repo. Let me create a working directory, e.g., /sandbox/repo/autumn-example.

Actually, first check if /sandbox/repo already has something.

$ pwd; ls -la; echo "---git---"; git -C /sandbox/repo status --short 2>&1 | head{"content":[{"text":"/sandbox/repo\ntotal 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Sep 19 05:06 ..\ndrwxr-xr-x 8 root root 40…ctrl+o
{"content":[{"text":"/sandbox/repo\ntotal 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Sep 19 05:06 ..\ndrwxr-xr-x 8 root root 4096 Sep 18 08:00 .git\n-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore\n---git---\n","type":"text"}]}
Thinking…

Empty repo (just .git and .gitignore). Let me check .gitignore.

$ cat /sandbox/repo/.gitignore{"content":[{"text":"# Keep generated and vendored files out of source diffs.\n\n# Logs / OS cruft\n*.log\n.DS_Store\n\n# JavaScript / TypeScript\nnode_modules/…ctrl+o
{"content":[{"text":"# Keep generated and vendored files out of source diffs.\n\n# Logs / OS cruft\n*.log\n.DS_Store\n\n# JavaScript / TypeScript\nnode_modules/\n.next/\ndist/\nbuild/\ncoverage/\n\n# Python\n.venv/\nvenv/\n__pycache__/\n*.py[cod]\n.pytest_cache/\n*.egg-info/\n\n# Rust\ntarget/\n\n# Go / PHP / Ruby vendored deps\nvendor/\n.bundle/\n\n# Java / Kotlin / Scala\n.gradle/\n\n# .NET\nbin/\nobj/\n\n# Elixir\n_build/\ndeps/\n\n# Dart / Flutter\n.dart_tool/\n","type":"text"}]}
Thinking…

.env is not in .gitignore. I should ensure the secret key doesn't get committed. I'll add .env to .gitignore (and .env.local), since it holds the API key. That's important.

Now let me run npx atmn login --keyless. I'll do it in /sandbox/repo. Use a timeout (e.g., 120s in case npx downloads). Let me capture output.

$ cd /sandbox/repo && npx -y atmn login --keyless 2>&1 | tail -40; echo "---EXIT:$?---"; ls -la{"content":[{"text":"npm warn deprecated @oslojs/jwt@0.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm wa…ctrl+o
{"content":[{"text":"npm warn deprecated @oslojs/jwt@0.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/binary@1.0.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/asn1@1.0.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/crypto@1.0.1: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated arctic@3.7.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\n✓ Created sandbox org repo_65582522 (keyless). Wrote AUTUMN_SECRET_KEY to /sandbox/repo/.env\n  This org has no owner yet. Link it within 3 days: atmn login --claim you@example.com\nnpm notice\nnpm notice New major version of npm available! 10.9.8 -> 12.0.2\nnpm notice Changelog: https://github.com/npm/cli/releases/tag/v12.0.2\nnpm notice To update run: npm install -g npm@12.0.2\nnpm notice\n---EXIT:0---\ntotal 20\ndrwxr-xr-x 3 root root 4096 Sep 19 05:08 .\ndrwxr-xr-x 8 root root 4096 Sep 19 05:08 ..\n-rw------- 1 root root   72 Sep 19 05:08 .env\ndrwxr-xr-x 8 root root 4096 Sep 19 05:08 .git\n-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore\n","type":"text"}]}
Thinking…

I now have a keyless sandbox org repo_65582522 with AUTUMN_SECRET_KEY in .env. Let me verify with npx atmn env --json. And check the key prefix (don't print the whole key in final response, just confirm). Let me view .env mask the key.

Actually let me not print the key. I'll verify by running atmn env --json but it may print the key; I'll mask. Better: run atmn api plans list to check it works and what plans exist (should be empty).

$ cd /sandbox/repo && npx -y atmn env --json 2>&1 | sed -E 's/(am_sk_[A-Za-z0-9_-]+)/am_sk_***REDACTED***/g'; echo "---plans---"; npx -y atmn api plans list 2>&1 | tail -30{"content":[{"text":"{\n \"organization\": {\n \"id\": \"org_3JX5LRP1qemLAPFUenOJZUfQFzh\",\n \"name\": \"repo\",\n \"slug\": \"repo_65582522\"\n },\…ctrl+o
{"content":[{"text":"{\n  \"organization\": {\n    \"id\": \"org_3JX5LRP1qemLAPFUenOJZUfQFzh\",\n    \"name\": \"repo\",\n    \"slug\": \"repo_65582522\"\n  },\n  \"env\": \"sandbox\",\n  \"isMaster\": true,\n  \"claimed\": false,\n  \"claimExpiresAt\": \"2026-09-22T05:08:35.097Z\",\n  \"sandbox\": null,\n  \"user\": null,\n  \"keyName\": \"AUTUMN_SECRET_KEY\",\n  \"baseUrl\": \"https://api.useautumn.com\",\n  \"notes\": [\n    \"This org has no owner yet (link it before 2026-09-22T05:08:35.097Z): atmn login --claim <email>.\",\n    \"`atmn sandbox use <name|id>` targets a named sandbox; `atmn sandbox list` shows them.\"\n  ]\n}\n---plans---\n{\n  \"list\": []\n}\n","type":"text"}]}
Thinking…

Works. Now I'll build the example:

  1. Create config files (autumn/autumn.config.ts) defining the Free/Pro plans with a messages metered feature. Then npx atmn push --yes to apply.

Actually the docs for atmn init create features.ts/plans.ts split, but a single config file works: "A single autumn.config.ts with everything in it works too." I'll use a single file for simplicity. But note the config's default export atmn({ features: [...], plans: [...] }). I need to write TypeScript. The CLI will load it (it presumably compiles with its bundled TS runner). I don't need to install atmn locally since config imports from "atmn"; the CLI resolves it from its own package. But wait: the config file import { atmn, feature, plan } from "atmn"; — when the CLI runs the config, does it resolve "atmn" from the project's node_modules or from the CLI's bundled deps?

The docs: init "Adds atmn to your package.json and installs it, because the config imports from it." So the project must have atmn installed. Without it, import resolution may fail. I could either run npm install atmn locally (light, quick) or use atmn init --keyless to set up the folder with package.json wiring. Simpler and cleanest: create package.json and run npm install atmn (or just npm i -D atmn). Actually the config is not "run" by Node; the CLI loads it. The import must resolve at runtime in the CLI's process, which transpiles and imports the config. It likely resolves "atmn" relative to the config file's directory (so project node_modules). Let me check what atmn init would produce, or just install atmn locally, which is fast. But npx atmn itself just downloaded the CLI earlier into npx cache; node_modules of the project is separate.

Simplest robust path: run npm install atmn in /sandbox/repo (creates node_modules, package.json). That's a light one-time install, not a service stack. Fine.

But actually, maybe even simpler: use the atmn init --keyless --path autumn to auto-setup (it creates config, package.json wiring, installs atmn, pulls existing = empty). But init also "Installs the Autumn skills next to the config" — writes skills files. That's extra but fine. However init might ask about monorepo? It said in a monorepo asks where folder should go. This is not a monorepo (no packages/), so it'll default to autumn. With --path autumn and --keyless it should be non-interactive. But there's a risk init does more (installs skills, modifies package.json, runs npm install). That's still light. But it might create a bunch of scaffold files.

I'll go the explicit route: write my own minimal config and install atmn package locally. Let me do it.

Actually, wait — do I even need atmn installed locally? Let me test by writing the config and running npx atmn push (dry-run) to see if it errors on module resolution. If it errors, install atmn. But to save roundtrips, I'll just install atmn (it's quick) AND write config in one go? Installing atmn pulls the same package that npx already downloaded, into project node_modules. Let me do npm init -y then npm i atmn — but that writes package.json. Fine.

Let me structure the example deliverables:

  • autumn/autumn.config.ts — pricing config (features + plans): messages feature, free plan (5/month), pro plan ($20/month, 100/month).
  • src/example.ts (or .mjs) — a small runtime demo using autumn-js SDK: create customer, check, track. Actually maybe simpler to demonstrate npm autumn-js.

But the user wants a "simple example" — I'll produce a compact Node example using the autumn-js SDK (matching the docs), plus the config. Since I have a live key, I can actually run it.

Let me first check the autumn-js package API surface quickly to ensure correct method names. From docs: new Autumn({ secretKey }), autumn.customers.getOrCreate({customerId, name, email}), autumn.check({customerId, featureId, requiredBalance}), autumn.track({customerId, featureId, value}), autumn.billing.attach(...). I'll trust the docs.

Let me also verify whether the SDK is ESM or CJS and how to import in Node. The docs show import { Autumn } from "autumn-js". I can use TypeScript via npx tsx or write .mjs. To keep it light, I'll write an .mjs file using ESM import, and run with node. Or simpler, write plain JS (CommonJS not needed). Node 22 supports ESM .mjs.

Plan execution:

  1. npm init -y then npm install atmn autumn-js (both needed: atmn for config imports, autumn-js for runtime example). Actually do I need atmn in node_modules? Let me test config resolution after creating config without local atmn. But just install both to be safe. autumn-js is the SDK. Wait, is the SDK package really named autumn-js? Docs repeatedly say npm install autumn-js and import { Autumn } from "autumn-js". Yes.
  2. Write config and example.
  3. Run npx atmn push (preview), then --yes.
  4. Run example script with AUTUMN_SECRET_KEY from .env.

Let me install packages first (with timeout). Also add .env to .gitignore now.

Let me do the install and .gitignore edit in parallel.

$ cd /sandbox/repo && npm init -y >/dev/null 2>&1 && npm install atmn autumn-js 2>&1 | tail -15; echo "---EXIT:$?---"{"content":[{"text":"npm warn deprecated @oslojs/jwt@0.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm wa…ctrl+o
{"content":[{"text":"npm warn deprecated @oslojs/jwt@0.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/asn1@1.0.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/binary@1.0.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated @oslojs/crypto@1.0.1: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\nnpm warn deprecated arctic@3.7.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.\n\nadded 32 packages, and audited 33 packages in 53s\n\n17 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities\n---EXIT:0---\n","type":"text"}]}
edit /sandbox/repo/.gitignore{"content":[{"text":"Successfully replaced 1 block(s) in /sandbox/repo/.gitignore.","type":"text"}],"details":{"diff":" ...\n 3 # Logs / OS cruft\n 4 *.log…ctrl+o
{"content":[{"text":"Successfully replaced 1 block(s) in /sandbox/repo/.gitignore.","type":"text"}],"details":{"diff":"    ...\n  3 # Logs / OS cruft\n  4 *.log\n  5 .DS_Store\n  6 \n+ 7 # Environment / secrets\n+ 8 .env\n+ 9 .env.local\n+10 .env.*.local\n+11 \n  7 # JavaScript / TypeScript\n  8 node_modules/\n  9 .next/\n 10 dist/\n    ...","patch":"--- /sandbox/repo/.gitignore\n+++ /sandbox/repo/.gitignore\n@@ -3,8 +3,13 @@\n # Logs / OS cruft\n *.log\n .DS_Store\n \n+# Environment / secrets\n+.env\n+.env.local\n+.env.*.local\n+\n # JavaScript / TypeScript\n node_modules/\n .next/\n dist/\n","firstChangedLine":7}}
Thinking…

Packages installed. Now let me inspect the installed atmn package structure quickly and autumn-js to confirm API. But I trust docs. Let me write the config and example.

Config file: autumn/autumn.config.ts.

import { atmn, feature, plan } from "atmn";

export const messages = feature({
  featureId: "messages",
  name: "Messages",
  type: "metered",
  consumable: true,
});

export const free = plan({
  planId: "free",
  versionSlug: "v1",
  active: true,
  name: "Free",
  autoEnable: true,
  items: [
    {
      featureId: messages.featureId,
      included: 5,
      reset: { interval: "month" },
    },
  ],
});

export const pro = plan({
  planId: "pro",
  versionSlug: "v1",
  active: true,
  name: "Pro",
  price: {
    amount: 20,
    interval: "month",
  },
  items: [
    {
      featureId: messages.featureId,
      included: 100,
      reset: { interval: "month" },
    },
  ],
});

export default atmn({ features: [messages], plans: [free, pro] });

Then push.

Example script example.mjs:

import { Autumn } from "autumn-js";

const key = process.env.AUTUMN_SECRET_KEY;
if (!key) throw new Error("AUTUMN_SECRET_KEY is not set");

const autumn = new Autumn({ secretKey: key });

const customerId = `user_demo_${Date.now()}`;

// 1. Create customer (auto-enables the Free plan)
const customer = await autumn.customers.getOrCreate({
  customerId,
  name: "Ada Lovelace",
  email: "ada@example.com",
});
console.log("Created customer:", customer.customerId);

// 2. Check access before sending 1 message
let check = await autumn.check({ customerId, featureId: "messages", requiredBalance: 1 });
console.log("check (free, 5/mo):", JSON.stringify({ allowed: check.allowed, balance: check.balance }));

// 3. Track 1 message used
let track = await autumn.track({ customerId, featureId: "messages", value: 1 });
console.log("after track:", JSON.stringify({ remaining: track.balance?.remaining, usage: track.balance?.usage }));

// 4. Attach Pro (returns a Stripe Checkout URL in sandbox)
const attach = await autumn.billing.attach({ customerId, planId: "pro", redirectMode: "always" });
console.log("attach pro -> paymentUrl:", attach.paymentUrl ? "yes (stripe checkout)" : "none");

// 5. Check again now that Pro is attached (skip if no payment completed)
check = await autumn.check({ customerId, featureId: "messages" });
console.log("check (pro):", JSON.stringify({ allowed: check.allowed, balance: check.balance }));

Wait, step 4 attach with redirectMode always will create a Stripe Checkout session. But our keyless sandbox may not have Stripe connected! In sandbox, when you attach a paid plan without Stripe connected, what happens? The keyless sandbox likely has a test Stripe account connected automatically? Hmm. The docs say "Your sandbox has no owner yet" — keyless sandbox. Stripe connection might not exist. Attaching a paid plan might fail with a Stripe-not-connected error, or it might create a payment URL using a default test mode.

Let me think. In Autumn cloud sandbox, there is likely a built-in Stripe test mode connection. Actually the setup doc mentions "Use Stripe's test card 4242..." in sandbox. But that's for an account created in dashboard that connects Stripe. For keyless sandbox, Stripe may not be connected, so attach to a paid plan would error.

To be safe, my example should primarily demonstrate check/track on the auto-enabled free plan (which doesn't require Stripe). For the paid attach, I can attempt it but handle errors gracefully ("attach requires Stripe connected in the sandbox; here's the call to run once connected"). Or I could check whether Stripe is connected.

Actually maybe simpler and more robust: demonstrate:

  1. Config push (pricing).
  2. getOrCreate customer (auto-enables free plan).
  3. check (allowed true, 5 remaining).
  4. track (remaining 4).
  5. Optionally list customer and plans.

And show the attach snippet in the example file but not necessarily run it, or run it and catch errors. That keeps the live demo within non-Stripe flow and avoids blocking.

But "payment flow" is core to pricing; still, the example can include the attach call with graceful handling. Let me try attach after pushing and see what happens; if it errors, I'll capture the error and adapt. It's fine to attempt — it won't charge anything (test mode), and errors are informative. Actually redirectMode: "always" could return a URL even in test. Let me just try after the free-plan part, with try/catch.

Actually, wait. There's a subtlety: attach on a paid plan for a customer with Stripe not connected. Let me check the attach docs context about sandbox Stripe. Not necessary; I'll empirically test and report. If it fails, I'll say "paid attach needs Stripe connected in the dashboard; skipped in the demo, code included."

Let me also confirm the free plan auto-enable works after push. Push must happen before getOrCreate so the free plan exists and auto-enables.

Order:

  1. Write config.
  2. npx atmn push --yes.
  3. Write example.mjs and run it (with env). For env, read .env. I can run set -a; source .env; set +a; node example.mjs. .env has AUTUMN_SECRET_KEY=am_sk_.... Shell source of .env works if format is KEY=value with no spaces. Let me check .env content format (masked).
$ cd /sandbox/repo && sed -E 's/(am_sk_[A-Za-z0-9_-]+)/am_sk_***REDACTED***/g' .env{"content":[{"text":"AUTUMN_SECRET_KEY=am_sk_***REDACTED***\n","type":"text"}]}
Thinking…

Good, .env has AUTUMN_SECRET_KEY=.... Now write the config file.

Let me create autumn/autumn.config.ts.

write /sandbox/repo/autumn/autumn.config.ts{"content":[{"text":"Successfully wrote 945 bytes to /sandbox/repo/autumn/autumn.config.ts","type":"text"}]}
$ cd /sandbox/repo && npx -y atmn push 2>&1 | tail -40{"content":[{"text":"No autumn.config.ts found. Looked in:\n /sandbox/repo\n /sandbox/repo/atmn\n\nRun `atmn init` to create one, or pass -c <dir>.\n","type":…ctrl+o
{"content":[{"text":"No autumn.config.ts found. Looked in:\n  /sandbox/repo\n  /sandbox/repo/atmn\n\nRun `atmn init` to create one, or pass -c <dir>.\n","type":"text"}]}
Thinking…

The CLI looks for the config in root or literally atmn? It said looked in /sandbox/repo and /sandbox/repo/atmn. Hmm, "pass -c <dir>" to specify. My config is in /sandbox/repo/autumn. So run npx atmn push -c autumn. Or it defaults root; I put it in autumn/. Let me use -c autumn.

Actually the message says looked in /sandbox/repo and /sandbox/repo/atmn — odd, maybe it derives from package name field "atmn"? Wait, npm init created package.json with name "repo"? Let me not worry; use -c autumn.

Let me run push preview with -c autumn.

$ cd /sandbox/repo && npx -y atmn push -c autumn 2>&1 | tail -50{"content":[{"text":"Features (1)\n + messages Messages\n\nPlans (2)\n + free@v1 Free\n + Name: \"Free\"\n + messages 5 Messages\n + pro@v1 Pro\n …ctrl+o
{"content":[{"text":"Features (1)\n  + messages  Messages\n\nPlans (2)\n  + free@v1  Free\n    + Name: \"Free\"\n    + messages  5 Messages\n  + pro@v1  Pro\n    + Name: \"Pro\"\n    + Price: $20 per month\n    + messages  100 Messages\n\nNothing applied. Re-run with --yes to apply these changes.\n","type":"text"}]}
Thinking…

Preview looks good. Apply with --yes.

$ cd /sandbox/repo && npx -y atmn push -c autumn --yes 2>&1 | tail -40{"content":[{"text":"Features (1)\n + messages Messages\n\nPlans (2)\n + free@v1 Free\n + Name: \"Free\"\n + messages 5 Messages\n + pro@v1 Pro\n …ctrl+o
{"content":[{"text":"Features (1)\n  + messages  Messages\n\nPlans (2)\n  + free@v1  Free\n    + Name: \"Free\"\n    + messages  5 Messages\n  + pro@v1  Pro\n    + Name: \"Pro\"\n    + Price: $20 per month\n    + messages  100 Messages\n\nApplied.\nWrote internalId into 3 fixtures.\n","type":"text"}]}
Thinking…

Pricing config is now live in the hosted sandbox. The CLI wrote internalId into the config file. Let me check the config file now (it modified it).

read /sandbox/repo/autumn/autumn.config.ts{"content":[{"text":"import { atmn, feature, plan } from \"atmn\";\n\n// Feature: a metered, consumable counter for chat messages.\nexport const messages = feat…ctrl+o
{"content":[{"text":"import { atmn, feature, plan } from \"atmn\";\n\n// Feature: a metered, consumable counter for chat messages.\nexport const messages = feature({\n  internalId: \"fe_3JX5b5hWXuk5qvuKWgJsrn7WMLz\",\n  featureId: \"messages\",\n  name: \"Messages\",\n  type: \"metered\",\n  consumable: true,\n});\n\n// Free plan: auto-assigned to every new customer, grants 5 messages/month.\nexport const free = plan({\n  internalId: \"prod_3JX5b6BqMemlmlE4xjiQcZqAFik\",\n  planId: \"free\",\n  versionSlug: \"v1\",\n  active: true,\n  name: \"Free\",\n  autoEnable: true,\n  items: [\n    {\n      featureId: messages.featureId,\n      included: 5,\n      reset: { interval: \"month\" },\n    },\n  ],\n});\n\n// Pro plan: $20/month, grants 100 messages/month.\nexport const pro = plan({\n  internalId: \"prod_3JX5b5SU0wX3CMiOcJxfFzDMz8X\",\n  planId: \"pro\",\n  versionSlug: \"v1\",\n  active: true,\n  name: \"Pro\",\n  price: {\n    amount: 20,\n    interval: \"month\",\n  },\n  items: [\n    {\n      featureId: messages.featureId,\n      included: 100,\n      reset: { interval: \"month\" },\n    },\n  ],\n});\n\nexport default atmn({ features: [messages], plans: [free, pro] });\n","type":"text"}]}
Thinking…

Now write the runtime example using autumn-js. Let me check the actual exported API quickly to avoid mistakes. I'll inspect node_modules/autumn-js exports/types.

$ cd /sandbox/repo && ls node_modules/autumn-js && echo "---pkg---" && cat node_modules/autumn-js/package.json | head -60{"content":[{"text":"LICENSE.md\nREADME.md\ndist\npackage.json\n---pkg---\n{\n \"name\": \"autumn-js\",\n \"description\": \"Autumn JS Library\",\n \"version…ctrl+o
{"content":[{"text":"LICENSE.md\nREADME.md\ndist\npackage.json\n---pkg---\n{\n  \"name\": \"autumn-js\",\n  \"description\": \"Autumn JS Library\",\n  \"version\": \"1.3.3\",\n  \"repository\": \"github:useautumn/autumn\",\n  \"homepage\": \"https://docs.useautumn.com\",\n  \"main\": \"./dist/sdk/index.js\",\n  \"module\": \"./dist/sdk/index.mjs\",\n  \"types\": \"./dist/sdk/index.d.ts\",\n  \"files\": [\n    \"dist\",\n    \"README.md\",\n    \"LICENSE.md\"\n  ],\n  \"scripts\": {\n    \"ts\": \"tsgo --noEmit --skipLibCheck\",\n    \"build\": \"rm -rf dist && tsup\"\n  },\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/sdk/index.d.ts\",\n      \"require\": \"./dist/sdk/index.js\",\n      \"import\": \"./dist/sdk/index.mjs\"\n    },\n    \"./react\": {\n      \"types\": \"./dist/react/index.d.ts\",\n      \"require\": \"./dist/react/index.js\",\n      \"import\": \"./dist/react/index.mjs\"\n    },\n    \"./backend\": {\n      \"types\": \"./dist/backend/index.d.ts\",\n      \"require\": \"./dist/backend/index.js\",\n      \"import\": \"./dist/backend/index.mjs\"\n    },\n    \"./express\": {\n      \"types\": \"./dist/backend/adapters/express.d.ts\",\n      \"require\": \"./dist/backend/adapters/express.js\",\n      \"import\": \"./dist/backend/adapters/express.mjs\"\n    },\n    \"./fetch\": {\n      \"types\": \"./dist/backend/adapters/fetch.d.ts\",\n      \"require\": \"./dist/backend/adapters/fetch.js\",\n      \"import\": \"./dist/backend/adapters/fetch.mjs\"\n    },\n    \"./hono\": {\n      \"types\": \"./dist/backend/adapters/hono.d.ts\",\n      \"require\": \"./dist/backend/adapters/hono.js\",\n      \"import\": \"./dist/backend/adapters/hono.mjs\"\n    },\n    \"./next\": {\n      \"types\": \"./dist/backend/adapters/next.d.ts\",\n      \"require\": \"./dist/backend/adapters/next.js\",\n      \"import\": \"./dist/backend/adapters/next.mjs\"\n    },\n    \"./better-auth\": {\n      \"types\": \"./dist/better-auth/index.d.ts\",\n      \"require\": \"./dist/better-auth/index.js\",\n      \"import\": \"./dist/better-auth/index.mjs\"\n    }\n  },\n","type":"text"}]}
$ cd /sandbox/repo && grep -nE "class Autumn|constructor|secretKey|getOrCreate|async check|async track|billing|attach|export " node_modules/autumn-js/dist/sdk/index.d.ts | head -60{"content":[{"text":"28: constructor(options?: HTTPClientOptions);\n80: secretKey?: string | (() => Promise<string>) | undefined;\n148: export { files_by…ctrl+o
{"content":[{"text":"28:    constructor(options?: HTTPClientOptions);\n80:    secretKey?: string | (() => Promise<string>) | undefined;\n148:  export { files_bytesToBlob as bytesToBlob, files_getContentTypeFromFileName as getContentTypeFromFileName, files_readableStreamToArrayBuffer as readableStreamToArrayBuffer };\n198:    constructor(message: string, cause: unknown, rawValue: unknown);\n526:declare function attachLicenseEntityToJSON(attachLicenseEntity: AttachLicenseEntity): string;\n535:declare function attachLicenseParamsToJSON(attachLicenseParams: AttachLicenseParams): string;\n538:declare function attachLicenseResponseFromJSON(jsonString: string): Result$1<AttachLicenseResponse, SDKValidationError>;\n642:     * Number of intervals per billing cycle. Defaults to 1.\n754:     * Price per billing_units after included usage. Either 'amount' or 'tiers' is required.\n771:     * Number of intervals per billing cycle. Defaults to 1.\n775:     * Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200).\n777:    billingUnits?: number | undefined;\n781:    billingMethod: AttachItemBillingMethod;\n815: * Proration settings for prepaid features. Controls mid-cycle quantity change billing.\n886:     * Credits consumed per billing-unit group when this dimension matches.\n905:     * Credits consumed per billing-unit group within this tier.\n937:     * Added to the rate after every factor is applied, in credits per billing-unit group.\n949:    billingUnits?: number | undefined;\n963:     * Credits consumed per billing-unit group.\n980:     * Credits consumed per billing-unit group when this dimension matches.\n999:     * Credits consumed per billing-unit group within this tier.\n1031:     * Added to the rate after every factor is applied, in credits per billing-unit group.\n1049:     * Credits consumed per billing-unit group within this tier.\n1061:    billingUnits?: number | undefined;\n1153:     * Proration settings for prepaid features. Controls mid-cycle quantity change billing.\n1273:     * Price per billing_units after included usage. Either 'amount' or 'tiers' is required.\n1290:     * Number of intervals per billing cycle. Defaults to 1.\n1294:     * Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200).\n1296:    billingUnits?: number | undefined;\n1300:    billingMethod: AttachAddItemBillingMethod;\n1334: * Proration settings for prepaid features. Controls mid-cycle quantity change billing.\n1405:     * Credits consumed per billing-unit group when this dimension matches.\n1424:     * Credits consumed per billing-unit group within this tier.\n1456:     * Added to the rate after every factor is applied, in credits per billing-unit group.\n1468:    billingUnits?: number | undefined;\n1482:     * Credits consumed per billing-unit group.\n1499:     * Credits consumed per billing-unit group when this dimension matches.\n1518:     * Credits consumed per billing-unit group within this tier.\n1550:     * Added to the rate after every factor is applied, in credits per billing-unit group.\n1568:     * Credits consumed per billing-unit group within this tier.\n1580:    billingUnits?: number | undefined;\n1672:     * Proration settings for prepaid features. Controls mid-cycle quantity change billing.\n1689: * Match items with this billing method (prepaid or usage_based).\n1696: * Match items with this billing method (prepaid or usage_based).\n1733:     * Match items with this billing method (prepaid or usage_based).\n1735:    billingMethod?: AttachRemoveItemBillingMethod | undefined;\n1887: * Interval for the cap, aligned to the customer's billing cycle.\n1896: * Interval for the cap, aligned to the customer's billing cycle.\n1900: * Window alignment. 'billing_cycle' phases the interval to the customer's renewal time; 'utc' aligns to the UTC calendar.\n1903:    readonly BillingCycle: \"billing_cycle\";\n1907: * Window alignment. 'billing_cycle' phases the interval to the customer's renewal time; 'utc' aligns to the UTC calendar.\n1933:     * Interval for the cap, aligned to the customer's billing cycle.\n1937:     * Window alignment. 'billing_cycle' phases the interval to the customer's renewal time; 'utc' aligns to the UTC calendar.\n2021: * Override the plan's billing controls (auto top-ups, spend limits, usage limits, usage alerts, overage allowed) for this customer.\n2083:     * Number of intervals per billing cycle. Defaults to 1.\n2195:     * Price per billing_units after included usage. Either 'amount' or 'tiers' is required.\n2212:     * Number of intervals per billing cycle. Defaults to 1.\n2216:     * Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200).\n2218:    billingUnits?: number | undefined;\n2222:    billingMethod: AttachUpsertLicenseAddItemBillingMethod;\n","type":"text"}]}
$ cd /sandbox/repo && grep -nE "export declare class|export \{|Autumn" node_modules/autumn-js/dist/sdk/index.d.ts | head -40; echo "---backend index---"; ls node_modules/autumn-js/dist/sdk/ 2>/dev/null …{"content":[{"text":"148: export { files_bytesToBlob as bytesToBlob, files_getContentTypeFromFileName as getContentTypeFromFileName, files_readableStreamToArra…ctrl+o
cd /sandbox/repo && grep -nE "export declare class|export \{|Autumn" node_modules/autumn-js/dist/sdk/index.d.ts | head -40; echo "---backend index---"; ls node_modules/autumn-js/dist/sdk/ 2>/dev/null | head; echo "---readme---"; sed -n '1,120p' node_modules/autumn-js/README.md

{"content":[{"text":"148:  export { files_bytesToBlob as bytesToBlob, files_getContentTypeFromFileName as getContentTypeFromFileName, files_readableStreamToArrayBuffer as readableStreamToArrayBuffer };\n3899:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n3933:     * If true, returns an Autumn-hosted checkout link that can create a fresh Stripe checkout session when opened.\n4494:declare class AutumnError extends Error {\n4513:declare class AutumnDefaultError extends AutumnError {\n8707:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n10319: * Accepted. Autumn is experiencing degraded service from a downstream provider, so access was allowed fail-open.\n12223:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n30992:     * List of discounts to apply to the immediate phase. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n31022:     * If true, the immediate-phase cusProducts are activated immediately (and scheduled-phase cusProducts pre-inserted) even when payment is pending via Stripe checkout. The Autumn schedule rows are persisted on checkout.session.completed.\n31128:     * The ID of the created schedule. Null when the schedule is waiting on Autumn checkout confirmation.\n31132:     * Persisted phases in ascending starts_at order. Empty when waiting on Autumn checkout confirmation.\n32724:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n33682: * Accepted. Autumn is experiencing degraded service from a downstream provider, so the finalize request was allowed fail-open.\n34667:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n37173:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n41094:     * Unix ms timestamp the customer signed up, so a migrated customer keeps its original signup date. Defaults to the import time for a customer Autumn creates here.\n41231:     * The Autumn plan to attach to the customer.\n41279:     * Autumn customer to image into.\n41325:     * True when the imaged state may be wrong — e.g. a resetting plan with no resolvable billing anchor, or a paid recurring plan with no linked subscription for Autumn to manage. The plan is still imaged; see `reason` and fix by supplying started_at or a subscription_id.\n41579:     * The Autumn invoice ID.\n42695:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n44987:     * The plan this line item came from. Null for lines with no Autumn plan behind them.\n45045:     * The Autumn invoice ID\n53837:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n58126:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n58160:     * If true, returns an Autumn-hosted checkout link that can create a fresh Stripe checkout session when opened.\n58448:    readonly AutumnCheckout: \"autumn_checkout\";\n59994:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n60271:    readonly AutumnCheckout: \"autumn_checkout\";\n64822:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n65861:declare class ResponseValidationError extends AutumnError {\n69226:     * List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.\n69943: * Accepted. Autumn is experiencing degraded service from a downstream provider, so the event was accepted for replay and will be tracked as soon as the service is restored.\n70257: * Accepted. Autumn is experiencing degraded service from a downstream provider, so the token usage event was accepted for replay and will be tracked as soon as the service is restored.\n70851:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n71836:     * Stops Autumn from posting usage-overage line items to Stripe for this customer. Check/track and balance resets still behave normally. When set, this overrides the organization-level disable_overage_billing setting.\n83949:     * @param discounts - List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code. (optional)\n83957:     * @param longLivedCheckout - If true, returns an Autumn-hosted checkout link that can create a fresh Stripe checkout session when opened. (optional)\n83989:     * @param discounts - List of discounts to apply to the immediate phase. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code. (optional)\n---backend index---\nindex.d.mts\nindex.d.ts\nindex.js\nindex.mjs\n---readme---\n# Autumn JS Library\n\n`autumn-js` is a JavaScript/TypeScript library for interacting with the Autumn pricing and billing platform. This package provides both a server-side SDK for the Autumn API and a React package for client-side implementation.\n\n## Installation\n\n```bash\nnpm install autumn-js\n```\n\n## Docs\nTo learn how to use `autumn-js`, visit our documentation [here](https://docs.useautumn.com)\n\n`plans.list` responses include each plan's assignable licenses and derived variants.","type":"text"}]}
Thinking…

The .d.ts is huge and generated. Let me specifically find the Autumn class and method signatures for customers.getOrCreate, check, track, and billing.attach. Let me grep for "class Autumn" in the actual SDK source (dist/sdk/index.mjs or classes).

$ cd /sandbox/repo && grep -nE "class Autumn " node_modules/autumn-js/dist/sdk/index.d.ts; grep -nE "getOrCreate|check\(|track\(|attach\(|Balances|Billing|Customers" node_modules/autumn-js/dist/sdk/inde…{"content":[{"text":"84909:declare class Autumn extends ClientSDK {\n605: * Billing interval (e.g. 'month', 'year').\n616: * Billing interval (e.g. 'month', 'ye…ctrl+o
cd /sandbox/repo && grep -nE "class Autumn " node_modules/autumn-js/dist/sdk/index.d.ts; grep -nE "getOrCreate|check\(|track\(|attach\(|Balances|Billing|Customers" node_modules/autumn-js/dist/sdk/index.d.ts | head -60

{"content":[{"text":"84909:declare class Autumn extends ClientSDK {\n605: * Billing interval (e.g. 'month', 'year').\n616: * Billing interval (e.g. 'month', 'year').\n638:     * Billing interval (e.g. 'month', 'year').\n650:type AttachItemThresholdBilling = {\n724: * Billing interval. For consumable features, should match reset.interval.\n735: * Billing interval. For consumable features, should match reset.interval.\n741:declare const AttachItemBillingMethod: {\n748:type AttachItemBillingMethod = ClosedEnum<typeof AttachItemBillingMethod>;\n767:     * Billing interval. For consumable features, should match reset.interval.\n781:    billingMethod: AttachItemBillingMethod;\n788: * Billing behavior when quantity increases mid-cycle.\n797: * Billing behavior when quantity increases mid-cycle.\n819:     * Billing behavior when quantity increases mid-cycle.\n1127:    thresholdBilling?: AttachItemThresholdBilling | null | undefined;\n1169:type AttachAddItemThresholdBilling = {\n1243: * Billing interval. For consumable features, should match reset.interval.\n1254: * Billing interval. For consumable features, should match reset.interval.\n1260:declare const AttachAddItemBillingMethod: {\n1267:type AttachAddItemBillingMethod = ClosedEnum<typeof AttachAddItemBillingMethod>;\n1286:     * Billing interval. For consumable features, should match reset.interval.\n1300:    billingMethod: AttachAddItemBillingMethod;\n1307: * Billing behavior when quantity increases mid-cycle.\n1316: * Billing behavior when quantity increases mid-cycle.\n1338:     * Billing behavior when quantity increases mid-cycle.\n1646:    thresholdBilling?: AttachAddItemThresholdBilling | null | undefined;\n1691:declare const AttachRemoveItemBillingMethod: {\n1698:type AttachRemoveItemBillingMethod = ClosedEnum<typeof AttachRemoveItemBillingMethod>;\n1721: * Match items with this interval. Accepts either a BillingInterval (price-side) or a ResetInterval (reset-side, includes day/hour/minute) so price-less items keyed by reset.interval can be disambiguated.\n1735:    billingMethod?: AttachRemoveItemBillingMethod | undefined;\n1737:     * Match items with this interval. Accepts either a BillingInterval (price-side) or a ResetInterval (reset-side, includes day/hour/minute) so price-less items keyed by reset.interval can be disambiguated.\n1884:    skipOverageBilling?: boolean | undefined;\n1903:    readonly BillingCycle: \"billing_cycle\";\n2023:type AttachBillingControls = {\n2046: * Billing interval (e.g. 'month', 'year').\n2057: * Billing interval (e.g. 'month', 'year').\n2079:     * Billing interval (e.g. 'month', 'year').\n2091:type AttachUpsertLicenseThresholdBilling = {\n2165: * Billing interval. For consumable features, should match reset.interval.\n2176: * Billing interval. For consumable features, should match reset.interval.\n2182:declare const AttachUpsertLicenseAddItemBillingMethod: {\n2189:type AttachUpsertLicenseAddItemBillingMethod = ClosedEnum<typeof AttachUpsertLicenseAddItemBillingMethod>;\n2208:     * Billing interval. For consumable features, should match reset.interval.\n2222:    billingMethod: AttachUpsertLicenseAddItemBillingMethod;\n2229: * Billing behavior when quantity increases mid-cycle.\n2238: * Billing behavior when quantity increases mid-cycle.\n2260:     * Billing behavior when quantity increases mid-cycle.\n2344:type AttachItemThresholdBilling$Outbound = {\n2348:declare const AttachItemThresholdBilling$outboundSchema: z$1.ZodMiniType<AttachItemThresholdBilling$Outbound, AttachItemThresholdBilling>;\n2349:declare function attachItemThresholdBillingToJSON(attachItemThresholdBilling: AttachItemThresholdBilling): string;\n2397:declare const AttachItemBillingMethod$outboundSchema: z$1.ZodMiniEnum<typeof AttachItemBillingMethod>;\n2675:    threshold_billing?: AttachItemThresholdBilling$Outbound | null | undefined;\n2691:type AttachAddItemThresholdBilling$Outbound = {\n2695:declare const AttachAddItemThresholdBilling$outboundSchema: z$1.ZodMiniType<AttachAddItemThresholdBilling$Outbound, AttachAddItemThresholdBilling>;\n2696:declare function attachAddItemThresholdBillingToJSON(attachAddItemThresholdBilling: AttachAddItemThresholdBilling): string;\n2744:declare const AttachAddItemBillingMethod$outboundSchema: z$1.ZodMiniEnum<typeof AttachAddItemBillingMethod>;\n3022:    threshold_billing?: AttachAddItemThresholdBilling$Outbound | null | undefined;\n3038:declare const AttachRemoveItemBillingMethod$outboundSchema: z$1.ZodMiniEnum<typeof AttachRemoveItemBillingMethod>;\n3180:type AttachBillingControls$Outbound = {\n3188:declare const AttachBillingControls$outboundSchema: z$1.ZodMiniType<AttachBillingControls$Outbound, AttachBillingControls>;\n3189:declare function attachBillingControlsToJSON(attachBillingControls: AttachBillingControls): string;\n","type":"text"}]}
$ cd /sandbox/repo && sed -n '84909,85100p' node_modules/autumn-js/dist/sdk/index.d.ts{"content":[{"text":"declare class Autumn extends ClientSDK {\n private _customers?;\n get customers(): Customers;\n private _plans?;\n get plans():…ctrl+o
{"content":[{"text":"declare class Autumn extends ClientSDK {\n    private _customers?;\n    get customers(): Customers;\n    private _plans?;\n    get plans(): Plans;\n    private _features?;\n    get features(): Features;\n    private _billing?;\n    get billing(): Billing;\n    private _balances?;\n    get balances(): Balances;\n    private _events?;\n    get events(): Events;\n    private _invoices?;\n    get invoices(): Invoices;\n    private _licenses?;\n    get licenses(): Licenses;\n    private _entities?;\n    get entities(): Entities;\n    private _referrals?;\n    get referrals(): Referrals;\n    private _rewards?;\n    get rewards(): Rewards;\n    private _platform?;\n    get platform(): Platform;\n    private _keys?;\n    get keys(): Keys;\n    private _sandboxes?;\n    get sandboxes(): Sandboxes;\n    /**\n     * Checks whether a customer currently has enough balance to use a feature.\n     *\n     * Use this to gate access before a feature action. Enable sendEvent when you want to check and consume balance atomically in one request.\n     *\n     * @example\n     * ```typescript\n     * // Check access for a feature\n     * const response = await client.check({ customerId: \"cus_123\", featureId: \"messages\" });\n     * ```\n     *\n     * @example\n     * ```typescript\n     * // Check and consume 3 units in one call\n     * const response = await client.check({\n     *\n     *   customerId: \"cus_123\",\n     *   featureId: \"messages\",\n     *   requiredBalance: 3,\n     *   sendEvent: true,\n     * });\n     * ```\n     *\n     * @param customerId - The ID of the customer.\n     * @param featureId - The ID of the feature.\n     * @param entityId - The ID of the entity for entity-scoped balances (e.g., per-seat limits). (optional)\n     * @param requiredBalance - Minimum balance required for access. Returns allowed: false if the customer's balance is below this value. Defaults to 1. (optional)\n     * @param properties - Additional properties to attach to the usage event if send_event is true. (optional)\n     * @param sendEvent - If true, atomically records a usage event while checking access. The required_balance value is used as the usage amount. Combines check + track in one call. (optional)\n     * @param lock - Reserve units of a feature upfront by passing a lock_id, then call balances.finalize to confirm or release the hold. (optional)\n     * @param withPreview - If true, includes upgrade/upsell information in the response when access is denied. Useful for displaying paywalls. (optional)\n     *\n     * @returns Whether access is allowed, plus the current balance for that feature. If Autumn is experiencing degraded service from a downstream provider, the API may return 202 and allow access fail-open.\n     */\n    check(request: CheckParams, options?: RequestOptions): Promise<CheckResponse>;\n    /**\n     * Records usage for a customer feature and returns updated balances.\n     *\n     * Use this after an action happens to decrement usage, or send a negative value to credit balance back.\n     *\n     * @example\n     * ```typescript\n     * // Track one message event\n     * const response = await client.track({ customerId: \"cus_123\", featureId: \"messages\", value: 1 });\n     * ```\n     *\n     * @example\n     * ```typescript\n     * // Track an event mapped to multiple features\n     * const response = await client.track({ customerId: \"cus_123\", eventName: \"ai_chat_request\", value: 1 });\n     * ```\n     *\n     * @param customerId - The ID of the customer.\n     * @param featureId - The ID of the feature to track usage for. Required if event_name is not provided. (optional)\n     * @param entityId - The ID of the entity for entity-scoped balances (e.g., per-seat limits). (optional)\n     * @param eventName - Event name to track usage for. Use instead of feature_id when multiple features should be tracked from a single event. (optional)\n     * @param value - The amount of usage to record. Defaults to 1. Use negative values to credit balance (e.g., when removing a seat). (optional)\n     * @param properties - Additional properties to attach to this usage event. (optional)\n     * @param timestamp - Unix timestamp in milliseconds to use for the usage event. Defaults to the current time. (optional)\n     * @param overageBehavior - How to handle usage that exceeds the available balance. \"cap\" (default) deducts only what fits, stopping at zero. \"overflow\" deducts the full value: the balance can go negative and usage limits do not clamp the deduction, though spend limits still apply. (optional)\n     * @param async - If true, enqueue the event for asynchronous processing and return 204 immediately. The response will not include balance information. (optional)\n     *\n     * @returns The usage value recorded, with either a single updated balance or a map of updated balances. If Autumn is experiencing degraded service from a downstream provider, the API may return 202 after accepting the event for replay so it can be tracked as soon as the service is restored.\n     */\n    track(request: TrackParams, options?: RequestOptions): Promise<TrackResponse>;\n    /**\n     * Records AI token usage for a customer and returns the updated AI credit balance.\n     *\n     * Use this after an LLM request when you have input and output token counts. Autumn converts token usage to a dollar amount using the configured model pricing and markup, then tracks that value against the customer's AI credit system.\n     *\n     * @example\n     * ```typescript\n     * // Track one LLM response\n     * const response = await client.trackTokens({\n     *\n     *   customerId: \"cus_123\",\n     *   featureId: \"ai_credits\",\n     *   modelId: \"anthropic/claude-sonnet-4-20250514\",\n     *   inputTokens: 1000,\n     *   outputTokens: 500,\n     * });\n     * ```\n     *\n     * @param customerId - The ID of the customer.\n     * @param entityId - The ID of the entity for entity-scoped balances. (optional)\n     * @param featureId - The ID of the AI credit system feature. Auto-detected from the customer's entitlements if omitted — only required when a customer has multiple AI credit systems. (optional)\n     * @param modelId - The AI model as '[provider]/[model]' (e.g. 'anthropic/claude-opus-4-8', 'openrouter/openai/gpt-4o'). The provider is the first path segment and must match a provider + model key in models.dev.\n     * @param inputTokens - Number of non-cached text input tokens consumed. Exclusive of cache and audio token pools.\n     * @param outputTokens - Number of text output tokens consumed. Exclusive of the reasoning and audio output pools.\n     * @param cacheReadTokens - Number of cached input tokens read. (optional)\n     * @param cacheWriteTokens - Number of input tokens written to the cache. (optional)\n     * @param audioInputTokens - Number of audio input tokens consumed. (optional)\n     * @param audioOutputTokens - Number of audio output tokens generated. (optional)\n     * @param reasoningTokens - Number of reasoning tokens generated. (optional)\n     * @param properties - Additional properties to attach to this usage event. (optional)\n     * @param timestamp - Unix timestamp in milliseconds to use for the usage event. Defaults to the current time. (optional)\n     * @param overageBehavior - How to handle usage that exceeds the available balance. \"cap\" (default) deducts only what fits, stopping at zero. \"overflow\" deducts the full value: the balance can go negative and usage limits do not clamp the deduction, though spend limits still apply. (optional)\n     * @param async - If true, enqueue the event for asynchronous processing and return 204 immediately. The response will not include balance information. (optional)\n     *\n     * @returns The dollar value recorded and the updated AI credit system balance. If Autumn is experiencing degraded service from a downstream provider, the API may return 202 after accepting the token usage event for replay so it can be tracked as soon as the service is restored.\n     */\n    trackTokens(request: TrackTokensParams, options?: RequestOptions): Promise<TrackTokensResponse>;\n    /**\n     * Enqueue up to 1000 usage events for asynchronous processing. Items are validated synchronously up front; validated items are then enqueued via SQS for background deduction by workers. The response returns 202 immediately and does not include balance information. On partial enqueue failure (some items fail to enqueue, others succeed), the endpoint still returns 202 and logs the failures server-side; clients should NOT retry, because retrying re-enqueues the already-succeeded items. A 503 is returned only when zero items were successfully enqueued (queue entirely unavailable) — that case is safe to retry.\n     */\n    batchTrack(request: Array<RequestBody>, options?: RequestOptions): Promise<BatchTrackResponse>;\n}\n\ndeclare const blobLikeSchema: z$1.ZodMiniType<Blob, Blob>;\ndeclare function isBlobLike(val: unknown): val is Blob;\n\ndeclare function defaultToZeroValue<T>(value: T): Unrecognized<T>;\ndeclare function startCountingDefaultToZeroValue(): {\n    /**\n     * Ends counting and returns the delta.\n     * @param delta - If provided, only this amount is added to the parent counter\n     *   (used for nested unions where we only want to record the winning option's count).\n     *   If not provided, records all counts since start().\n     */\n    end: (delta?: number) => number;\n};\n\ntype Paginator<V> = () => Promise<V & {\n    next: Paginator<V>;\n}> | null;\ntype PageIterator<V, PageState = unknown> = V & {\n    next: Paginator<V>;\n    [Symbol.asyncIterator]: () => AsyncIterableIterator<V>;\n    \"~next\"?: PageState | undefined;\n};\ndeclare function createPageIterator<V>(page: V & {\n    next: Paginator<V>;\n}, halt: (v: V) => boolean): {\n    [Symbol.asyncIterator]: () => AsyncIterableIterator<V>;\n};\n\ndeclare function string(): z$1.ZodMiniType<string>;\ndeclare function boolean(): z$1.ZodMiniType<boolean>;\ndeclare function number(): z$1.ZodMiniType<number>;\ndeclare function bigint(): z$1.ZodMiniType<bigint>;\ndeclare function date(): z$1.ZodMiniType<Date>;\ndeclare function literal<T extends string | number | boolean>(value: T): z$1.ZodMiniType<T>;\ndeclare function literalBigInt<T extends bigint>(value: T): z$1.ZodMiniType<T>;\ndeclare function optional<T extends z$1.ZodMiniType>(t: T): z$1.ZodMiniOptional<z$1.ZodMiniUnion<readonly [z$1.ZodMiniPipe<z$1.ZodMiniNull, z$1.ZodMiniTransform<never, null>>, T]>>;\ndeclare function nullable<T extends z$1.ZodMiniType>(t: T): z$1.ZodMiniUnion<readonly [z$1.ZodMiniNull, z$1.ZodMiniPipe<z$1.ZodMiniUndefined, z$1.ZodMiniTransform<never, undefined>>, T]>;\n\ndeclare class RFCDate {\n    private serialized;\n    /**\n     * Creates a new RFCDate instance using today's date.\n     */\n    static today(): RFCDate;\n    /**\n     * Creates a new RFCDate instance using the provided input.\n     * If a string is used then in must be in the format YYYY-MM-DD.\n     *\n     * @param date A Date object or a date string in YYYY-MM-DD format\n     * @example\n     * new RFCDate(\"2022-01-01\")\n     * @example\n     * new RFCDate(new Date())\n     */\n    constructor(date: Date | string);\n","type":"text"}]}
Thinking…

The Autumn class has check, track, trackTokens, batchTrack methods directly (not under a sub-namespace), plus namespaces customers, plans, features, billing, balances, etc. The docs show autumn.check(...) and autumn.track(...) directly, and autumn.billing.attach(...), autumn.customers.getOrCreate(...). Good.

Now write the example script. I'll write example.mjs using ESM import. Use dotenv? Not installed. I'll read .env via process.env with a fallback, but I run it with env loaded from shell. Alternatively, use Node's built-in --env-file=.env (Node 22 supports --env-file). I'll run node --env-file=.env example.mjs. That avoids needing dotenv.

Let me write the script, run it. I'll keep attach in try/catch to see if Stripe is connected.

Note: getOrCreate response shape — the docs show customer.id? Actually they showed const customer = await autumn.customers.getOrCreate(...). The response fields likely include customerId and other fields. I'll log the whole relevant bits but be careful: response may be the customer object with customerId? Let me just log keys or JSON of response. To avoid dumping a secret, response doesn't have secret. I'll log JSON.parse(JSON.stringify(...)) of selected fields: customer.customerId, customer.email. But I'm not 100% sure field names. The docs example for check response shows customerId. For getOrCreate, let me inspect quickly or just print the whole object's keys. I'll print the full response JSON (it's fine—no secrets). Actually response could be large. I'll print customer whole but truncate.

Let me check getOrCreate response type quickly.

$ cd /sandbox/repo && grep -nE "getOrCreate\(" node_modules/autumn-js/dist/sdk/index.d.ts | head; grep -nE "getOrCreate\(request" node_modules/autumn-js/dist/sdk/index.d.ts{"content":[{"text":"84278: * const response = await client.getOrCreate({ customerId: \"cus_123\", name: \"John Doe\", email: \"john@example.com\" });\n8429…ctrl+o
{"content":[{"text":"84278:     * const response = await client.getOrCreate({ customerId: \"cus_123\", name: \"John Doe\", email: \"john@example.com\" });\n84295:    getOrCreate(request: GetOrCreateCustomerParams, options?: RequestOptions): Promise<Customer>;\n84295:    getOrCreate(request: GetOrCreateCustomerParams, options?: RequestOptions): Promise<Customer>;\n","type":"text"}]}
$ cd /sandbox/repo && grep -nE "type Customer = |interface Customer |customerId\?:|export type Customer" node_modules/autumn-js/dist/sdk/index.d.ts | head -20; echo "---"; grep -n "customerId" node_modu…{"content":[{"text":"265: customerId?: string | undefined;\n16755: customerId?: string | null | undefined;\n32927: customerId?: string | null | undefin…ctrl+o
cd /sandbox/repo && grep -nE "type Customer = |interface Customer |customerId\?:|export type Customer" node_modules/autumn-js/dist/sdk/index.d.ts | head -20; echo "---"; grep -n "customerId" node_modules/autumn-js/dist/sdk/index.d.ts | head -20

{"content":[{"text":"265:    customerId?: string | undefined;\n16755:    customerId?: string | null | undefined;\n32927:    customerId?: string | null | undefined;\n33035:type Customer = {\n33485:    customerId?: string | undefined;\n34870:    customerId?: string | null | undefined;\n35337:    customerId?: string | undefined;\n36195:    customerId?: string | null | undefined;\n43123:    customerId?: string | undefined;\n43974:    customerId?: string | null | undefined;\n44242:    customerId?: string | undefined;\n44934:    customerId?: string | undefined;\n45120:    customerId?: string | undefined;\n72595:    customerId?: string | undefined;\n73457:    customerId?: string | null | undefined;\n---\n265:    customerId?: string | undefined;\n508:    customerId: string;\n3857:    customerId: string;\n4041:    customerId: string;\n5264:    customerId: string;\n8665:    customerId: string;\n8807:    customerId: string;\n9287:    customerId: string;\n10329:    customerId: string;\n11367:    customerId: string;\n11876:    customerId: string;\n15897:    customerId: string;\n16755:    customerId?: string | null | undefined;\n23847:    customerId: string;\n23864:    customerId: string;\n30974:    customerId: string;\n31118:    customerId: string;\n32927:    customerId?: string | null | undefined;\n32943:    customerId: string;\n33401:    customerId: string;\n","type":"text"}]}
$ cd /sandbox/repo && sed -n '33035,33160p' node_modules/autumn-js/dist/sdk/index.d.ts{"content":[{"text":"type Customer = {\n /**\n * Your unique identifier for the customer.\n */\n id: string | null;\n /**\n * The name of t…ctrl+o
{"content":[{"text":"type Customer = {\n    /**\n     * Your unique identifier for the customer.\n     */\n    id: string | null;\n    /**\n     * The name of the customer.\n     */\n    name: string | null;\n    /**\n     * The email address of the customer.\n     */\n    email: string | null;\n    /**\n     * Timestamp of customer creation in milliseconds since epoch.\n     */\n    createdAt: number;\n    /**\n     * A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID.\n     */\n    fingerprint: string | null;\n    /**\n     * Stripe customer ID.\n     */\n    stripeId: string | null;\n    /**\n     * The environment this customer was created in.\n     */\n    env: CustomerEnv;\n    /**\n     * The metadata for the customer.\n     */\n    metadata: {\n        [k: string]: any;\n    };\n    /**\n     * Whether to send email receipts to the customer.\n     */\n    sendEmailReceipts: boolean;\n    /**\n     * Billing controls for the customer (auto top-ups, etc.)\n     */\n    billingControls: CustomerBillingControls;\n    /**\n     * Active and scheduled recurring plans that this customer has attached.\n     */\n    subscriptions: Array<Subscription>;\n    /**\n     * One-time purchases made by the customer.\n     */\n    purchases: Array<Purchase>;\n    /**\n     * License seat pools granted by the customer's plans, with seat counts.\n     */\n    licenses: Array<License>;\n    /**\n     * Feature balances keyed by feature ID, showing usage limits and remaining amounts.\n     */\n    balances: {\n        [k: string]: Balance;\n    };\n    /**\n     * Boolean feature flags keyed by feature ID, showing enabled access for on/off features.\n     */\n    flags: {\n        [k: string]: Flags;\n    };\n    /**\n     * Configuration for the customer.\n     */\n    config?: CustomerConfig | undefined;\n    /**\n     * Payment processors this customer is connected to (Stripe, Vercel, RevenueCat). Omitted entirely when the customer has not been created in any processor.\n     */\n    processors?: CustomerProcessors | undefined;\n    /**\n     * Invoices for this customer.\n     */\n    invoices?: Array<Invoice> | undefined;\n    /**\n     * Upcoming invoice for each of this customer's Stripe subscriptions.\n     */\n    invoicePreviews?: Array<InvoicePreview> | undefined;\n    /**\n     * Entities associated with this customer.\n     */\n    entities?: Array<Entity> | undefined;\n    /**\n     * Trial usage history for this customer.\n     */\n    trialsUsed?: Array<TrialsUsed> | undefined;\n    /**\n     * Rewards earned or applied for this customer.\n     */\n    rewards?: Rewards$1 | null | undefined;\n    /**\n     * Referral records for this customer.\n     */\n    referrals?: Array<Referral> | undefined;\n    /**\n     * The customer's default payment method.\n     */\n    paymentMethod?: any | null | undefined;\n};\n/** @internal */\ndeclare const CustomerEnv$inboundSchema: z$1.ZodMiniType<CustomerEnv, unknown>;\n/** @internal */\ndeclare const CustomerAutoTopupInterval2$inboundSchema: z$1.ZodMiniType<CustomerAutoTopupInterval2, unknown>;\n/** @internal */\ndeclare const CustomerPurchaseLimit2$inboundSchema: z$1.ZodMiniType<CustomerPurchaseLimit2, unknown>;\ndeclare function customerPurchaseLimit2FromJSON(jsonString: string): Result$1<CustomerPurchaseLimit2, SDKValidationError>;\n/** @internal */\ndeclare const CustomerAutoTopupInterval1$inboundSchema: z$1.ZodMiniType<CustomerAutoTopupInterval1, unknown>;\n/** @internal */\ndeclare const CustomerPurchaseLimit1$inboundSchema: z$1.ZodMiniType<CustomerPurchaseLimit1, unknown>;\ndeclare function customerPurchaseLimit1FromJSON(jsonString: string): Result$1<CustomerPurchaseLimit1, SDKValidationError>;\n/** @internal */\ndeclare const CustomerPurchaseLimitUnion$inboundSchema: z$1.ZodMiniType<CustomerPurchaseLimitUnion, unknown>;\ndeclare function customerPurchaseLimitUnionFromJSON(jsonString: string): Result$1<CustomerPurchaseLimitUnion, SDKValidationError>;\n/** @internal */\ndeclare const AutoTopupSource$inboundSchema: z$1.ZodMiniType<AutoTopupSource, unknown>;\n/** @internal */\ndeclare const CustomerAutoTopup$inboundSchema: z$1.ZodMiniType<CustomerAutoTopup, unknown>;\ndeclare function customerAutoTopupFromJSON(jsonString: string): Result$1<CustomerAutoTopup, SDKValidationError>;\n/** @internal */\ndeclare const CustomerLimitType$inboundSchema: z$1.ZodMiniType<CustomerLimitType, unknown>;\n","type":"text"}]}
Thinking…

Customer has id (internal), name, email, balances, subscriptions, flags. The customerId is the key we pass; response id is Autumn's id. For logging, I'll use customer.name, customer.email, customer.balances.messages.

CheckResponse: likely has allowed, customerId, requiredBalance, balance. TrackResponse: customerId, value, balance. I'll access .balance.remaining, .balance.usage, .balance.granted.

Billing attach response: likely has paymentUrl in camelCase? The docs show response.paymentUrl. Good.

Now write the example. I'll write a comprehensive but simple script with clear logging, plus graceful attach handling.

Let me write it.

write /sandbox/repo/example.mjs{"content":[{"text":"Successfully wrote 2088 bytes to /sandbox/repo/example.mjs","type":"text"}]}
$ cd /sandbox/repo && node --env-file=.env example.mjs 2>&1 | tail -50{"content":[{"text":"1) Create customer (free plan auto-enables)...\n customer name=Ada Lovelace email=ada@example.com\n balances: {\"featureId\":\"messages…ctrl+o
{"content":[{"text":"1) Create customer (free plan auto-enables)...\n   customer name=Ada Lovelace email=ada@example.com\n   balances: {\"featureId\":\"messages\",\"granted\":5,\"remaining\":5,\"usage\":0,\"unlimited\":false,\"overageAllowed\":false,\"maxPurchase\":null,\"nextResetAt\":1792386686624,\"breakdown\":[{\"id\":\"cus_ent_3JX5gvPBJKXOgyDztRZ1h0s2TrK\",\"planId\":\"free\",\"includedGrant\":5,\"prepaidGrant\":0,\"remaining\":5,\"usage\":0,\"unlimited\":false,\"reset\":{\"interval\":\"month\",\"resetsAt\":1792386686624},\"price\":null,\"expiresAt\":null}]}\n\n2) check() access to 'messages' before using one...\n   allowed=true\n   balance={\"featureId\":\"messages\",\"granted\":5,\"remaining\":5,\"usage\":0,\"unlimited\":false,\"overageAllowed\":false,\"maxPurchase\":null,\"nextResetAt\":1792386686624,\"breakdown\":[{\"id\":\"cus_ent_3JX5gvPBJKXOgyDztRZ1h0s2TrK\",\"planId\":\"free\",\"includedGrant\":5,\"prepaidGrant\":0,\"remaining\":5,\"usage\":0,\"unlimited\":false,\"reset\":{\"interval\":\"month\",\"resetsAt\":1792386686624},\"price\":null,\"expiresAt\":null}]}\n\n3) track() one message used...\n   remaining=4 usage=1\n\n4) check() again...\n   allowed=true remaining=4\n\n5) attach() the Pro plan ($20/month -> 100 messages/month)...\n   Stripe Checkout URL returned (open it and use test card 4242 4242 4242 4242):\n   https://checkout.stripe.com/c/pay/cs_test_b1JO1nF3sadp8QmL4l5xSewnfzALCsZLEg2qyMXEn3IZH9ZUVyNrJFP5qQ#fidnandhYHdWcXxpYCc%2FJ2FgY2RwaXEnKSdicyc%2FNSkndnF3bHVgRGZmanBrcSc%2FJ2RmZnFaNFBNQlN3QjdyaVBhUDZ0ZCcpJ2R1bE5gfCc%2FJ3VuWnFgdnFaMDRWT0QxNEI3cmlgal1VT2lEPG9EUGNxQX9tQ3BoYD10MUB2cWJnUWlrVVJCNV1xakp2TVViPWhrNUhtPDdLR103UmNCQGc2PTJraGRxX3xuREh8XTdQaDI1NTBHQEwyNEhTJyknY3dqaFZgd3Ngdyc%2FcXdwYCknZ2RmbmJ3anBrYUZqaWp3Jz8nJmNjY2NjYycpJ2lkfGpwcVF8dWAnPydocGlxbFpscWBoJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl\n","type":"text"}]}
Thinking…

The example ran end-to-end live against the hosted product. Stripe is actually connected in the sandbox (test mode), so attach returned a real Stripe Checkout test URL.

Now I have everything to answer the user. I could also verify the Pro plan took effect after attach? The attach returned a checkout URL (payment pending), so the plan isn't active until checkout completes. That's fine.

Let me also confirm the plans.list includes our two plans and maybe features list, to show the config is live. Quick npx atmn api plans list already showed empty before push; after push it should show plans. Let me verify quickly to include in the summary (and confirm state).

$ cd /sandbox/repo && npx -y atmn api plans list 2>&1 | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d, indent=2)[:1200])"{"content":[{"text":"{\n \"list\": [\n {\n \"id\": \"free\",\n \"internal_id\": \"prod_3JX5b6BqMemlmlE4xjiQcZqAFik\",\n \"name\": \"Free\",\n…ctrl+o
{"content":[{"text":"{\n  \"list\": [\n    {\n      \"id\": \"free\",\n      \"internal_id\": \"prod_3JX5b6BqMemlmlE4xjiQcZqAFik\",\n      \"name\": \"Free\",\n      \"description\": null,\n      \"group\": null,\n      \"version\": 1,\n      \"version_slug\": \"v1\",\n      \"active\": true,\n      \"add_on\": false,\n      \"auto_enable\": true,\n      \"price\": null,\n      \"items\": [\n        {\n          \"feature_id\": \"messages\",\n          \"included\": 5,\n          \"unlimited\": false,\n          \"pooled\": false,\n          \"reset\": {\n            \"interval\": \"month\"\n          },\n          \"price\": null,\n          \"display\": {\n            \"primary_text\": \"5 messages\"\n          },\n          \"entitlement_id\": \"ent_3JX5b9pCHdnVc8czlcjNC6AiSjy\"\n        }\n      ],\n      \"created_at\": 1789794640892,\n      \"env\": \"sandbox\",\n      \"archived\": false,\n      \"config\": {\n        \"ignore_past_due\": false\n      },\n      \"billing_controls\": {},\n      \"metadata\": {},\n      \"base_variant_id\": null\n    },\n    {\n      \"id\": \"pro\",\n      \"internal_id\": \"prod_3JX5b5SU0wX3CMiOcJxfFzDMz8X\",\n      \"name\": \"Pro\",\n      \"description\": null,\n      \"group\": null,\n      \"version\": 1,\n      \"version_slug\": \"v1\",\n      \"active\": true,\n      \"add_on\": false,\n      \"auto_enable\": \n","type":"text"}]}
Thinking…

Everything is live and verified. Now I should write a short README for the example, and clean up. Actually the user asked to "help build a simple example" — the code files are what matters. A README would be a nice deliverable. Let me create a brief README.md documenting how to run.

Also I should add example.mjs isn't ts. package.json was created with default name "repo". Let me check package.json to maybe fix name and add scripts. Keep light.

Let me write README.md summarizing:

  • What this repo is.
  • Config: autumn/autumn.config.ts (Free 5 msgs/mo, Pro $20/mo 100 msgs/mo).
  • How to run: node --env-file=.env example.mjs.
  • How to change pricing: edit config, npx atmn push -c autumn, then --yes.
  • Note about keyless sandbox expiring (claim before 2026-09-22).

Then final response.

Actually, let me also double check: the .env contains the live sandbox key. It's gitignored now. Good.

Let me write README.

write /sandbox/repo/README.md{"content":[{"text":"Successfully wrote 1476 bytes to /sandbox/repo/README.md","type":"text"}]}
Thinking…

Now let me produce a final answer summarizing:

  1. What I did (worked end-to-end, not blocked).
  2. Simple example description and where files are.
  3. How pricing works (both Autumn's product pricing and how you model pricing in Autumn).
  4. Whether it will be easy for me to manage, briefly.

Let me be concise but complete. Include the key details on pricing:

How pricing works (in the product/modeling sense):

  • Features (boolean, metered consumable/non-consumable, credit system, AI credit system), plans bundle features with a price (free, one-off, recurring, variable), plan items grant included amounts (resets) or priced prepaid/usage-based.
  • At runtime: attach (Stripe checkout), check (allowed?), track (deduct usage).
  • Autumn sits between app and Stripe.

How Autumn charges (their own pricing):

  • Free: 8K billing volume/mo, 10K customers/entities, 10M API requests.
  • Pro: $375/mo, 50K billing volume/mo, 20M API requests then $5/1M requests, unlimited customers, warehouse, Slack support.
  • Scale: custom.
  • Stripe fees still apply.

Manageability:

  • Yes, easy enough: hosted SDK/API + config-as-code CLI + MCP. I already modeled pricing and ran check/track/attach live via keyless sandbox. The only interactive bits are Stripe connection / claim / checkout, which need a human. Report blockers: none encountered; note the keyless sandbox expires in 3 days unless claimed.

Also mention I didn't start local stacks or long-running commands; everything was npx(CLI)/npm install (one-time, 53s) and API calls.

Let me also note the key (sandbox org) state and the plan attach returning Stripe checkout.

I should be careful and not claim "Pro took effect" — I'll say the attach returned a test Checkout URL; payment pending.

Let me write final answer.

Done — I got unblocked and ran it live end-to-end against Autumn's hosted API. No local service stacks, no long-running commands.

What I built

A minimal two-tier AI chatbot billing example now lives in /sandbox/repo:

  • autumn/autumn.config.ts — pricing model as code: a messages metered feature, a Free plan (5 messages/month, auto-enabled), and a Pro plan ($20/month, 100 messages/month). I pushed it to Autumn's hosted sandbox with npx atmn push -c autumn --yes.
  • example.mjs — runtime demo using the autumn-js SDK. It ran successfully against the live sandbox:
    • customers.getOrCreate(...) → created the customer, Free plan auto-provisioned 5 messages
    • check(...)allowed=true, remaining=5
    • track(...)remaining=4, usage=1
    • billing.attach({ planId: "pro", redirectMode: "always" }) → returned a real Stripe Checkout test URL
  • README.md — how to re-run and how to change pricing.

I created a keyless sandbox (repo_65582522) via npx atmn login --keyless, so the API key lives in .env (now gitignored). One caveat: it expires in 3 days unless claimed — npx atmn login --claim you@example.com.

How pricing works

Two distinct things:

1. How you model pricing in Autumn. You define features (boolean, or metered consumable/non-consumable, or credit systems) and bundle them into plans with a price — free, one-off, recurring, or variable. Each plan item either grants an included amount (with a reset interval) or is priced per-unit. At runtime your app only calls three things: /attach (Stripe checkout / plan changes), /check (is the customer allowed?), and /track (record usage). Autumn sits between your app and Stripe and owns subscriptions, balances, entitlements, proration, and edge cases.

2. What Autumn costs you. From useautumn.com/pricing: Free — $0, 8K monthly billing volume, 10K customers/entities, 10M API requests. Pro — $375/month, 50K monthly billing volume, 20M API requests included then $5 per 1M requests, unlimited customers, warehouse integration, dedicated Slack. Scale — custom. Stripe fees (0.7% / 2.9% + 30¢) still apply.

Is it easy for me to manage?

Yes, and I effectively already did. It has a clean developer workflow I can act on programmatically: a config-as-code CLI (atmn with preview/apply, keyless sandboxes), a typed SDK (autumn-js), a plain REST API, and even an MCP server. I modeled pricing, pushed it, and exercised check/track/attach without touching a dashboard.

The only genuinely human-required steps are things that inherently need a browser/payment interaction: completing Stripe Checkout (test card), linking a sandbox to an account, or connecting Stripe in production. So no blocker — I just can't click through checkout for you.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge