Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
175cfb0
feat: add usage alerts schema and database support
og2701 Mar 19, 2026
3a8c13a
feat: include database migration files
og2701 Mar 19, 2026
870665b
Remove gitignored drizzle migration files from tracking
og2701 Mar 19, 2026
aba7df7
feat: add percentage-based usage alerts
og2701 Mar 19, 2026
4ca1bf7
switch to threshold_type and enum validation
og2701 Mar 19, 2026
7eb24eb
add upper bound % check
og2701 Mar 19, 2026
28baddc
define threshold_reached webhook schema
og2701 Mar 19, 2026
9a547ee
remove balance from webhook payload
og2701 Mar 19, 2026
a5d4cf3
add check for usage alert
og2701 Mar 19, 2026
bf1b332
remove_current_usage
og2701 Mar 19, 2026
538e5a9
implement usage-alert detection and emission logic
og2701 Mar 19, 2026
7de45d6
use oldGrantedBalance and newGrantedBalance
og2701 Mar 19, 2026
9973aa0
prepaid fix
og2701 Mar 19, 2026
023a1c6
use new usage alert webhook
og2701 Mar 19, 2026
ec21241
add unit tests
og2701 Mar 19, 2026
aad8644
address comments
og2701 Mar 19, 2026
9e3a653
fix: is free product
johnyeocx Mar 21, 2026
abbb14d
docs: fix auto top-up dashboard instructions and remove duplicate set…
ay-rod Mar 21, 2026
6cb375e
Merge pull request #1046 from useautumn/docs/fix-auto-topup-dashboard
ay-rod Mar 21, 2026
ac71195
Merge pull request #1047 from useautumn/docs/fix-auto-topup-dashboard
ay-rod Mar 21, 2026
5368e38
fix: invalidate product list cache on plan create, save, and version …
ay-rod Mar 21, 2026
2f2520a
feat: add env+org aware query keys to eliminate stale cache on switch
ay-rod Mar 21, 2026
80f57b9
feat: add static env pill for non-deployed orgs and fix env dropdown …
ay-rod Mar 22, 2026
7b87e49
fix: prevent false sandbox redirect when switching to deployed org
ay-rod Mar 22, 2026
63dff8e
Merge pull request #1048 from useautumn/fix/env-org-switch-redirect
ay-rod Mar 22, 2026
d2f135b
fix: migrate all SWR queries to React Query to fix stale cache on org…
ay-rod Mar 22, 2026
fad914a
Merge pull request #1050 from useautumn/fix/remove-swr
ay-rod Mar 22, 2026
812c6e9
initialised artillery / memory leak testing script
johnyeocx Mar 22, 2026
570a17b
Merge pull request #1045 from useautumn/fix/is-free-product
johnyeocx Mar 22, 2026
0e3befd
fix: enpty price init
johnyeocx Mar 22, 2026
a119160
Merge pull request #1052 from useautumn/fix/empty-price-init
johnyeocx Mar 22, 2026
8c92997
fix: legacy checkout prepaid
johnyeocx Mar 23, 2026
1734eda
fix: 🐛 an issue with @inkjs/ui bundling the wrong react version
SirTenzin Mar 23, 2026
50d6226
Merge pull request #1053 from useautumn/fix/legacy-checkout-prepaid
johnyeocx Mar 23, 2026
19f9778
fix: 🐛 sync pkg version for atmn
SirTenzin Mar 23, 2026
d96726f
commented in stripe client cache
johnyeocx Mar 23, 2026
f30f0db
Merge pull request #1054 from useautumn/fix/atmn/init-useReducer
SirTenzin Mar 23, 2026
43421d0
feat: 🎸 remove debug logs from atmn
SirTenzin Mar 23, 2026
6e4154a
fix: minor issues with stripe client caching
johnyeocx Mar 23, 2026
60538ed
fix: test utilities
johnyeocx Mar 23, 2026
763e695
Merge pull request #1051 from useautumn/chore/infra-cleanup
johnyeocx Mar 23, 2026
35ea25f
Merge branch 'main' into dev
johnyeocx Mar 23, 2026
c684641
fix: bun.lock
johnyeocx Mar 23, 2026
01c9177
Merge pull request #1055 from useautumn/dev
johnyeocx Mar 23, 2026
c811ca8
fix: remove block against lifetime prepaid + monthly overage
johnyeocx Mar 23, 2026
70020ef
Merge pull request #1056 from useautumn/fix/prepaid-overage-block
johnyeocx Mar 23, 2026
5877db5
chore: rename webStandard to fetch
SirTenzin Mar 23, 2026
d3d5a2e
Merge branch 'dev' into feature/usage-alerts-existing-threshold-migra…
johnyeocx Mar 23, 2026
94d20c5
fix: checkout one off
johnyeocx Mar 23, 2026
dfb4984
Merge pull request #1057 from useautumn/fix/checkout-oneoff
johnyeocx Mar 23, 2026
39af9f0
Merge pull request #1058 from useautumn/rename-fetch-export-docs
SirTenzin Mar 23, 2026
416a633
update: cleaned up balance webhooks
johnyeocx Mar 23, 2026
6493d1b
Merge pull request #1061 from useautumn/feature/usage-alerts-existing…
johnyeocx Mar 23, 2026
a7a2ad9
updated docs with usage alert guides
johnyeocx Mar 23, 2026
ee50aca
Merge pull request #1062 from useautumn/dev
johnyeocx Mar 23, 2026
c8f7ae7
chore: added preview attach params
johnyeocx Mar 23, 2026
e830f36
Merge pull request #1063 from useautumn/dev
johnyeocx Mar 23, 2026
b6a92db
Merge branch 'main' into dev
johnyeocx Mar 23, 2026
065868a
Merge branch 'main' into dev
johnyeocx Mar 23, 2026
0dde2b3
fix: reward indexes
johnyeocx Mar 23, 2026
870d54f
Merge pull request #1064 from useautumn/fix/reward-indexes
johnyeocx Mar 23, 2026
3698373
chore: index experiments
johnyeocx Mar 23, 2026
228560c
Merge pull request #1065 from useautumn/chore/index-experiments
johnyeocx Mar 23, 2026
ad6249a
fix: change acquireLock error code to be 423 Locked instead of 429 To…
SirTenzin Mar 24, 2026
fd9c7cc
Merge pull request #1067 from useautumn/lock-status-423
SirTenzin Mar 24, 2026
1eea322
M
johnyeocx Mar 24, 2026
d4ca583
updated package.json for autumn-js
johnyeocx Mar 24, 2026
9d48a38
fix: usage alert credit systems
johnyeocx Mar 24, 2026
31347ce
M (#1068)
johnyeocx Mar 24, 2026
f12f21a
fix: use entitlement index for json path
johnyeocx Mar 24, 2026
011e08f
fix: has path idx bug in spendLimitUtils.lua
johnyeocx Mar 24, 2026
44bac03
fix: use entitlement index for json path (#1069)
johnyeocx Mar 24, 2026
20a3e73
Merge pull request #1071 from useautumn/dev
johnyeocx Mar 24, 2026
5e68234
fix: 🐛 test broken
SirTenzin Mar 24, 2026
5210fbd
Merge pull request #1070 from useautumn/fix/usage-alerts-credit-system
SirTenzin Mar 24, 2026
e8bd602
Merge pull request #1072 from useautumn/dev
SirTenzin Mar 24, 2026
0fde605
fix: batch delete customers
johnyeocx Mar 24, 2026
857df63
Merge pull request #1079 from useautumn/fix/batch-delete-customers
johnyeocx Mar 24, 2026
d14a159
chore: serve OpenAPI spec at /openapi.yml and /openapi.json
jjmaxwell4 Mar 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
35 changes: 33 additions & 2 deletions .claude/rules/sdk.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ alwaysApply: true

Zod Schemas → ORPC Contracts → OpenAPI Spec → Speakeasy SDKs → autumn-js Wrapper → React Hooks

Webhook Zod Schemas → Webhook Registry → OpenAPI Spec (injected) + Svix Event Types

Run `bun api` from root to execute the full pipeline.

---
Expand Down Expand Up @@ -152,15 +154,40 @@ When writing documentation examples for React hooks or the TypeScript SDK, alway

---

## 6. Testing (sdk-test)
## 6. Webhook Pipeline

**Registry:** `shared/api/webhooks/webhookRegistry.ts`

Each webhook is defined as a `WebhookDefinition` with `eventType`, `operationId`, `title`, `schema` (Zod), `description`, and `group`. Schemas live in `shared/api/webhooks/`.

### OpenAPI injection

`packages/openapi/v2.1/webhooks/injectWebhooks.ts` reads the registry and injects `webhooks` entries into the generated OpenAPI document. Only definitions with a Zod schema are included.

### Svix sync

`packages/openapi/scripts/svixPush.ts` pushes event types to Svix (create or update). It does **not** delete event types missing from the registry.

### Adding a new webhook event

1. **Create schema** in `shared/api/webhooks/` (Zod schema with `.meta()` descriptions)
2. **Add to registry** in `shared/api/webhooks/webhookRegistry.ts`
3. **Add to `WebhookEventType`** enum in `shared/api/webhooks/webhookEventType.ts`
4. **Re-export** from `shared/api/webhooks/index.ts`
5. **Regenerate** via `bun api` (webhooks are injected into the OpenAPI spec automatically)
6. **Push to Svix** via `bun run --cwd packages/openapi scripts/svixPush.ts`

---

## 7. Testing (sdk-test)

**Location:** `apps/sdk-test/`

Scenario pages organized by provider: `scenarios/core/`, `scenarios/better-auth/`, `scenarios/convex/`.

---

## Adding a New Route
## Adding a New API Route

1. **Add contract** in `packages/openapi/v2.1/contracts/`
2. **Add to router** in `packages/openapi/v2.1/contracts/index.ts`
Expand All @@ -184,3 +211,7 @@ Scenario pages organized by provider: `scenarios/core/`, `scenarios/better-auth/
| React client | `packages/autumn-js/src/react/client/AutumnClient.ts` |
| React hooks | `packages/autumn-js/src/react/hooks/` |
| SDK tests | `apps/sdk-test/` |
| Webhook schemas | `shared/api/webhooks/` |
| Webhook registry | `shared/api/webhooks/webhookRegistry.ts` |
| Webhook OpenAPI injection | `packages/openapi/v2.1/webhooks/injectWebhooks.ts` |
| Svix push script | `packages/openapi/scripts/svixPush.ts` |
55 changes: 19 additions & 36 deletions apps/docs/mintlify/api-reference/billing/attach.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ This is useful for attaching custom metadata to the Stripe subscription created
### Body Parameters

<DynamicParamField body="customer_id" type="string" required>
The ID of the customer to attach the plan to.
The ID of the customer to attach the plan to.
</DynamicParamField>

<DynamicParamField body="entity_id" type="string">
The ID of the entity to attach the plan to.
The ID of the entity to attach the plan to.
</DynamicParamField>

<DynamicParamField body="plan_id" type="string" required>
The ID of the plan.
The ID of the plan.
</DynamicParamField>

<DynamicParamField body="feature_quantities" type="object[]">
Expand All @@ -107,7 +107,7 @@ This is useful for attaching custom metadata to the Stripe subscription created
</DynamicParamField>

<DynamicParamField body="version" type="number">
The version of the plan to attach.
The version of the plan to attach.
</DynamicParamField>

<DynamicParamField body="customize" type="object">
Expand Down Expand Up @@ -278,28 +278,16 @@ This is useful for attaching custom metadata to the Stripe subscription created
</Expandable>
</DynamicParamField>

<DynamicParamField
body="proration_behavior"
type="'prorate_immediately' | 'none'"
>
How to handle proration when updating an existing subscription.
'prorate_immediately' charges/credits prorated amounts now, 'none' skips
creating any charges.
<DynamicParamField body="proration_behavior" type="'prorate_immediately' | 'none'">
How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.
</DynamicParamField>

<DynamicParamField
body="redirect_mode"
type="'always' | 'if_required' | 'never'"
>
Controls when to return a checkout URL. 'always' returns a URL even if
payment succeeds, 'if_required' only when payment action is needed, 'never'
disables redirects.
<DynamicParamField body="redirect_mode" type="'always' | 'if_required' | 'never'">
Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects.
</DynamicParamField>

<DynamicParamField body="subscription_id" type="string">
A unique ID to identify this subscription. Can be used to target specific
subscriptions in update operations when a customer has multiple products
with the same plan.
A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan.
</DynamicParamField>

<DynamicParamField body="discounts" type="object[]">
Expand All @@ -317,24 +305,19 @@ This is useful for attaching custom metadata to the Stripe subscription created
</DynamicParamField>

<DynamicParamField body="success_url" type="string">
URL to redirect to after successful checkout.
URL to redirect to after successful checkout.
</DynamicParamField>

<DynamicParamField body="new_billing_subscription" type="boolean">
Only applicable when the customer has an existing Stripe subscription. If
true, creates a new separate subscription instead of merging into the
existing one.
Only applicable when the customer has an existing Stripe subscription. If true, creates a new separate subscription instead of merging into the existing one.
</DynamicParamField>

<DynamicParamField body="plan_schedule" type="'immediate' | 'end_of_cycle'">
When the plan change should take effect. 'immediate' applies now,
'end_of_cycle' schedules for the end of the current billing cycle. By
default, upgrades are immediate and downgrades are scheduled.
When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled.
</DynamicParamField>

<DynamicParamField body="checkout_session_params" type="object">
Additional parameters to pass into the creation of the Stripe checkout
session.
Additional parameters to pass into the creation of the Stripe checkout session.
</DynamicParamField>

<DynamicParamField body="custom_line_items" type="object[]">
Expand All @@ -352,8 +335,7 @@ This is useful for attaching custom metadata to the Stripe subscription created
</DynamicParamField>

<DynamicParamField body="processor_subscription_id" type="string">
The processor subscription ID to link. Use this to attach an existing Stripe
subscription instead of creating a new one.
The processor subscription ID to link. Use this to attach an existing Stripe subscription instead of creating a new one.
</DynamicParamField>

<DynamicParamField body="carry_over_balances" type="object">
Expand Down Expand Up @@ -384,14 +366,15 @@ This is useful for attaching custom metadata to the Stripe subscription created
</Expandable>
</DynamicParamField>


### Response

<DynamicResponseField name="customer_id" type="string">
The ID of the customer.
The ID of the customer.
</DynamicResponseField>

<DynamicResponseField name="entity_id" type="string">
The ID of the entity, if the plan was attached to an entity.
The ID of the entity, if the plan was attached to an entity.
</DynamicResponseField>

<DynamicResponseField name="invoice" type="object">
Expand Down Expand Up @@ -421,8 +404,7 @@ This is useful for attaching custom metadata to the Stripe subscription created
</DynamicResponseField>

<DynamicResponseField name="payment_url" type="string | null">
URL to redirect the customer to complete payment. Null if no payment action
is required.
URL to redirect the customer to complete payment. Null if no payment action is required.
</DynamicResponseField>

<DynamicResponseField name="required_action" type="object">
Expand All @@ -439,6 +421,7 @@ This is useful for attaching custom metadata to the Stripe subscription created
</Expandable>
</DynamicResponseField>


<ResponseExample>
```json 200
{
Expand Down
10 changes: 10 additions & 0 deletions apps/docs/mintlify/api-reference/billing/billingUpdate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,16 @@ const response = await autumn.billing.update({
If true, the subscription is updated internally without applying billing changes in Stripe.
</DynamicParamField>

<DynamicParamField body="recalculate_balances" type="object">
Controls whether balances should be recalculated during the subscription update.
<Expandable title="properties">
<DynamicParamField body="enabled" type="boolean" required>
If true, recalculates balances during the subscription update. Only applicable when updating feature quantities.
</DynamicParamField>

</Expandable>
</DynamicParamField>


### Response

Expand Down
52 changes: 52 additions & 0 deletions apps/docs/mintlify/api-reference/billing/multiAttach.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx
</Expandable>
</DynamicParamField>

<DynamicParamField body="usage_alerts" type="object[]">
List of usage alert configurations per feature.
<Expandable title="properties">
<DynamicParamField body="feature_id" type="string">
The feature ID this alert applies to. If omitted, the alert applies globally.
</DynamicParamField>

<DynamicParamField body="enabled" type="boolean">
Whether this usage alert is enabled.
</DynamicParamField>

<DynamicParamField body="threshold" type="number" required>
The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).
</DynamicParamField>

<DynamicParamField body="threshold_type" type="'usage' | 'usage_percentage'" required>
Whether the threshold is an absolute usage count or a percentage of the usage allowance.
</DynamicParamField>

<DynamicParamField body="name" type="string">
Optional user-defined label to distinguish multiple alerts on the same feature.
</DynamicParamField>

</Expandable>
</DynamicParamField>

</Expandable>
</DynamicParamField>

Expand Down Expand Up @@ -384,6 +410,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx
</Expandable>
</DynamicParamField>

<DynamicParamField body="usage_alerts" type="object[]">
List of usage alert configurations per feature.
<Expandable title="properties">
<DynamicParamField body="feature_id" type="string">
The feature ID this alert applies to. If omitted, the alert applies globally.
</DynamicParamField>

<DynamicParamField body="enabled" type="boolean">
Whether this usage alert is enabled.
</DynamicParamField>

<DynamicParamField body="threshold" type="number" required>
The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).
</DynamicParamField>

<DynamicParamField body="threshold_type" type="'usage' | 'usage_percentage'" required>
Whether the threshold is an absolute usage count or a percentage of the usage allowance.
</DynamicParamField>

<DynamicParamField body="name" type="string">
Optional user-defined label to distinguish multiple alerts on the same feature.
</DynamicParamField>

</Expandable>
</DynamicParamField>

</Expandable>
</DynamicParamField>

Expand Down
25 changes: 24 additions & 1 deletion apps/docs/mintlify/api-reference/billing/previewAttach.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx
</DynamicResponseField>

<DynamicResponseField name="line_items" type="object[]">
List of line items for the current billing period.
<Expandable title="properties">
<DynamicResponseField name="display_name" type="string">
The name of the line item to display to the customer if you're building a UI. It will either be the plan name or the feature name.
Expand Down Expand Up @@ -796,6 +795,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx
When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.
</DynamicResponseField>

<DynamicResponseField name="canceled_at" type="number | null">
When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.
</DynamicResponseField>

<DynamicResponseField name="expires_at" type="number | null">
When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.
</DynamicResponseField>

</Expandable>
</DynamicResponseField>

Expand Down Expand Up @@ -1099,9 +1106,25 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx
When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.
</DynamicResponseField>

<DynamicResponseField name="canceled_at" type="number | null">
When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.
</DynamicResponseField>

<DynamicResponseField name="expires_at" type="number | null">
When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.
</DynamicResponseField>

</Expandable>
</DynamicResponseField>

<DynamicResponseField name="redirect_to_checkout" type="boolean">
Whether the customer will be redirected to a checkout page if attach is called.
</DynamicResponseField>

<DynamicResponseField name="checkout_type" type="'stripe_checkout' | 'autumn_checkout'">
The type of checkout that will be used if the customer is redirected to a checkout page.
</DynamicResponseField>


<ResponseExample>
```json 200
Expand Down
Loading
Loading