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

1. Installation

Install the Parmot SDK:

npm install parmot
2. Set up API Keys

Get your API keys and set them as environment variables:

.env
# 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.

3. Track Your First API Call
Basic Usage
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

Creating Plans

Create subscription plans with token and cost limits through the dashboard:

  1. Navigate to the Dashboard
  2. Go to the "Plans" section
  3. Click "Create Plan"
  4. Set your plan name, limits, and description
  5. 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
Managing Users

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

Creating Plans Programmatically
Create Plan
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}`);
Assigning Users to Plans
Assign Plan
// 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");
}
Getting Usage Summary
Usage Summary
// 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

OpenAI Support

Both streaming and non-streaming responses are automatically tracked:

OpenAI Usage
// 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
Anthropic Support

Full support for Anthropic's Messages API:

Anthropic Usage
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);
  }
}
Cohere Support

Support for Cohere's Chat API:

Cohere Usage
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.

Supported Providers
ProviderStatusModalitiesNotes
OpenAI logoOpenAI
SupportedText, VisionChat Completions API (Beta and Responses coming soon).
Anthropic logoAnthropic
SupportedTextChat completions API
OpenRouter logoOpenRouter
SupportedText, VisionChat completions API
Cohere logoCohere
SupportedTextChat API
AWS Bedrock logoAWS Bedrock
Coming Soon--
Databricks logoDatabricks
Coming Soon--

Stripe Integration

Step 1: Include End User ID in Subscription Metadata

When creating Stripe subscriptions, include your app's end user ID in the metadata:

Create Subscription with 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.

Step 2: Webhook Setup

Set up Stripe webhooks to automatically manage user plan transitions based on payment events:

Stripe Webhook Handler
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

Automatic Plan Management

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

Usage and Rate Limit Errors

Handle usage and rate limit errors gracefully:

Error Handling
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 Types
ErrorDescription
ParmotUsageLimitErrorYour monthly usage logging limit has been exceeded
ParmotEndUserUsageLimitErrorThe end user's token/cost limit has been exceeded
ParmotEndUserRateLimitErrorThe end user's rate limit has been exceeded
ParmotEndUserBannedErrorUser is banned from making API calls
ParmotAPIErrorGeneral API error
ParmotNotFoundErrorResource not found
ParmotValidationErrorRequest validation failed

Ready to get started?

Start tracking usage and managing user limits today with our easy-to-use SDKs.