LLMtrack / SDK

Official SDKs for Node and Python

Track every LLM request's cost with one line of code. Never throws, never blocks, retries safely, and counts reasoning tokens — so your cost data is complete and your app is untouched.

Quickstart

  1. Install the package.
  2. Initialize it with your ingestion key.
  3. Track after your LLM call.
import { LLMtrack } from 'llmtrack';

const llmtrack = new LLMtrack({ apiKey: process.env.LLMTRACK_API_KEY });

// after your LLM call — fire-and-forget, never throws, never blocks
llmtrack.track({
  provider: 'openai',
  model: 'gpt-5.6-sol',
  feature: 'chat-completion',
  promptTokens: 1200,
  completionTokens: 480,
  reasoningTokens: 3100,
});

Examples

OpenAI completion

const response = await openai.chat.completions.create({
  model: 'gpt-5.6-sol',
  messages,
});

llmtrack.track({
  provider: 'openai', model: response.model, feature: 'chat-completion',
  promptTokens: response.usage?.prompt_tokens,
  completionTokens: response.usage?.completion_tokens,
  reasoningTokens: response.usage?.completion_tokens_details?.reasoning_tokens,
});

Anthropic completion

const message = await anthropic.messages.create({
  model: 'claude-sonnet-5', max_tokens: 1024, messages,
});

llmtrack.track({
  provider: 'anthropic', model: message.model, feature: 'chat-completion',
  promptTokens: message.usage.input_tokens,
  completionTokens: message.usage.output_tokens,
});

Anthropic includes thinking tokens inside output_tokens rather than reporting them separately — do not also pass them as reasoningTokens, or the cost will be double-counted.

Why use the SDK?

  • Never throws: track() swallows every failure into a warning callback.
  • Auto-retry: network, timeout, and 5xx failures retry with stable idempotency keys, so retries can never double-count cost.
  • Client-side validation: enforces 8 KB metadata and non-negative integer tokens.
  • Fully typed: typed constructors, event fields, callbacks, errors, and warnings.

Prefer raw HTTP or another language? The full API reference documents the endpoint every SDK uses — Go, Ruby, PHP, Rust and anything else can integrate with one POST.

Constructor options

OptionTypeDefaultDescription
apiKeystring— (required)LLMtrack ingestion key.
baseUrlstringhttps://llm-track.comAPI base URL.
environmentstringproductionDefault event environment.
onError(error) => voidundefinedReceives validation errors.
onWarning(warning) => voidconsole.warnReceives swallowed delivery failures and API warnings.
enabledbooleantrueTurns tracking on or off.
timeoutMsnumber5000Request timeout in milliseconds.
maxRetriesnumber3Maximum network, timeout, and 5xx retries.

Event fields

The exported Node event type is TrackOptions. Field names are language-specific; using the other SDK's casing is silently ignored.

Node (camelCase only)

FieldTypeRequiredDescription
providerstringRequiredNon-empty provider name.
modelstringRequiredNon-empty model name.
featurestring | nullOptionalTakes precedence over metadata.feature; defaults to unknown.
customerIdstring | nullOptionalCustomer attribution.
customerNamestring | nullOptionalCustomer attribution.
environmentstring | nullOptionalDefaults to production.
promptTokensinteger | nullOptionalNon-negative token count.
completionTokensinteger | nullOptionalNon-negative token count.
totalTokensinteger | nullOptionalComputed from prompt + completion + reasoning when omitted or null.
reasoningTokensinteger | nullOptionalNon-negative reasoning token count.
cachedInputTokensinteger | nullOptionalNon-negative cached input token count.
cacheWriteTokensinteger | nullOptionalNon-negative cache-write token count.
latencyMsinteger | nullOptionalNon-negative latency in milliseconds.
statusstringOptionalsuccess, error, timeout, or cancelled; defaults to success.
metadataobjectOptionalArbitrary JSON object, at most 8 KB (8192 bytes) serialized.

Python (snake_case only)

FieldTypeRequiredDescription
providerstringRequiredNon-empty provider name.
modelstringRequiredNon-empty model name.
featurestring | nullOptionalTakes precedence over metadata.feature; defaults to unknown.
customer_idstring | nullOptionalCustomer attribution.
customer_namestring | nullOptionalCustomer attribution.
environmentstring | nullOptionalDefaults to production.
prompt_tokensinteger | nullOptionalNon-negative token count.
completion_tokensinteger | nullOptionalNon-negative token count.
total_tokensinteger | nullOptionalComputed from prompt + completion + reasoning when omitted or null.
reasoning_tokensinteger | nullOptionalNon-negative reasoning token count.
cached_input_tokensinteger | nullOptionalNon-negative cached input token count.
cache_write_tokensinteger | nullOptionalNon-negative cache-write token count.
latency_msinteger | nullOptionalNon-negative latency in milliseconds.
statusstringOptionalsuccess, error, timeout, or cancelled; defaults to success.
metadataobjectOptionalArbitrary JSON object, at most 8 KB (8192 bytes) serialized.

Errors and warnings

CodeMeaningFix
INVALID_API_KEYThe key is missing or invalid.Use an active LLMtrack ingestion key.
REVOKED_API_KEYThe key was deleted or revoked.Create and use a new key.
INACTIVE_API_KEYThe key is deactivated.Reactivate it or use an active key.
INVALID_PAYLOADOne or more event fields are invalid.Correct the fields identified by validation.
QUOTA_EXCEEDEDThe plan event allowance is exhausted.Wait for reset or upgrade the workspace.
PLAN_INACTIVEThe workspace plan cannot ingest events.Restore an active plan.
NETWORK_ERRORThe SDK could not reach LLMtrack.Check connectivity; the SDK retries automatically.

Warnings

  • pricing_status: "unknown_model": no active pricing row exists, so cost is 0; this is different from a genuine calculated zero.

Troubleshooting

  • Events not appearing: confirm that you are using an active key and inspect the response for errors.
  • Cost is 0: check for pricing_status: "unknown_model".
  • Key rejected: revoked keys need replacement; inactive keys need reactivation or replacement.
  • Nothing happens: confirm enabled is not false and LLMTRACK_API_KEY is the correct environment variable.

Track your first request