- Updated: March 25, 2026
- 3 min read
Implementing Usage‑Based (Metered) Billing in the OpenClaw SaaS Boilerplate
Why Metered Billing Is Essential for AI SaaS
Artificial‑intelligence services are typically consumed in a pay‑as‑you‑go fashion: the more tokens processed, the higher the cost. Fixed‑price plans either over‑charge low‑usage customers or under‑price heavy users, leading to churn or lost revenue. Metered (usage‑based) billing aligns price with actual consumption, improves transparency, and lets developers experiment with AI features without fear of unexpected bills.
Step‑by‑Step Technical Guide
1. Data Collection
Collect usage metrics at the point where the AI model is invoked. In OpenClaw, this is usually the service layer that calls OpenAI, Anthropic, etc. Store the following per request:
- Customer ID
- Timestamp
- Number of tokens (prompt + completion) or other relevant units
- Feature flag (e.g., “image‑generation”) if you bill different features differently
Persist this data in a dedicated usage_events table (PostgreSQL, MySQL, or a time‑series DB). Example schema:
CREATE TABLE usage_events (
id SERIAL PRIMARY KEY,
customer_id UUID NOT NULL,
event_time TIMESTAMP NOT NULL DEFAULT NOW(),
tokens_used INTEGER NOT NULL,
feature VARCHAR(50) NOT NULL
);
2. Rate Calculation
Define a pricing matrix, e.g.:
{
"gpt-4": 0.03, // $0.03 per 1k tokens
"gpt-3.5": 0.006,
"image": 0.0015
}
Periodically (hourly or daily) aggregate usage per customer and calculate the amount owed:
SELECT customer_id,
SUM(tokens_used) / 1000.0 * price_per_k AS amount
FROM usage_events ue
JOIN pricing p ON ue.feature = p.feature
GROUP BY customer_id;
3. Stripe Integration
Use Stripe’s Usage‑Based Billing (metered billing) API. Create a product and a recurring price with billing_scheme=per_unit and usage_type=metered. Then, for each aggregation window, report usage:
stripe.subscriptionItems.createUsageRecord(
subscriptionItemId,
{
quantity: Math.round(totalTokens / 1000),
timestamp: Math.floor(Date.now() / 1000),
action: 'set'
}
);
Make sure the customer in Stripe matches the customer_id stored in your DB.
4. Webhook Handling
Listen to Stripe webhooks to keep your internal state in sync:
invoice.created– generate a PDF or store the invoice reference.invoice.payment_succeeded– mark the period as paid.customer.subscription.deleted– disable the API key for that tenant.
Example webhook endpoint (Node.js/Express):
app.post('/stripe/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
switch (event.type) {
case 'invoice.payment_succeeded':
// update DB
break;
// … other cases …
}
res.json({received: true});
});
Putting It All Together in OpenClaw
1. Add a middleware that records each AI request into usage_events.
2. Create a scheduled job (e.g., using node‑cron) that aggregates the day’s usage and calls the Stripe usage‑record API.
3. Deploy the Stripe webhook route and secure it with the signing secret.
4. Test end‑to‑end with a sandbox Stripe account before going live.
Internal Reference
For a deeper dive into hosting OpenClaw on UBOS, see the guide Host OpenClaw on UBOS.
With these steps, developers can offer AI‑powered features that scale with usage, ensuring fair billing and a better customer experience.