ModulesAI ModuleAPIsTelemetry Usage

Telemetry Usage API

This is the main API you’ll use to ship your AI usage data to Antarctica. By sending us the specifics of each LLM call, we can compute your analytics and show you exactly what’s happening across your infrastructure.

POST https://otm-api.antarctica.io/v1/telemetry/usage

The Payload Schema

We use a strict schema to make sure your analytics stay clean. If a request doesn’t match the types below, you’ll get a 400 Validation Error.

1. Request Info (request) : Object, Required

FieldTypeRequired?Description
modelIdstringYesThe specific model used. e.g., "gpt-4o" or "claude-3-5-sonnet".
statusstringYesDid the call work? Use "success" or "error".
providerstringYesWho provided the model? e.g., "openai", "anthropic", or "google".

2. User Info (user) : Object, Required

FieldTypeRequired?Description
idstringYesA unique ID for the user making the request (e.g., a hashed email or UUID).
typestringYesIs this an "external" customer or an "internal" employee?
namestringNoOptional: The display name of the user.

3. Tokens (tokens) : Object, Required on Success

Finding These Values: Unsure where to find these in your LLM’s response? Check out our Extracting Metrics guide for OpenAI, Gemini, and Claude examples.

FieldTypeRequired?Description
inputuintYesThe number of tokens you sent to the model (prompt).
outputuintYesThe number of tokens the model sent back (completion).
totaluintNoThe combined total of input and output tokens.

4. Timing Object (timing) : Object, Conditionally Required

Note: Required if the request.status evaluates to "success".

FieldTypeRequired?Description
startTimeISO 8601YesExactly when you started the API request.
firstTokenTimeISO 8601YesWhen you received the very first chunk of data (TTFT).
lastTokenTimeISO 8601YesWhen the full response was finished.
latencyMsuintNoTotal duration in milliseconds (we can calculate this if you leave it blank).

5. Extra Details

  • error object (Required if status is “error”): Include a code and message.
  • io object (Optional): If you want to log the actual prompt and response text. Only use this if your privacy policy allows it!
  • context object (Optional): A place for any extra tags you want to track, like {"projectId": "my_app_v1"}.

The Response Schema

The API will return an HTTP 202 Accepted status when your telemetry package is successfully validated and queued for ingestion.

Success Response (202 Accepted)

FieldTypeDescription
requestIdstringThe unique ID assigned to this ingestion event.
statusstringAlways returns "accepted" for successful requests.
messagestringA human-readable confirmation message.
timestampstringThe ISO 8601 timestamp of when the data was recorded.
usageobjectAn object containing the processed token counts for the record.

JSON Payload Examples

Sometimes it is easiest to just see the raw data. Below are complete, formatted JSON payloads you can use as templates for your system.

1. Successful Inference

When your LLM generates a successful response, send the complete tokens and timing metrics:

{
  "request": {
    "modelId": "gpt-4-turbo",
    "status": "success",
    "provider": "openai"
  },
  "user": {
    "id": "usr_9a8b7c6d",
    "type": "external",
    "name": "Jane Doe"
  },
  "tokens": {
    "input": 145,
    "output": 810,
    "total": 955
  },
  "timing": {
    "startTime": "2024-05-18T14:30:00.000Z",
    "firstTokenTime": "2024-05-18T14:30:01.200Z",
    "lastTokenTime": "2024-05-18T14:30:05.400Z",
    "latencyMs": 5400
  },
  "io": {
    "prompt": "Write a python script to reverse a string.",
    "response": "Here is your python script..."
  },
  "context": {
    "projectId": "prj_python_tutor",
    "location": "us-east-1"
  }
}

Expected Success Response (202 Accepted)

{
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "accepted",
  "usage": {
    "inputTokens": 145,
    "outputTokens": 810,
    "totalTokens": 955
  },
  "message": "Usage recorded successfully.",
  "timestamp": "2024-05-18T14:30:06.124Z"
}

2. Failed Inference (System Error)

If the prompt was flagged, or the provider API timed out, you do not send tokens or timing. Instead, pass the error details:

{
  "request": {
    "modelId": "claude-3-opus",
    "status": "error",
    "provider": "anthropic"
  },
  "user": {
    "id": "usr_1x2y3z",
    "type": "internal"
  },
  "error": {
    "code": "provider_timeout",
    "message": "Anthropic API failed to respond within 30 seconds.",
    "stack": "Error: timeout at Object.request..."
  },
  "context": {
    "projectId": "internal_testing"
  }
}

Implementation Examples

Here is how you might implement this in your actual code. We recommend sending these requests in the background so you don’t slow down your users.

import crypto from "crypto";
 
/**
 * Dispatch Telemetry cleanly and asynchronously without blocking the main event loops.
 */
async function dispatchTelemetryAnalytics(completionMetrics) {
  const payload = {
    request: {
      modelId: "gpt-4-turbo",
      status: "success",
      provider: "openai",
    },
    user: { id: "user_a1b2c3", type: "external" },
    tokens: {
      input: completionMetrics.prompt_tokens,
      output: completionMetrics.completion_tokens,
    },
    timing: {
      startTime: completionMetrics.time.start,
      firstTokenTime: completionMetrics.time.ttft,
      lastTokenTime: completionMetrics.time.end,
    },
    context: {
      projectId: "internal_marketing_gen",
      location: "us-east-1",
    },
  };
 
  try {
    // Run un-awaited to execute purely in background/edge runtime
    fetch("https://otm-api.antarctica.io/v1/telemetry/usage", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.ANTARCTICA_SK_PROD}`,
        "Content-Type": "application/json",
        "Idempotency-Key": crypto.randomUUID(), // Crucial for enterprise reliability
      },
      body: JSON.stringify(payload),
      // Set an aggressive timeout to ensure thread release
      signal: AbortSignal.timeout(3000),
    }).catch((err) =>
      console.warn("[Analytics Warning] Dropped package:", err),
    );
  } catch (err) {
    // Ensures your primary application completely ignores reporting crashes
    console.error("Critical parsing error during telemetry generation", err);
  }
}