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:
import Limitry from '@limitry/sdk';
const client = new Limitry();
// Create a client token
const result = await client.clientTokens.create({
// Public metadata - exposed via GET /client/token
publicMetadata: {
customerId: "cust_123",
plan: "pro"
},
// Server context - only accessible server-side, never exposed to client
serverContext: {
internalId: "int_456",
creditLimit: 1000
},
ttlSeconds: 3600 // 1 hour (default). Max: 86400 (24 hours)
});
console.log(`Token: ${result.token}`);
Payload: publicMetadata and serverContext
Tokens support two payloads:
const result = await client.clientTokens.create({
// Public metadata - client can read via GET /client/token
publicMetadata: {
customerId: "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
serverContext: {
internalId: "int_456", // Internal references
creditLimit: 1000, // Sensitive limits
permissions: ["read"] // Access control
}
});
| Type | Description | Accessible To |
|---|
publicMetadata | Public data | Client (via GET /client/token) and your handlers |
serverContext | Private data | Your handlers only - never exposed to client |
Token Expiration
Set how long the token is valid:
// Short-lived token (recommended)
const result = await client.clientTokens.create({
publicMetadata: { customerId: "cust_123" },
ttlSeconds: 3600 // 1 hour
});
// Longer-lived token (use sparingly)
const result = await client.clientTokens.create({
publicMetadata: { customerId: "cust_123" },
ttlSeconds: 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:
Express
import express from 'express';
import Limitry from '@limitry/sdk';
const app = express();
const client = new Limitry();
app.post('/api/limitry-token', async (req, res) => {
// 1. Authenticate the user (your auth logic)
const user = await getAuthenticatedUser(req);
if (!user) {
return res.status(401).json({ error: 'Unauthorized' });
}
// 2. Create a client token for this user's customer
const result = await client.clientTokens.create({
publicMetadata: {
customerId: user.customerId,
plan: user.plan
},
serverContext: {
userId: user.id
},
ttlSeconds: 3600
});
// 3. Return the token to the frontend
res.json({ token: result.token });
});
Next.js API Route
// app/api/limitry-token/route.ts
import { NextResponse } from 'next/server';
import Limitry from '@limitry/sdk';
import { getServerSession } from 'next-auth';
const client = new Limitry();
export async function POST() {
const session = await getServerSession();
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const result = await client.clientTokens.create({
publicMetadata: {
customerId: session.user.customerId,
plan: session.user.plan
},
ttlSeconds: 3600
});
return NextResponse.json({ token: result.token });
}
Hono
import { Hono } from 'hono';
import Limitry from '@limitry/sdk';
const app = new Hono();
const client = new Limitry();
app.post('/api/limitry-token', async (c) => {
const user = c.get('user'); // From your auth middleware
if (!user) {
return c.json({ error: 'Unauthorized' }, 401);
}
const result = await client.clientTokens.create({
publicMetadata: {
customerId: user.customerId,
plan: user.plan
},
ttlSeconds: 3600
});
return c.json({ token: result.token });
});
Frontend Usage
Once your backend returns a token, use it in the browser:
// Fetch token from your backend
const { token } = await fetch('/api/limitry-token', {
method: 'POST'
}).then(r => r.json());
// Use token to check limits
const response = await fetch('https://api.limitry.com/client/limits/check', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const { allowed, limits } = await response.json();
if (!allowed) {
showUpgradePrompt();
}
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 serverContext for sensitive data - Never put sensitive info in public metadata
- Create tokens on-demand - Don’t pre-generate or cache tokens