Skip to content

Latest commit

Β 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation


TokenToll

The open-source billing engine for AI & SaaS products

Meter tokens. Enforce quotas. Invoice automatically.


License: MIT Python FastAPI TypeScript MongoDB Redis Docker Stripe PRs Welcome



Star History

Star History Chart

12 AI Providers Β· 5 Pricing Models Β· 30+ API Endpoints Β· Python & Node SDKs


πŸš€ Quick Start Β· 🎯 Features Β· πŸ“¦ SDKs Β· πŸ“– API Reference Β· βš™οΈ Configuration Β· 🐳 Deployment Β· 🀝 Contributing




🐾 What is TokenToll?

The problem: You're building a SaaS on top of LLMs. You need to track usage per customer, enforce quotas, support free tiers and prepaid credits, and generate invoices. Building all that from scratch takes weeks.

The solution: TokenToll gives you a single API to handle all of it. Ingest usage events, define pricing in YAML, and let TokenToll compute costs, enforce limits, generate invoices, and sync to Stripe β€” or run fully self-hosted.

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚              β”‚  report  β”‚              β”‚  invoice β”‚              β”‚
  β”‚   Your App   │────────▢ β”‚  TokenToll   │────────▢ β”‚   Customer   β”‚
  β”‚  calls LLM   β”‚  tokens  β”‚   API        β”‚  auto    β”‚   gets bill  β”‚
  β”‚              β”‚          β”‚              β”‚          β”‚              β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Features

πŸ“Š Usage Metering

βœ… Event ingestion via REST or SDK
βœ… Idempotent (duplicate IDs ignored)
βœ… Batch ingestion
βœ… Multi-meter (tokens, calls, compute)


πŸ’° Flexible Pricing

βœ… Per-unit β€” qty Γ— rate
βœ… Tiered β€” bracket-based rates
βœ… Volume β€” total determines rate
βœ… Flat β€” fixed monthly fee
βœ… Prepaid β€” credit deduction
βœ… Free tiers β€” free allowance

πŸ”’ Quotas & Entitlements

βœ… Hard limits β€” block at cap
βœ… Soft limits β€” alert via webhook
βœ… Budget caps β€” dollar spending limits
βœ… Alert thresholds β€” 80%, 100%, etc.


🧾 Invoicing & Payments

βœ… Auto monthly invoice generation
βœ… Per-meter line items
βœ… Stripe sync or self-hosted
βœ… Prepaid credit auto-apply
βœ… Invoice status tracking
βœ… Retry with exponential backoff

🏒 Multi-Tenancy

βœ… Full tenant isolation
βœ… Operator super-admin API
βœ… Per-tenant API key rotation
βœ… SHA-256 hashed key storage


πŸ”” Webhooks & Observability

βœ… HMAC-SHA256 signed delivery
βœ… 3 event types with auto-retry
βœ… Full audit logging
βœ… Event replay / reconciliation
βœ… Platform analytics endpoint
βœ… Rate limiting per tenant


πŸ€– Built-in AI Provider Pricing

TokenToll ships with pre-configured cost tables for 12 providers and 100+ models. Pass provider and model with your events β€” costs are calculated automatically.


GPT-4o Β· o1 Β· o3

Claude 4 Β· 3.5 Β· Haiku

Gemini 2.5 Β· Flash

Large Β· Codestral

V3 Β· R1

Llama 3 Β· Llama 4

Command R+

LPU Inference

Grok

Sonar Pro

Open Models

Hosted OpenAI

Tip

Rates are YAML files in config/provider_pricing/ β€” update them anytime and hot-reload without restart.


πŸ—οΈ Architecture

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚                 β”‚         β”‚                  β”‚         β”‚               β”‚
  β”‚    Your App     │────────▢│   TokenToll API  │────────▢│   MongoDB     β”‚
  β”‚  (SDK / HTTP)   β”‚         β”‚   (FastAPI)      β”‚         β”‚               β”‚
  β”‚                 β”‚         β”‚                  β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚  Redis Streams   β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€-┐
                     β”‚                β”‚                 β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
              β”‚  Ingestion  β”‚  β”‚   Invoice   β”‚   β”‚   Webhook   β”‚
              β”‚   Worker    β”‚  β”‚   Worker    β”‚   β”‚   Worker    β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                      β”‚
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚    Stripe      β”‚
                              β”‚  (optional)    β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Component Role
