Add AI Token Metering to Your API in 5 Minutes
You’re building an AI-powered product. Users get a credit allowance. When they’re out, they upgrade or stop using the feature.
Simple concept. Complex implementation.
You need to track usage per user. Decrement on each request. Handle concurrent requests without overselling. Expose balances in your UI. Block requests when empty. Reset on billing cycles.
That’s a billing system. You wanted to build an AI product.
The 5-Minute Version
Meter handles the accounting. You handle the AI.
Step 1: Create a meter for your user
curl -X POST https://meter.solenoid.systems/v1/meter/create \
-H "Authorization: Bearer sm_your_api_key" \
-H "Content-Type: application/json" \
-d '{"meter_id": "user_123", "initial_balance": 10000}'
User 123 now has 10,000 credits.
Step 2: Check and decrement on each request
// In your AI endpoint
async function handleAIRequest(userId: string, prompt: string) {
// Estimate tokens (or use actual count after response)
const estimatedTokens = Math.ceil(prompt.length / 4) + 500
const meter = await fetch('https://meter.solenoid.systems/v1/meter/decrement', {
method: 'POST',
headers: {
'Authorization': 'Bearer sm_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
meter_id: `user_${userId}`,
amount: estimatedTokens
})
})
const { success, balance } = await meter.json()
if (!success) {
return { error: 'insufficient_credits', balance }
}
// Proceed with AI call
const response = await callOpenAI(prompt)
return { response, remaining_credits: balance }
}
Step 3: Show balance in your UI
const balance = await fetch(
`https://meter.solenoid.systems/v1/meter/balance?meter_id=user_${userId}`,
{ headers: { 'Authorization': 'Bearer sm_your_api_key' } }
).then(r => r.json())
// Returns: { meter_id: "user_123", balance: 8500 }
That’s it. You have usage metering.
Handling the Edge Cases
Concurrent requests: Meter operations are atomic. Two simultaneous decrements won’t oversell. If a user has 100 credits and sends two 60-credit requests at once, one succeeds, one fails.
Negative balances: By default, Meter rejects decrements that would go negative. If you want to allow overdraft (maybe you bill overage later), pass allow_negative: true.
Refunds: Increment the balance back:
curl -X POST https://meter.solenoid.systems/v1/meter/increment \
-H "Authorization: Bearer sm_your_api_key" \
-d '{"meter_id": "user_123", "amount": 500}'
Monthly resets: On your billing cycle, set the balance:
curl -X POST https://meter.solenoid.systems/v1/meter/set \
-H "Authorization: Bearer sm_your_api_key" \
-d '{"meter_id": "user_123", "balance": 10000}'
Pre-flight Checks for Better UX
Don’t let users start a long AI generation only to fail mid-stream. Check balance before expensive operations:
async function canAffordGeneration(userId: string, estimatedCost: number) {
const { balance } = await fetch(
`https://meter.solenoid.systems/v1/meter/balance?meter_id=user_${userId}`,
{ headers: { 'Authorization': 'Bearer sm_your_api_key' } }
).then(r => r.json())
return balance >= estimatedCost
}
// In your UI
if (!await canAffordGeneration(userId, 1000)) {
showUpgradePrompt()
return
}
Real Token Counts
Estimating tokens from prompt length works, but actual usage varies. For precise billing, adjust after the response:
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }]
})
const actualTokens = response.usage.total_tokens
const estimatedTokens = 500 // What you decremented earlier
// Adjust if estimate was off
const difference = actualTokens - estimatedTokens
if (difference > 0) {
await meterDecrement(userId, difference)
} else if (difference < 0) {
await meterIncrement(userId, Math.abs(difference))
}
Multi-Tenant Usage
Building a platform where customers have their own users? Namespace your meter IDs:
customer_acme:user_123
customer_globex:user_456
Each namespace is isolated. Acme’s users can’t affect Globex’s balances. Your billing stays clean.
Why Not Build This Yourself?
You could. Redis with atomic DECRBY. Postgres with row-level locking. It’s not complicated code.
But it’s infrastructure. Redis needs monitoring. Postgres needs connection pooling. Both need backups. When your metering database hiccups at 2 AM, your AI product is down.
Meter runs on Cloudflare’s edge. Low latency globally. High availability backed by Cloudflare’s infrastructure. You pay per operation, not per server.
Build the AI product. Let the accounting be someone else’s problem.
Try It Now
Free tier: 10,000 API calls to prototype. Pro tier ($49.99/mo) and above: unlimited Meter usage. Build without counting API calls.
# Create a test meter
curl -X POST https://meter.solenoid.systems/v1/meter/create \
-H "Authorization: Bearer sm_your_api_key" \
-d '{"meter_id": "test_user", "initial_balance": 1000}'
# Decrement it
curl -X POST https://meter.solenoid.systems/v1/meter/decrement \
-H "Authorization: Bearer sm_your_api_key" \
-d '{"meter_id": "test_user", "amount": 100}'
# Check balance
curl https://meter.solenoid.systems/v1/meter/balance?meter_id=test_user \
-H "Authorization: Bearer sm_your_api_key"
Your AI billing system, in three curl commands.