Files
cfw-autumn/apps/docs/mintlify/documentation/getting-started/display-billing.mdx
Ayush Rodrigues 73d3d23939 docs wip again
2026-03-11 11:35:01 +00:00

434 lines
9.8 KiB
Plaintext

---
title: "Display billing data"
description: "Display usage and billing data in your app for your users"
---
Software applications typically ship with a billing page. This allows customers to change plan, cancel subscription and view their usage.
The customer endpoint returns the current state of the customer, including their active subscriptions, one-time purchases, and feature balances.
### Active plans
Display the plan the user is currently on. Users can have multiple active subscriptions and purchases (e.g., main plan and add-ons).
- **`subscriptions`** - Free and paid recurring plans
- **`purchases`** - One-off plans (e.g., credit top-ups)
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
const { data: customer } = useCustomer();
const active = customer?.subscriptions.filter(
(sub) => sub.status === "active"
);
console.log(active?.map((sub) => sub.planId).join(", "));
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const customer = await autumn.customers.getOrCreate({
customerId: "user_123",
});
const active = customer.subscriptions?.filter(
(sub) => sub.status === "active"
);
console.log(active?.map((sub) => sub.planId).join(", "));
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
customer = await autumn.customers.get_or_create(
customer_id="user_123"
)
active = [s for s in customer.subscriptions if s.status == "active"]
print([s.plan_id for s in active])
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/customers' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{ "customer_id": "user_123" }'
# Response includes subscriptions array
```
</CodeGroup>
### Usage balances
Metered features have `granted`, `usage`, and `remaining` fields. Use these to display current usage and remaining balance.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
const { data: customer } = useCustomer();
const messages = customer?.balances.messages;
console.log(`${messages?.remaining} / ${messages?.granted}`);
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const customer = await autumn.customers.getOrCreate({
customerId: "user_123",
});
const messages = customer.balances?.messages;
console.log(`${messages?.remaining} / ${messages?.granted}`);
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
customer = await autumn.customers.get_or_create(
customer_id="user_123"
)
messages = customer.balances.get("messages")
print(f"{messages.remaining} / {messages.granted}")
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/customers' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{ "customer_id": "user_123" }'
# Response includes balances.[feature_id]
```
</CodeGroup>
### Switching or cancelling plans
Switching plans uses `billing.attach`. See [Attaching Plans](/documentation/customers/attaching-plans) for the full guide.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
export default function UpgradeButton() {
const { attach } = useCustomer();
return (
<button onClick={() => attach({ planId: "pro" })}>
Upgrade to Pro
</button>
);
}
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const response = await autumn.billing.attach({
customerId: "user_123",
planId: "pro",
});
// Redirect to complete payment or confirm plan change
redirect(response.paymentUrl);
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
response = await autumn.billing.attach(
customer_id="user_123",
plan_id="pro",
)
# Redirect to response.payment_url
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/attach' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "user_123",
"plan_id": "pro"
}'
```
</CodeGroup>
To cancel a plan, use `billing.update` with a `cancelAction`. See [Updating Subscriptions](/documentation/customers/updating-subscriptions#canceling-a-subscription) for details.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
const { updateSubscription } = useCustomer();
// Cancel at end of billing cycle
await updateSubscription({
planId: "pro",
cancelAction: "cancel_end_of_cycle"
});
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
// Cancel at end of billing cycle
await autumn.billing.update({
customerId: "user_123",
planId: "pro",
cancelAction: "cancel_end_of_cycle",
});
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
# Cancel at end of billing cycle
await autumn.billing.update(
customer_id="user_123",
plan_id="pro",
cancel_action="cancel_end_of_cycle",
)
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/billing/update' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "user_123",
"plan_id": "pro",
"cancel_action": "cancel_end_of_cycle"
}'
```
</CodeGroup>
### Uncancelling a plan
If a subscription has a pending cancellation, a scheduled downgrade, or a scheduled plan switch, you can reverse it with `cancelAction: "uncancel"`.
A subscription is pending cancellation when `canceledAt` is not null while the subscription is still `active`.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
export default function BillingPage() {
const { data: customer, updateSubscription } = useCustomer();
const cancellingSub = customer?.subscriptions.find(
(sub) => sub.status === "active" && sub.canceledAt !== null
);
return cancellingSub ? (
<button onClick={() => updateSubscription({
planId: cancellingSub.planId,
cancelAction: "uncancel"
})}>
Keep plan
</button>
) : null;
}
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const customer = await autumn.customers.getOrCreate({
customerId: "user_123",
});
const cancellingSub = customer.subscriptions?.find(
(sub) => sub.status === "active" && sub.canceledAt !== null
);
if (cancellingSub) {
await autumn.billing.update({
customerId: "user_123",
planId: cancellingSub.planId,
cancelAction: "uncancel",
});
}
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
customer = await autumn.customers.get_or_create(
customer_id="user_123"
)
cancelling_sub = next(
(s for s in customer.subscriptions
if s.status == "active" and s.canceled_at is not None),
None,
)
if cancelling_sub:
await autumn.billing.update(
customer_id="user_123",
plan_id=cancelling_sub.plan_id,
cancel_action="uncancel",
)
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/billing/update' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "user_123",
"plan_id": "pro",
"cancel_action": "uncancel"
}'
```
</CodeGroup>
### Stripe billing portal
The Stripe billing portal lets users manage their payment method, view past invoices, and cancel their plan.
<Warning>
Enable the billing portal in your [Stripe settings](https://dashboard.stripe.com/settings/billing/portal).
</Warning>
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
const { openCustomerPortal } = useCustomer();
// Opens Stripe billing portal in current tab
await openCustomerPortal({
returnUrl: "https://your-app.com/billing"
});
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const { url } = await autumn.billing.openCustomerPortal({
customerId: "user_123",
returnUrl: "https://your-app.com/billing",
});
redirect(url);
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
response = await autumn.billing.open_customer_portal(
customer_id="user_123",
return_url="https://your-app.com/billing",
)
# Redirect to response.url
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/billing.open_customer_portal' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "user_123",
"return_url": "https://your-app.com/billing"
}'
```
</CodeGroup>
### Usage history chart
Autumn provides aggregate time series queries for usage data. Pass the response to a charting library like Recharts.
<CodeGroup>
```jsx React
import { useAggregateEvents } from "autumn-js/react";
const { list, total } = useAggregateEvents({
featureId: "messages",
range: "30d",
});
// list: [{ period: 1234567890, values: { messages: 42 } }, ...]
// total: { messages: { count: 100, sum: 500 } }
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const { list, total } = await autumn.events.aggregate({
customerId: "user_123",
featureId: "messages",
range: "30d",
});
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
response = await autumn.events.aggregate(
customer_id="user_123",
feature_id="messages",
range="30d",
)
# response.list, response.total
```
```bash cURL
curl -X POST 'https://api.useautumn.com/v1/events.aggregate' \
-H 'Authorization: Bearer am_sk_test_1234' \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "user_123",
"feature_id": "messages",
"range": "30d"
}'
```
</CodeGroup>