🌐 API Server FastAPI REST API β€” auth, rate limiting, multi-tenant routing
⚑ Ingestion Worker Processes usage events, updates wallets, checks entitlements
πŸ’΅ Invoice Worker Monthly invoice generation, Stripe sync, credit application
πŸ“¨ Webhook Worker HMAC-signed delivery with retries to your endpoints
πŸƒ MongoDB Persistent storage β€” tenants, customers, events, invoices, audit logs
πŸ”΄ Redis Stream-based queue + per-tenant rate limiting

πŸš€ Quick Start

Note

You need Docker & Docker Compose. Stripe is optional β€” without it, TokenToll runs in manual invoicing mode.

Step 1 β€” Start the stack

git clone https://github.com/AlameerAshraf/tokentoll.git
cd tokentoll
docker compose -f docker/docker-compose.yml up -d

Step 2 β€” Verify it's running

curl http://localhost:8000/health | jq
# βœ… {"status": "ok", "database": "ok"}

Step 3 β€” Create a tenant (your SaaS company)

curl -s -X POST http://localhost:8000/v1/tenants \
  -H "Content-Type: application/json" \
  -d '{"name": "My SaaS", "slug": "my-saas"}' | jq

Step 4 β€” Generate an API key

curl -s -X POST http://localhost:8000/v1/tenants/{tenant_id}/api-keys \
  -d '{"name": "production"}' | jq

# ⚠️ Save the "key" field β€” shown only once!

Step 5 β€” Create a customer & send usage

# Create customer on the "default" plan
curl -s -X POST http://localhost:8000/v1/tenants/{tenant_id}/customers \
  -H "Authorization: Bearer tt_your_key" \
  -H "Content-Type: application/json" \
  -d '{"external_id": "user_123", "plan_id": "default", "name": "Alice"}' | jq

# Report usage
curl -s -X POST http://localhost:8000/v1/events \
  -H "Authorization: Bearer tt_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "evt_001",
    "customer_id": "user_123",
    "meter_name": "token_count",
    "quantity": 1500,
    "provider": "openai",
    "model": "gpt-4o"
  }' | jq
# βœ… {"accepted": 1, "rejected": 0, "errors": []}

Step 6 β€” Check the balance

curl -s http://localhost:8000/v1/tenants/{tenant_id}/customers/{customer_id}/balance \
  -H "Authorization: Bearer tt_your_key" | jq

Tip

For the full 14-phase walkthrough covering every feature with curl, see docs/full-scenario-guide.md.


πŸ“¦ SDKs

The SDKs are not published to package registries. Build and use them locally from your macine or PUBLISH THEM IF YOU WANT πŸ‘πŸ» 🐾.

Build & install locally

Python SDK

# From repo root β€” editable install (changes apply immediately)
pip install -e ./packages/sdk-python
# or with uv:
uv pip install -e ./packages/sdk-python

Node.js SDK

# 1. Build the package (from repo root)
cd packages/sdk-node && npm run build

# 2. In your app, install from the local path
# If your app is inside tokentoll (e.g. apps/dashboard):
npm install ../../packages/sdk-node

# If your app is elsewhere, use an absolute or relative path:
npm install /path/to/tokentoll/packages/sdk-node

# Or add to your package.json dependencies:
# "@tokentoll/sdk-node": "file:../path/to/tokentoll/packages/sdk-node"

🐍 Python

from tokentoll import TokenToll

client = TokenToll(
    api_key="tt_your_key",
    base_url="http://localhost:8000",
    tenant_id="your_tenant_id"
)

# 🐾 Emit usage β€” one line
client.emit("user_123", "token_count", 1500)

# Check balance
balance = client.get_balance("user_123")

# Gate requests on quota
result = client.check_entitlement(
    "user_123", "token_count", 1000
)
if result["allowed"]:
    # serve the request
    ...

πŸ’š Node.js

