Files
cfw-autumn/apps/docs/mintlify/examples/prepaid.mdx
2026-02-20 17:33:15 +00:00

351 lines
7.9 KiB
Plaintext

---
title: Prepaid top-ups
description: Let customers purchase prepaid packages and top-ups.
---
If a user hits a usage limit you granted them, they may be willing to purchase a top-up.
These are typically one-time purchases (or less commonly, recurring add-ons) that grant a fixed usage of a feature.
This gives users full spend control and allows your business to be paid upfront. For these reasons, it tends to be a more popular alternative to usage-based pricing -- eg, OpenAI uses this model for their API.
## Example case
In this example, we have an AI chatbot that offers:
- 10 premium messages for free
- An option for customers to top-up premium messages in packages of $10 per 100 messages.
## Configure Pricing
<Steps>
<Step>
#### Create Features
Create a `metered` `consumable` feature for our premium messages, so we can track its balance.
<Frame>
<img src="/assets/guides/prepaid/features-light.png" className="block dark:hidden" />
<img src="/assets/guides/prepaid/features-dark.png" className="hidden dark:block" />
</Frame>
</Step>
<Step>
#### Create Free and Top-up Plans
Create our free plan, and assign 10 premium messages to it. These are "one-off" credits, that will not reset periodically.
<Tip>
Make sure to set the `auto-enable` flag on the free plan, so that it is automatically assigned to new customers.
</Tip>
<Frame>
<img src="/assets/guides/prepaid/free-light.png" className="block dark:hidden" />
<img src="/assets/guides/prepaid/free-dark.png" className="hidden dark:block" />
</Frame>
Now we'll create our top-up plan. We'll add a price to our premium messages feature, at $10 per 100 messages. These are "one-off" purchases, with a `prepaid` billing method.
`prepaid` features require a `quantity` to be sent in when a customer attaches this product, so the customer can specify how many premium messages they want to top up with.
<Frame>
<img src="/assets/guides/prepaid/topup-light.png" className="block dark:hidden" />
<img src="/assets/guides/prepaid/topup-dark.png" className="hidden dark:block" />
</Frame>
</Step>
</Steps>
## Implementation
<Steps>
<Step>
#### Create an Autumn Customer
When your user signs up, create an Autumn customer. This will automatically assign them the Free plan, and grant them 10 premium messages.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
const App = () => {
const { data: customer } = useCustomer();
console.log("Autumn customer:", customer);
return <h1>Welcome, {customer?.name || "user"}!</h1>;
};
```
```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",
name: "John Yeo",
email: "john@example.com",
});
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
customer = await autumn.customers.get_or_create(
customer_id="user_123",
name="John Yeo",
email="john@example.com",
)
```
```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",
"name": "John Yeo",
"email": "john@example.com"
}'
```
</CodeGroup>
</Step>
<Step>
#### Checking for access
Every time our user wants to send a premium message, we'll first check if they have enough premium messages remaining.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
export function CheckPremiumMessage() {
const { check, refetch } = useCustomer();
const handleCheckAccess = async () => {
const { allowed } = check({ featureId: "premium_messages" });
if (!allowed) {
alert("You've run out of premium messages");
} else {
// proceed with sending message
await refetch();
}
};
}
```
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
const response = await autumn.customers.check({
customerId: "user_123",
featureId: "premium_messages",
});
if (!response.allowed) {
console.log("User has run out of premium messages");
return;
}
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
response = await autumn.customers.check(
customer_id="user_123",
feature_id="premium_messages",
)
if not response.allowed:
print("User has run out of premium messages")
```
```bash cURL
curl -X POST "https://api.useautumn.com/v1/check" \
-H "Authorization: Bearer am_sk_test_1234" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "user_123",
"feature_id": "premium_messages"
}'
```
</CodeGroup>
<Expandable title="check response">
```json
{
"allowed": true,
"customerId": "user_123",
"requiredBalance": 1,
"balance": {
"featureId": "premium_messages",
"granted": 10,
"remaining": 10,
"usage": 0,
"unlimited": false,
"overageAllowed": false,
"nextResetAt": null
}
}
```
</Expandable>
</Step>
<Step>
#### Tracking premium messages
Now let's implement our usage tracking and use up our premium messages. In this example, we're using 5 premium messages.
<CodeGroup>
```typescript TypeScript
import { Autumn } from "autumn-js";
const autumn = new Autumn({ secretKey: "am_sk_test_1234" });
await autumn.customers.track({
customerId: "user_123",
featureId: "premium_messages",
value: 5,
});
```
```python Python
from autumn_sdk import Autumn
autumn = Autumn("am_sk_test_1234")
await autumn.customers.track(
customer_id="user_123",
feature_id="premium_messages",
value=5,
)
```
```bash cURL
curl -X POST "https://api.useautumn.com/v1/track" \
-H "Authorization: Bearer am_sk_test_1234" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "user_123",
"feature_id": "premium_messages",
"value": 5
}'
```
</CodeGroup>
<Expandable title="track response">
```json
{
"customerId": "user_123",
"value": 5,
"balance": {
"featureId": "premium_messages",
"granted": 10,
"remaining": 5,
"usage": 5,
"unlimited": false,
"overageAllowed": false,
"nextResetAt": null
}
}
```
</Expandable>
</Step>
<Step>
#### Purchasing top-ups
When users run out of premium messages, they can purchase additional messages using our top-up plan. In this example, the user is purchasing 200 premium messages, which will cost them $20.
<CodeGroup>
```jsx React
import { useCustomer } from "autumn-js/react";
export default function TopUpButton() {
const { attach } = useCustomer();
return (
<button
onClick={() => attach({
planId: "top_up",
featureQuantities: [{
featureId: "premium_messages",
quantity: 200,
}],
})}
>
Buy More Messages
</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: "top_up",
featureQuantities: [{
featureId: "premium_messages",
quantity: 200,
}],
});
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="top_up",
feature_quantities=[{
"feature_id": "premium_messages",
"quantity": 200,
}],
)
# 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": "top_up",
"feature_quantities": [{
"feature_id": "premium_messages",
"quantity": 200
}]
}'
```
</CodeGroup>
Once the customer completes the payment, they will have an additional 200 premium messages available to use. You can display this to the user by getting balances from the customer endpoint.
</Step>
</Steps>