Commet
  • Pricing
Log InTry out
Introduction

Quickstart

Learn

Track UsageAI Token BillingSeat ManagementQuota Management

Resources

SDK ReferenceAPI VersioningError HandlingTestingCLI

Plugins

Better Auth
System status
DocumentationKnowledge BaseBuild with AIAPI ReferenceWebhooks

Track Usage

Record metered consumption with the current Commet SDKs.

Every metered feature has one code. Send that code as featureCode; Commet aggregates events for access, credits, balance, and billing.

Track an event

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const usageEvent = await commet.usage.track({  featureCode: "api_calls",  customerId: "user_123",  model: "example",  inputTokens: 1,  outputTokens: 1,});
from commet import Commetcommet = Commet("ck_xxx")usage_event = commet.usage.track(    feature_code="api_calls",    customer_id="user_123",    model="example",    input_tokens=1,    output_tokens=1,)
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()usageEvent, err := client.Usage.Track(ctx, &commet.TrackUsageParams{	FeatureCode: "api_calls",	CustomerID: "user_123",	Model: func(value string) *string { return &value }("example"),	InputTokens: func(value int) *int { return &value }(1),	OutputTokens: func(value int) *int { return &value }(1),})if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.TrackUsageParams;var commet = Commet.builder().apiKey("ck_xxx").build();var usageEvent = commet.usage().track(    TrackUsageParams.builder("api_calls", "user_123").model("example").inputTokens(1L).outputTokens(1L).build());
use Commet\Commet;$commet = new Commet('ck_xxx');$usageEvent = $commet->usage->track(    featureCode: 'api_calls',    customerId: 'user_123',    model: 'example',    inputTokens: 1,    outputTokens: 1,);

The request accepts:

FieldRequiredMeaning
featureCodeYesMetered feature code
customerIdYesCommet customer ID or your stable customer ID
valueNoNumeric quantity; defaults to one for normal usage events
eventIdNoCaller-owned business event ID used to deduplicate retries
timestampNoISO 8601 event time; defaults to now
propertiesNoString property entries for attribution and debugging

AI-model events use the same operation but send model, inputTokens, and outputTokens instead of value.

Business event ID vs request idempotency

eventId identifies the consumption event in your system. Reuse it when the same event is retried.

Request idempotency protects one HTTP mutation and is passed through the SDK's request options as idempotencyKey. It becomes the Idempotency-Key header. Do not put that transport key in the usage body.

await commet.usage.track(
  {
    featureCode: 'api_calls',
    customerId: 'user_123',
    value: 1,
    eventId: 'request_01JXYZ',
  },
  { idempotencyKey: 'delivery_01JXYZ' },
)

Correct current-period usage

Use set when your source of truth needs to replace the current metered total:

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const usageAdjustment = await commet.usage.set({  customerId: "user_123",  featureCode: "api_calls",  value: 1,});
from commet import Commetcommet = Commet("ck_xxx")usage_adjustment = commet.usage.set(    customer_id="user_123",    feature_code="api_calls",    value=1,)
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()usageAdjustment, err := client.Usage.Set(ctx, &commet.SetUsageParams{	CustomerID: "user_123",	FeatureCode: "api_calls",	Value: 1,})if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.SetUsageParams;var commet = Commet.builder().apiKey("ck_xxx").build();var usageAdjustment = commet.usage().set(    SetUsageParams.builder("user_123", "api_calls", 1L).build());
use Commet\Commet;$commet = new Commet('ck_xxx');$usageAdjustment = $commet->usage->set(    customerId: 'user_123',    featureCode: 'api_calls',    value: 1,);

value is the desired total, not a delta. Commet records a signed adjustment and preserves the original event trail. This operation applies only to the active metered period.

Check before consuming

When access or cost depends on the proposed quantity, call Usage Check before performing the action:

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const usageCheck = await commet.usage.check({  customerId: "user_123",  featureCode: "api_calls",});
from commet import Commetcommet = Commet("ck_xxx")usage_check = commet.usage.check(    customer_id="user_123",    feature_code="api_calls",)
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()usageCheck, err := client.Usage.Check(ctx, &commet.CheckUsageAvailabilityParams{	CustomerID: "user_123",	FeatureCode: "api_calls",})if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.CheckUsageAvailabilityParams;var commet = Commet.builder().apiKey("ck_xxx").build();var usageCheck = commet.usage().check(    CheckUsageAvailabilityParams.builder("user_123", "api_calls").build());
use Commet\Commet;$commet = new Commet('ck_xxx');$usageCheck = $commet->usage->check(    customerId: 'user_123',    featureCode: 'api_calls',);

Related

  • Configure Features
  • AI Token Billing
  • Consumption Models

How is this guide?

Upgrade and Downgrade Plans

How customers change plans through the Customer Portal and dashboard.

AI Token Billing

Automatically measure and charge for AI token usage with model-aware pricing and configurable margins.

On this page

Track an event
Business event ID vs request idempotency
Correct current-period usage
Check before consuming
Related