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
- Install the package.
- Initialize it with your ingestion key.
- 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
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — (required) | LLMtrack ingestion key. |
baseUrl | string | https://llm-track.com | API base URL. |
environment | string | production | Default event environment. |
onError | (error) => void | undefined | Receives validation errors. |
onWarning | (warning) => void | console.warn | Receives swallowed delivery failures and API warnings. |
enabled | boolean | true | Turns tracking on or off. |
timeoutMs | number | 5000 | Request timeout in milliseconds. |
maxRetries | number | 3 | Maximum 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)
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Required | Non-empty provider name. |
model | string | Required | Non-empty model name. |
feature | string | null | Optional | Takes precedence over metadata.feature; defaults to unknown. |
customerId | string | null | Optional | Customer attribution. |
customerName | string | null | Optional | Customer attribution. |
environment | string | null | Optional | Defaults to production. |
promptTokens | integer | null | Optional | Non-negative token count. |
completionTokens | integer | null | Optional | Non-negative token count. |
totalTokens | integer | null | Optional | Computed from prompt + completion + reasoning when omitted or null. |
reasoningTokens | integer | null | Optional | Non-negative reasoning token count. |
cachedInputTokens | integer | null | Optional | Non-negative cached input token count. |
cacheWriteTokens | integer | null | Optional | Non-negative cache-write token count. |
latencyMs | integer | null | Optional | Non-negative latency in milliseconds. |
status | string | Optional | success, error, timeout, or cancelled; defaults to success. |
metadata | object | Optional | Arbitrary JSON object, at most 8 KB (8192 bytes) serialized. |
Python (snake_case only)
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Required | Non-empty provider name. |
model | string | Required | Non-empty model name. |
feature | string | null | Optional | Takes precedence over metadata.feature; defaults to unknown. |
customer_id | string | null | Optional | Customer attribution. |
customer_name | string | null | Optional | Customer attribution. |
environment | string | null | Optional | Defaults to production. |
prompt_tokens | integer | null | Optional | Non-negative token count. |
completion_tokens | integer | null | Optional | Non-negative token count. |
total_tokens | integer | null | Optional | Computed from prompt + completion + reasoning when omitted or null. |
reasoning_tokens | integer | null | Optional | Non-negative reasoning token count. |
cached_input_tokens | integer | null | Optional | Non-negative cached input token count. |
cache_write_tokens | integer | null | Optional | Non-negative cache-write token count. |
latency_ms | integer | null | Optional | Non-negative latency in milliseconds. |
status | string | Optional | success, error, timeout, or cancelled; defaults to success. |
metadata | object | Optional | Arbitrary JSON object, at most 8 KB (8192 bytes) serialized. |
Errors and warnings
| Code | Meaning | Fix |
|---|---|---|
INVALID_API_KEY | The key is missing or invalid. | Use an active LLMtrack ingestion key. |
REVOKED_API_KEY | The key was deleted or revoked. | Create and use a new key. |
INACTIVE_API_KEY | The key is deactivated. | Reactivate it or use an active key. |
INVALID_PAYLOAD | One or more event fields are invalid. | Correct the fields identified by validation. |
QUOTA_EXCEEDED | The plan event allowance is exhausted. | Wait for reset or upgrade the workspace. |
PLAN_INACTIVE | The workspace plan cannot ingest events. | Restore an active plan. |
NETWORK_ERROR | The 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
enabledis notfalseandLLMTRACK_API_KEYis the correct environment variable.