Documentation
Everything you need to integrate usage tracking and billing into your AI application.
The typescript npm package is currently in invite-only beta.
Quick Start
Install the Parmot SDK:
npm install parmot
Get your API keys and set them as environment variables:
# Add to your .env file
PARMOT_API_KEY="parmot_your_api_key_here"
OPENAI_API_KEY="your_openai_api_key_here"
ANTHROPIC_API_KEY="your_anthropic_api_key_here"
COHERE_API_KEY="your_cohere_api_key_here"
💡 Get your Parmot API key: Sign up at the dashboard and create a new API key in the API Keys section.
import { TrackedOpenAI } from "parmot";
const client = new TrackedOpenAI({
apiKey: "your_openai_api_key",
parmotApiKey: "your_parmot_api_key",
});
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{
role: "user",
content: "Hello, world!"
}],
user_id: "user_123"
});
console.log(response.choices[0].message.content);
✅ That's it! Your API call is now tracked with cost and token usage. Usage limits will be automatically enforced based on the user's plan.
Dashboard Usage
Create subscription plans with token and cost limits through the dashboard:
- Navigate to the Dashboard
- Go to the "Plans" section
- Click "Create Plan"
- Set your plan name, limits, and description
- Save the plan
Plan Settings:
- Monthly Token Limit: Maximum tokens per month (optional)
- Monthly Cost Limit: Maximum cost per month in USD (optional)
- Rate Limit (per minute): Maximum requests per minute (optional)
- Rate Limit (per hour): Maximum requests per hour (optional)
- Rate Limit (per day): Maximum requests per day (optional)
- Description: Plan description for your reference
View and manage all your users from the Users section:
- View real-time usage statistics
- Assign users to different plans
- Monitor usage against plan limits
- Delete users and all their data
Plan Management
import { ParmotClient } from "parmot";
const parmot = new ParmotClient();
const plan = await parmot.createEndUserPlan({
name: "Pro",
monthly_token_limit: 1000000,
monthly_cost_limit: 50.00,
description: "Pro tier with 1M tokens/month"
});
console.log(`Created plan with ID: ${plan.plan_id}`);
// Assign user to a plan
await parmot.assignEndUserToPlan("user_123", "Pro");
// Check user's current plan
const plan = await parmot.getEndUserPlanAssignment("user_123");
if (plan) {
console.log(`User is on ${plan.name} plan`);
} else {
console.log("User has no assigned plan");
}
// Get usage summary for a specific user
const summary = await parmot.getEndUserUsageSummary("user_123");
console.log(`Total cost: $${summary.total_cost}`);
console.log(`This month: $${summary.current_month_cost}`);
console.log(`Total requests: ${summary.total_requests}`);
console.log(`Total tokens: ${summary.total_tokens}`);
// Get usage summary for all users (admin only)
const allUsage = await parmot.getEndUserUsageSummary();
console.log(`Total platform cost: $${allUsage.total_cost}`);
Usage Tracking
Both streaming and non-streaming responses are automatically tracked:
// Streaming responses are automatically tracked
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Count to 10" }],
stream: true,
user_id: "user_123"
});
for await (const chunk of stream) {
if (chunk.choices[0]?.delta?.content) {
process.stdout.write(chunk.choices[0].delta.content);
}
}
// Usage is automatically recorded when stream completes
Full support for Anthropic's Messages API:
import { TrackedAnthropic } from "parmot";
const client = new TrackedAnthropic({
apiKey: "your_anthropic_api_key",
parmotApiKey: "your_parmot_api_key"
});
// Non-streaming
const response = await client.messages.create({
max_tokens: 100,
messages: [{ role: "user", content: "Hello!" }],
model: "claude-3-5-haiku-20241022",
user_id: "user_123"
});
console.log(response.content[0].text);
// Streaming
const stream = await client.messages.create({
max_tokens: 100,
messages: [{ role: "user", content: "Tell me a joke." }],
model: "claude-3-5-haiku-20241022",
user_id: "user_123",
stream: true
});
for await (const event of stream) {
if (event.delta?.text) {
process.stdout.write(event.delta.text);
}
}
Support for Cohere's Chat API:
import { TrackedCohere } from "parmot";
const client = new TrackedCohere({
apiKey: "your_cohere_api_key",
parmotApiKey: "your_parmot_api_key"
});
// Non-streaming (not yet implemented in TypeScript SDK)
// Streaming (not yet implemented in TypeScript SDK)
⚠️ Note: Cohere support is not yet implemented in the TypeScript SDK.
Provider | Status | Modalities | Notes |
---|---|---|---|
![]() | Supported | Text, Vision | Chat Completions API (Beta and Responses coming soon). |
![]() | Supported | Text | Chat completions API |
![]() | Supported | Text, Vision | Chat completions API |
![]() | Supported | Text | Chat API |
![]() | Coming Soon | - | - |
![]() | Coming Soon | - | - |
Stripe Integration
When creating Stripe subscriptions, include your app's end user ID in the metadata:
import Stripe from 'stripe';
const stripe = new Stripe("sk_your_stripe_key");
// When creating a Stripe subscription, include the end user ID in metadata
const subscription = await stripe.subscriptions.create({
customer: "cus_customer_id",
items: [{
price: "price_your_stripe_price_id",
}],
metadata: {
end_user_id: "user_123" // Your app's end user ID
}
});
💡 Pro tip: This approach creates a clean mapping between your Stripe subscriptions and your Parmot end users, allowing seamless plan management via webhooks.
Set up Stripe webhooks to automatically manage user plan transitions based on payment events:
import Stripe from 'stripe';
import express from 'express';
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) {
console.log(`Webhook signature verification failed.`, err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'invoice.payment_succeeded':
// Get end user ID from subscription metadata
const subscriptionId = event.data.object.subscription;
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
const endUserId = subscription.metadata?.end_user_id;
if (endUserId) {
// Move user to paid plan
await parmot.assignEndUserToPlan(endUserId, "Pro");
}
break;
case 'invoice.payment_failed':
// Get end user ID from subscription metadata
const failedSubscriptionId = event.data.object.subscription;
const failedSubscription = await stripe.subscriptions.retrieve(failedSubscriptionId);
const failedEndUserId = failedSubscription.metadata?.end_user_id;
if (failedEndUserId) {
// Move user to free plan
await parmot.assignEndUserToPlan(failedEndUserId, "Free");
}
break;
}
res.json({received: true});
});
⚠️ Important: Configure these webhook events in your Stripe dashboard:invoice.payment_succeeded
,invoice.payment_failed
With webhooks configured, users will be automatically:
Payment Success
Moved to paid plan with increased limits when payment succeeds
Payment Failure
Moved to free plan with basic limits when payment fails
Error Handling
Handle usage and rate limit errors gracefully:
import {
TrackedOpenAI,
ParmotEndUserUsageLimitError,
ParmotEndUserRateLimitError
} from "parmot";
const client = new TrackedOpenAI();
try {
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
user_id: "user_123"
});
} catch (error) {
if (error instanceof ParmotEndUserUsageLimitError) {
console.log(`Usage limit exceeded: ${error.message}`);
console.log(`Current usage: ${error.current_usage}`);
console.log(`Limit: ${error.limit}`);
console.log(`Limit type: ${error.limit_type}`);
// Handle limit exceeded - maybe upgrade user plan
} else if (error instanceof ParmotEndUserRateLimitError) {
console.log(`Rate limit exceeded: ${error.message}`);
console.log(`Retry after: ${error.retry_after} seconds`);
} else {
console.log(`Other error: ${error}`);
}
}
Error | Description |
---|---|
ParmotUsageLimitError | Your monthly usage logging limit has been exceeded |
ParmotEndUserUsageLimitError | The end user's token/cost limit has been exceeded |
ParmotEndUserRateLimitError | The end user's rate limit has been exceeded |
ParmotEndUserBannedError | User is banned from making API calls |
ParmotAPIError | General API error |
ParmotNotFoundError | Resource not found |
ParmotValidationError | Request validation failed |
Ready to get started?
Start tracking usage and managing user limits today with our easy-to-use SDKs.