Overview
Client tokens allow your frontend applications to call Limitry APIs directly without exposing your API key. They are short-lived, scoped tokens created by your backend.
Create a Client Token
Generate a token for a specific customer:
from limitry import Limitry
client = Limitry()
# Create a client token
result = client.client_tokens.create(
# Public metadata - exposed via GET /client/token
public_metadata={
"customer_id": "cust_123",
"plan": "pro"
},
# Server context - only accessible server-side, never exposed to client
server_context={
"internal_id": "int_456",
"credit_limit": 1000
},
ttl_seconds=3600 # 1 hour (default). Max: 86400 (24 hours)
)
print(f"Token: {result.token}")
Payload: public_metadata and server_context
Tokens support two payloads:
result = client.client_tokens.create(
# Public metadata - client can read via GET /client/token
public_metadata={
"customer_id": "cust_123", # Required: determines whose usage is returned
"plan": "pro", # Optional: for UI display
"features": ["chat", "api"] # Optional: custom data
},
# Server context - never exposed to client
server_context={
"internal_id": "int_456", # Internal references
"credit_limit": 1000, # Sensitive limits
"permissions": ["read"] # Access control
}
)
| Type | Description | Accessible To |
|---|
public_metadata | Public data | Client (via GET /client/token) and your handlers |
server_context | Private data | Your handlers only - never exposed to client |
Token Expiration
Set how long the token is valid:
# Short-lived token (recommended)
result = client.client_tokens.create(
public_metadata={"customer_id": "cust_123"},
ttl_seconds=3600 # 1 hour
)
# Longer-lived token (use sparingly)
result = client.client_tokens.create(
public_metadata={"customer_id": "cust_123"},
ttl_seconds=86400 # 24 hours (maximum)
)
Shorter TTLs are more secure. Use the default 1 hour unless you have a specific need for longer tokens.
Backend Endpoint Example
Create an endpoint that generates tokens for authenticated users:
from flask import Flask, request, jsonify
from limitry import Limitry
app = Flask(__name__)
client = Limitry()
@app.route("/api/limitry-token", methods=["POST"])
def get_limitry_token():
# 1. Authenticate the user (your auth logic)
user = get_authenticated_user(request)
if not user:
return jsonify({"error": "Unauthorized"}), 401
# 2. Create a client token for this user's customer
result = client.client_tokens.create(
public_metadata={
"customer_id": user.customer_id,
"plan": user.plan
},
server_context={
"user_id": user.id
},
ttl_seconds=3600
)
# 3. Return the token to the frontend
return jsonify({"token": result.token})
FastAPI Example
from fastapi import FastAPI, Depends, HTTPException
from limitry import Limitry
app = FastAPI()
client = Limitry()
@app.post("/api/limitry-token")
async def get_limitry_token(user: User = Depends(get_current_user)):
result = client.client_tokens.create(
public_metadata={
"customer_id": user.customer_id,
"plan": user.plan
},
ttl_seconds=3600
)
return {"token": result.token}
Async Support
Use the async client for async applications:
from limitry import AsyncLimitry
async def create_token(customer_id: str) -> str:
async with AsyncLimitry() as client:
result = await client.client_tokens.create(
public_metadata={"customer_id": customer_id},
ttl_seconds=3600
)
return result.token
What Clients Can Do
Once the frontend has a token, it can call these Client API endpoints:
| Endpoint | Description |
|---|
GET /client/token | Retrieve the token (projectId + publicMetadata) |
POST /client/limits/check | Check limits for the customer |
POST /client/events/record | Record an event |
GET /client/events/summary | Get usage summary |
Client tokens cannot access management endpoints like creating limits, viewing other customers, or modifying meters.
Best Practices
- Always authenticate users first - Create tokens only for authenticated users
- Keep TTLs short - Use 1 hour or less when possible
- Use server_context for sensitive data - Never put sensitive info in public metadata
- Create tokens on-demand - Don’t pre-generate or cache tokens