Back to Blog
Getting StartedTutorial
Getting Started with Parmot
Learn how to set up your first usage plan with token limits and rate limiting in just a few minutes.
August 14, 2025
10 min read
By Parmot Team
Integrate usage tracking and plan enforcement for OpenAI, Anthropic, and more—with optional Stripe-driven plan changes.
1) Install
npm install parmot
# or
yarn add parmot
# Python
pip install parmot
2) Set API Keys
# .env
PARMOT_API_KEY="parmot_your_api_key_here"
OPENAI_API_KEY="your_openai_api_key_here"
3) Track Your First Call
TypeScript
import { TrackedOpenAI } from "parmot";
const client = new TrackedOpenAI({
apiKey: process.env.OPENAI_API_KEY!,
parmotApiKey: process.env.PARMOT_API_KEY!,
});
const res = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello, world!" }],
user_id: "user_123",
});
console.log(res.choices[0].message?.content);
Python
from parmot import TrackedOpenAI
client = TrackedOpenAI(
api_key="your_openai_api_key",
parmot_api_key="your_parmot_api_key"
)
res = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role":"user","content":"Hello, world!"}],
user_id="user_123"
)
print(res.choices[0].message.content)
Streaming responses are tracked automatically (both TS and Python).
4) Plans & Assignments (Programmatic)
TypeScript
import { ParmotClient } from "parmot";
const parmot = new ParmotClient();
const plan = await parmot.createEndUserPlan({
name: "Pro",
monthly_token_limit: 1_000_000,
monthly_cost_limit: 50.0,
description: "Pro tier with 1M tokens/month",
});
await parmot.assignEndUserToPlan("user_123", "Pro");
const assignment = await parmot.getEndUserPlanAssignment("user_123");
console.log(assignment?.name); // "Pro"
Python
from parmot import ParmotClient
parmot = ParmotClient()
plan = parmot.create_end_user_plan(
name="Pro",
monthly_token_limit=1_000_000,
monthly_cost_limit=50.00,
description="Pro tier with 1M tokens/month"
)
parmot.assign_end_user_to_plan("user_123", "Pro")
print(parmot.get_end_user_plan_assignment("user_123")?.name)
Usage summaries
// TS
const user = await parmot.getEndUserUsageSummary("user_123");
const all = await parmot.getEndUserUsageSummary();
# Python
user = parmot.get_end_user_usage_summary("user_123")
all = parmot.get_end_user_usage_summary()
5) Stripe Integration (Recommended)
Include end-user id in subscription metadata
import Stripe from "stripe";
const stripe = new Stripe("sk_your_stripe_key");
await stripe.subscriptions.create({
customer: "cus_customer_id",
items: [{ price: "price_your_stripe_price_id" }],
metadata: { end_user_id: "user_123" },
});
Webhook: move users between plans
import express from "express";
import Stripe from "stripe";
import { ParmotClient } from "parmot";
const app = express();
const stripe = new Stripe("sk_your_stripe_key");
const parmot = new ParmotClient();
app.post("/stripe/webhook", express.raw({ type: "application/json" }), async (req, res) => {
const sig = req.headers["stripe-signature"];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig!, "whsec_your_webhook_secret");
} catch (err:any) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case "invoice.payment_succeeded": {
const subId = event.data.object.subscription as string;
const sub = await stripe.subscriptions.retrieve(subId);
const endUserId = sub.metadata?.end_user_id;
if (endUserId) await parmot.assignEndUserToPlan(endUserId, "Pro");
break;
}
case "invoice.payment_failed": {
const subId = event.data.object.subscription as string;
const sub = await stripe.subscriptions.retrieve(subId);
const endUserId = sub.metadata?.end_user_id;
if (endUserId) await parmot.assignEndUserToPlan(endUserId, "Free");
break;
}
}
res.json({ received: true });
});
Python Flask version available as well; mirror the same logic.
Configureinvoice.payment_succeeded
andinvoice.payment_failed
in your Stripe dashboard.
6) Error Handling
TypeScript
import {
TrackedOpenAI,
ParmotEndUserUsageLimitError,
ParmotEndUserRateLimitError,
} from "parmot";
const client = new TrackedOpenAI();
try {
await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
user_id: "user_123",
});
} catch (err) {
if (err instanceof ParmotEndUserUsageLimitError) {
// upgrade flow, show UI, etc.
} else if (err instanceof ParmotEndUserRateLimitError) {
// respect err.retry_after
} else {
// generic error path
}
}
Python
from parmot import (
TrackedOpenAI,
ParmotEndUserUsageLimitError,
ParmotEndUserRateLimitError,
)
client = TrackedOpenAI()
try:
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role":"user","content":"Hello!"}],
user_id="user_123"
)
except ParmotEndUserUsageLimitError as e:
pass # upgrade flow
except ParmotEndUserRateLimitError as e:
pass # wait e.retry_after
except Exception:
pass
7) Other Providers
Anthropic
import { TrackedAnthropic } from "parmot";
const client = new TrackedAnthropic({
apiKey: process.env.ANTHROPIC_API_KEY!,
parmotApiKey: process.env.PARMOT_API_KEY!,
});
const resp = await client.messages.create({
model: "claude-3-5-haiku-20241022",
messages: [{ role: "user", content: "Hello!" }],
max_tokens: 100,
user_id: "user_123",
});
console.log(resp.content[0].text);
Cohere
from parmot import TrackedCohere
client = TrackedCohere(
api_key="your_cohere_api_key",
parmot_api_key="your_parmot_api_key"
)
resp = client.chat(
model="command-r-08-2024",
messages=[{"role":"user","content":"Hello!"}],
user_id="user_123"
)
print(resp.message.content[0].text)
Supported Providers (snapshot)
- OpenAI — Supported (Chat Completions; Text, Vision)
- Anthropic — Supported (Messages API; Text)
- OpenRouter — Supported (Chat Completions; Text, Vision)
- Cohere — Supported (Chat API; Python ready; TS not yet)
- AWS Bedrock — Coming Soon
- Databricks — Coming Soon
That’s it
Create plans in the dashboard or via API, assign users, and let Parmot enforce limits automatically. For keys and UI, head to /dashboard
.