import { TokenToll } from '@tokentoll/sdk-node';

const client = new TokenToll({
  apiKey: 'tt_your_key',
  baseUrl: 'http://localhost:8000',
  tenantId: 'your_tenant_id',
});

// 🐾 Emit usage β€” one line
await client.emit('user_123', 'token_count', 1500);

// Check balance
const balance = await client.getBalance('user_123');

// Gate requests on quota
const { allowed, remaining } =
  await client.checkEntitlement(
    'user_123', 'token_count', 1000
  );

Environment variables (both SDKs): TOKENTOLL_API_KEY Β· TOKENTOLL_BASE_URL Β· TOKENTOLL_TENANT_ID


πŸ“– API Reference

Note

🐾 Interactive Swagger UI is available at http://localhost:8000/docs when running locally.

Core Endpoints

Method Path Auth Description
πŸ“€ POST /v1/events Tenant Ingest usage events (single or batch)
🏒 POST /v1/tenants Operator Create a tenant
🏒 GET /v1/tenants Any List tenants
🏒 PATCH /v1/tenants/{id} Any Update tenant
🏒 DELETE /v1/tenants/{id} Any Delete tenant (cascade)
πŸ‘€ POST /v1/tenants/{id}/customers Tenant Create a customer
πŸ‘€ GET /v1/tenants/{id}/customers Tenant List customers
πŸ‘€ PATCH /v1/tenants/{id}/customers/{id} Tenant Update customer / change plan
πŸ‘€ DELETE /v1/tenants/{id}/customers/{id} Tenant Delete customer
πŸ’° GET .../customers/{id}/balance Tenant Get usage & credit balance
πŸ’° POST .../customers/{id}/credits Operator Add prepaid credits
πŸ”’ POST .../customers/{id}/check-entitlement Tenant Check quota before serving
πŸ“Š PUT .../customers/{id}/budget Tenant Set budget cap & alert thresholds
πŸ“Š GET .../customers/{id}/budget Tenant Get budget
πŸ“Š DELETE .../customers/{id}/budget Tenant Remove budget
🧾 GET .../customers/{id}/invoices Tenant List invoices
🧾 GET /v1/tenants/{id}/invoices/{id} Tenant Get single invoice
πŸ”‘ POST /v1/tenants/{id}/api-keys Any Create API key
πŸ”‘ GET /v1/tenants/{id}/api-keys Any List API keys
πŸ”‘ DELETE /v1/tenants/{id}/api-keys/{id} Any Revoke API key
πŸ”” POST /v1/tenants/{id}/webhooks Tenant Register webhook
πŸ”” GET /v1/tenants/{id}/webhooks Tenant List webhooks
πŸ”” PATCH /v1/tenants/{id}/webhooks/{id} Tenant Update webhook
πŸ”” DELETE /v1/tenants/{id}/webhooks/{id} Tenant Delete webhook
πŸ“‹ GET /v1/tenants/{id}/plans Tenant List plans for tenant

Operator Endpoints

Method Path Description
βš™οΈ GET /v1/config/plans List all plan configs
βš™οΈ GET /v1/config/plans/{id} Get plan config detail
βš™οΈ PUT /v1/config/plans/{id} Create or update plan
βš™οΈ DELETE /v1/config/plans/{id} Delete plan
πŸ”„ POST /v1/config/reload Hot-reload config from YAML
πŸ“ˆ GET /v1/analytics Platform-wide aggregate stats
βͺ POST /v1/tenants/{id}/replay Replay events to rebuild usage
πŸ€– GET /v1/providers List available provider pricing

Authentication

Authorization: Bearer tt_...       ← Recommended
X-API-Key: tt_...                  ← Alternative header
?api_key=tt_...                    ← Query parameter

βš™οΈ Configuration

