@raypx/billing
Plan limits and billing logic for free and pro tiers.
@raypx/billing provides plan tier definitions and usage checking functions. It currently supports two tiers (free and pro) and exports utility functions for checking whether a user can perform AI operations or upload documents based on their current usage.
Plan Tiers
| Tier | Description |
|---|---|
free | Default tier with basic limits |
pro | Paid tier with higher limits |
Use resolvePlanTier() to convert a raw value to a PlanTier:
import { resolvePlanTier } from "@raypx/billing"
resolvePlanTier("pro") // "pro"
resolvePlanTier("free") // "free"
resolvePlanTier("other") // "free"
resolvePlanTier(null) // "free"
resolvePlanTier(undefined) // "free"Plan Limits
| Limit | Free | Pro |
|---|---|---|
| Monthly AI tokens | 25,000 | 250,000 |
| Monthly AI requests | 100 | 2,000 |
| Max documents | 25 | 2,000 |
| Max file size | 2 MB | 25 MB |
Use getPlanLimits() to retrieve the limits for a tier:
import { getPlanLimits } from "@raypx/billing"
const limits = getPlanLimits("pro")
// { monthlyAiTokens: 250000, monthlyAiRequests: 2000, maxDocuments: 2000, maxFileSizeBytes: 26214400 }Usage Check Functions
canUseAi
Check whether a user can make an AI request given their current usage:
import { canUseAi } from "@raypx/billing"
const result = canUseAi(
{ aiTokens: 24_000, aiRequests: 99, documents: 5 },
"free",
800, // requested tokens
)
if (result.allowed) {
// Proceed with AI request
} else {
// result.reason: "monthly_ai_tokens" or "monthly_ai_requests"
}The function checks two conditions in order:
- Whether the next request would exceed
monthlyAiRequests. - Whether the requested tokens would push the total over
monthlyAiTokens.
canUploadDocument
Check whether a user can upload a document:
import { canUploadDocument } from "@raypx/billing"
const result = canUploadDocument(
{ aiTokens: 100, aiRequests: 2, documents: 24 },
"free",
1_500_000, // file size in bytes
)
if (result.allowed) {
// Proceed with upload
} else {
// result.reason: "max_documents" or "max_file_size"
}Checks two conditions:
- Whether adding one more document would exceed
maxDocuments. - Whether the file size exceeds
maxFileSizeBytes.
Usage Snapshot
A UsageSnapshot represents the current usage counters for a billing period:
interface UsageSnapshot {
aiTokens: number
aiRequests: number
documents: number
}Use getDefaultUsageSnapshot() to get a zeroed snapshot:
import { getDefaultUsageSnapshot } from "@raypx/billing"
const snapshot = getDefaultUsageSnapshot()
// { aiTokens: 0, aiRequests: 0, documents: 0 }Usage Allowance Result
Both check functions return a UsageAllowanceResult:
interface UsageAllowanceResult {
allowed: boolean
reason?: "monthly_ai_tokens" | "monthly_ai_requests" | "max_documents" | "max_file_size"
}When allowed is false, the reason field indicates which limit was exceeded, allowing the frontend to display an appropriate message.
Future: Payment Provider Integration
The billing package currently handles plan limits only. Payment provider integration (subscription management, invoicing, webhooks) is planned for a future release. The existing PlanTier type and resolvePlanTier() function are designed to be extended with additional tiers as needed.