Skip to main content

Overview

The UsageClient provides methods for reporting and querying metered feature usage. It works in conjunction with the EntitlementsClient — report usage after a successful entitlement check, and revert it if downstream operations fail.

Methods

report()

Report usage of a metered feature. Increments the customer’s usage meter.
const result = await revstack.usage.report(params);
params
ReportUsageParams
required
Usage report parameters.
result
object
success
boolean
Confirmation of the reported usage.
Example:
const { success } = await revstack.usage.report({
  customerId: "usr_abc123",
  featureId: "api-calls",
  amount: 10,
  idempotencyKey: "req_xyz",
});

if (success) {
  console.log("Usage reported successfully");
}

revert()

Revert (roll back) previously reported usage. Decrements the customer’s usage meter. Essential for maintaining accurate billing when downstream operations fail after usage was already recorded.
const result = await revstack.usage.revert(params);
params
RevertUsageParams
required
Revert parameters including reason for audit trail.
result
object
success
boolean
Confirmation of the reverted usage.
Example:
// Revert usage after an OpenAI call fails
await revstack.usage.revert({
  customerId: "usr_abc123",
  featureId: "ai-tokens",
  amount: 500,
  reason: "downstream_failure",
});

getMeters()

Retrieve all usage meters for a customer (one per metered entitlement).
const meters = await revstack.usage.getMeters(customerId);
customerId
string
required
The customer whose meters to retrieve.Example: "usr_abc123"
meters
UsageMeter[]
Array of usage meters with current counts and reset times.
Example:
const meters = await revstack.usage.getMeters("usr_abc123");

for (const meter of meters) {
  console.log(
    `Entitlement ${meter.entitlementId}: ${meter.currentUsage} used`
  );
}

getMeter()

Retrieve a single usage meter for a specific customer and feature.
const meter = await revstack.usage.getMeter(customerId, featureId);
customerId
string
required
The customer whose meter to retrieve.
featureId
string
required
The entitlement slug or ID.
meter
UsageMeter
The usage meter with current count and reset time.
Example:
const meter = await revstack.usage.getMeter(
  "usr_abc123",
  "api-calls"
);

console.log(`API Calls: ${meter.currentUsage}`);
console.log(`Resets at: ${meter.resetAt}`);

Usage Patterns

Optimistic Usage Pattern

For operations where you need to check limits before execution:
// 1. Check entitlement
const { allowed } = await revstack.entitlements.check(
  userId,
  "ai-tokens",
  { amount: 500 }
);

if (!allowed) {
  throw new Error("Insufficient tokens");
}

// 2. Report usage immediately
await revstack.usage.report({
  customerId: userId,
  featureId: "ai-tokens",
  amount: 500,
});

// 3. Perform the operation
try {
  await openai.chat.completions.create({ ... });
} catch (error) {
  // 4. Revert if operation fails
  await revstack.usage.revert({
    customerId: userId,
    featureId: "ai-tokens",
    amount: 500,
    reason: "downstream_failure",
  });
  throw error;
}

Pessimistic Usage Pattern

For operations where you know the exact usage after execution:
try {
  // 1. Perform the operation
  const result = await expensiveOperation();
  
  // 2. Report actual usage after success
  await revstack.usage.report({
    customerId: userId,
    featureId: "api-calls",
    amount: result.callsMade,
  });
  
  return result;
} catch (error) {
  // No usage to revert since we didn't report any
  throw error;
}

Idempotent Usage Reporting

import { v4 as uuidv4 } from "uuid";

// Generate idempotency key from request ID
const idempotencyKey = `usage_${requestId}`;

await revstack.usage.report({
  customerId: userId,
  featureId: "api-calls",
  amount: 1,
  idempotencyKey, // Prevents duplicate charges on retries
});

Display Current Usage

// Get all meters for a customer
const meters = await revstack.usage.getMeters(userId);

// Display in a usage dashboard
for (const meter of meters) {
  const entitlement = await revstack.entitlements.get(
    meter.entitlementId
  );
  
  console.log(`${entitlement.name}:`);
  console.log(`  Current: ${meter.currentUsage}`);
  console.log(`  Resets: ${new Date(meter.resetAt).toLocaleDateString()}`);
}

Build docs developers (and LLMs) love