πŸ“‹ Plans β€” config/plans/*.yaml

# config/plans/pro.yaml
name: pro
pricing_model: tiered
provider: openai                    # Use built-in provider rates

meters:
  token_count:
    tiers:
      - up_to: 1_000_000           # First 1M tokens
        rate: 0.0001
      - up_to: 10_000_000          # 1M – 10M tokens
        rate: 0.00008
      - up_to: null                 # 10M+ tokens
        rate: 0.00005

entitlements:
  token_count:
    hard_limit: 50_000_000          # πŸ›‘ Block at 50M
    soft_limit: 40_000_000          # ⚠️ Alert at 40M

free_tier:
  token_count: 100_000              # 🎁 First 100K free

πŸ’² Pricing Models

Model Formula Use Case
per_unit quantity Γ— rate Simple token billing β€” $0.001/token
tiered Rate changes per bracket Volume discounts β€” cheaper at scale
volume Total volume picks the rate Enterprise pricing β€” all units at best rate
flat Fixed fee SaaS subscriptions β€” $99/month
prepaid Deduct from credit balance Buy $100 in credits, use until gone

πŸ“ Meters β€” config/meters/*.yaml

name: token_count
type: token_count         # token_count | request_count | compute_time | custom
unit: tokens

πŸ€– Provider Pricing β€” config/provider_pricing/*.yaml

provider: openai
currency: USD
updated_at: "2025-03-01"
models:
  gpt-4o:
    input_per_million: 2.50
    output_per_million: 10.00
  gpt-4o-mini:
    input_per_million: 0.15
    output_per_million: 0.60

πŸ”„ Hot Reload

curl -X POST http://localhost:8000/v1/config/reload \
  -H "Authorization: Bearer $OPERATOR_KEY"

# βœ… {"reloaded": true, "plans_synced": 4, "meters_synced": 1}

πŸ§ͺ Testing

TokenToll includes integration tests covering critical billing guarantees:

tests/
β”œβ”€β”€ integration/
β”‚   β”œβ”€β”€ test_ingestion_idempotency.py   ← Duplicate events never double-counted
β”‚   └── test_tenant_isolation.py        ← Cross-tenant access blocked (403)
└── conftest.py                         ← Shared fixtures
Test What It Proves
βœ… Idempotency Same event_id sent twice β†’ usage counted only once
βœ… Tenant Isolation Tenant A cannot read Tenant B's data β†’ returns 403
βœ… Cross-Tenant Events Events for another tenant's customer β†’ rejected as unknown_customer

Run Tests

# Start dependencies
docker compose -f docker/docker-compose.yml up -d mongodb redis

# API integration tests
cd apps/api && uv run pytest -v

# Node SDK tests
cd packages/sdk-node && npm test

# Lint
cd apps/api && ruff check .

🐳 Deployment

Docker Compose (Recommended)

STRIPE_SECRET_KEY=sk_live_... \
OPERATOR_API_KEY=your-secret \
docker compose -f docker/docker-compose.yml up -d

Services

Service Port Description
🌐 api 8000 FastAPI REST API
⚑ workers β€” Ingestion event processor
πŸ’΅ invoice-worker β€” Monthly invoice generator
πŸ“¨ webhook-worker β€” Webhook delivery with retries
πŸ–₯️ dashboard 5174 React operator & customer UI
πŸƒ mongodb 27018 Persistent storage
πŸ”΄ redis 6379 Queue + rate limiting

Environment Variables

Variable Default Description
MONGODB_URI mongodb://localhost:27017/tokentoll MongoDB connection
REDIS_URL redis://localhost:6379/0 Redis connection
STRIPE_SECRET_KEY (none) Stripe key β€” omit for manual invoicing
OPERATOR_API_KEY (none) Super-admin key β€” omit for open bootstrap
RATE_LIMIT_REQUESTS_PER_MINUTE 1000 Per-tenant rate limit
LOG_LEVEL INFO Logging verbosity
CONFIG_PATH (auto) Path to config/ directory
INVOICE_INTERVAL_MIN 60 Invoice worker interval (minutes)

πŸ“‚ Project Structure

tokentoll/
β”‚
β”œβ”€β”€ 🐾 apps/
β”‚   β”œβ”€β”€ api/                          ← FastAPI REST API
β”‚   β”‚   └── src/
β”‚   β”‚       β”œβ”€β”€ main.py               ← App entry point & lifespan
β”‚   β”‚       β”œβ”€β”€ api/
β”‚   β”‚       β”‚   β”œβ”€β”€ routes/           ← 15 route modules
β”‚   β”‚       β”‚   β”œβ”€β”€ middleware/       ← Auth (API key) + Rate limiting
β”‚   β”‚       β”‚   └── errors.py        ← Standardized error responses
β”‚   β”‚       β”œβ”€β”€ models/               ← 12 Beanie ODM document classes
β”‚   β”‚       β”œβ”€β”€ services/             ← 7 business logic modules
β”‚   β”‚       β”œβ”€β”€ adapters/             ← MongoDB, Redis, Stripe, Manual
β”‚   β”‚       └── config/               ← YAML loaders + JSON schemas
β”‚   β”‚
β”‚   β”œβ”€β”€ workers/                      ← Background processors
β”‚   β”‚   └── src/workers/
β”‚   β”‚       β”œβ”€β”€ ingestion_worker.py   ← Usage event processing
β”‚   β”‚       β”œβ”€β”€ invoice_worker.py     ← Monthly billing
β”‚   β”‚       └── webhook_worker.py     ← Webhook delivery
β”‚   β”‚
β”‚   └── dashboard/                    ← React + Vite + TypeScript
β”‚       └── src/pages/                ← Operator & customer views
β”‚
β”œβ”€β”€ πŸ“¦ packages/
β”‚   β”œβ”€β”€ sdk-python/                   ← Python SDK (httpx)
β”‚   └── sdk-node/                     ← Node.js SDK (TypeScript)
β”‚
β”œβ”€β”€ βš™οΈ config/
β”‚   β”œβ”€β”€ plans/                        ← Pricing plan definitions
β”‚   β”œβ”€β”€ meters/                       ← Meter definitions
β”‚   └── provider_pricing/             ← 12 AI provider cost tables
β”‚
β”œβ”€β”€ 🐳 docker/
β”‚   β”œβ”€β”€ docker-compose.yml            ← Full stack (7 services)
β”‚   β”œβ”€β”€ Dockerfile.api
β”‚   β”œβ”€β”€ Dockerfile.workers
β”‚   └── Dockerfile.dashboard
β”‚
└── πŸ“š docs/
    β”œβ”€β”€ full-scenario-guide.md        ← Complete HTTP walkthrough (14 phases)
    β”œβ”€β”€ video-script.md               ← Demo video script
    β”œβ”€β”€ deployment.md                 ← Production deployment
    └── testing-scenario.md           ← Test scenarios

🀝 Contributing

We welcome contributions! TokenToll is open source and community-driven.

Dev Setup

# 1. Fork & clone
git clone https://github.com/your-username/tokentoll.git && cd tokentoll

# 2. Start dependencies
docker compose -f docker/docker-compose.yml up -d mongodb redis

# 3. Install & run API
cd apps/api && uv sync && uvicorn src.main:app --reload --port 8000

# 4. Run workers (separate terminals)
cd apps/workers && uv sync
python -m src.workers.main ingestion
python -m src.workers.main invoice
python -m src.workers.main webhook

# 5. Build SDKs (for local use in your projects β€” see [SDKs](#-sdks))
cd packages/sdk-python && uv sync && pip install -e .   # or: uv pip install -e .
cd packages/sdk-node && npm install && npm run build

Contribution Flow

Step Action
1 🍴 Fork the repo
2 🌿 Branch β€” git checkout -b feat/my-feature
3 βœ… Test β€” cd apps/api && uv run pytest -v
4 🧹 Lint β€” ruff check .
5 πŸ“¬ PR β€” open with a clear description

πŸ“„ License

MIT β€” use it however you want. See LICENSE for details.




TokenToll

πŸš€ Get Started Β· πŸ“š Read the Docs Β· πŸ”— View API


Built with ❀️ for the AI developer community in Egypt πŸ‡ͺπŸ‡¬


About

🐾 TokenToll: is a self-hostable billing infrastructure for LLM APIs and SaaS products. Drop-in SDKs for Node.js and Python, YAML-defined pricing plans, Stripe adapter, and a real-time usage dashboard | The open-source alternative to Lago and Orb.

Topics

Resources

Stars

77 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages