REST API

One ingest contract. Every server runtime.

The public Traket API has two versioned endpoints: one writes request-level usage and one publishes the provider and local-pricing catalog. Everything else under the application's API namespace is private product or operations infrastructure.
On this page

Public endpoints

The hosted base URL is https://traket.ai. Send usage only from trusted server code.

POST/api/v1/usage/events
Authenticate with a project SDK write key and submit 1–100 usage events.
Read the contract
GET/api/v1/usage/catalog
Read the public provider list and the models that have local OpenAI-family pricing.
Read the contract
Guardrail actions travel in the opposite direction: Traket calls your HTTPS receiver. Their signature and delivery contract lives in the Guardrails guide.

Authenticate writes

Send the project-scoped SDK write key as a bearer token. The Catalog endpoint is public and requires no authorization.

Events API headers
Authorization: Bearer traket_live_...
Content-Type: application/json

One project per key

Every accepted event is written to the project that issued the key. A request cannot select or override its project ID.

Plaintext shown once

Store the key in a server secret manager. Rotate or revoke it from Connections without exposing it to a browser.

POST usage events

Submit a JSON object with one events array. The endpoint processes every item independently after request-level authentication and limit checks.

cURL request
curl --request POST \
  https://traket.ai/api/v1/usage/events \
  --header "Authorization: Bearer traket_live_..." \
  --header "Content-Type: application/json" \
  --data '{
    "events": [
      {
        "provider": "openai",
        "externalCustomerId": "cus_123",
        "environment": "production",
        "feature": "support_reply",
        "operation": "responses.create",
        "model": "gpt-5.4-mini",
        "idempotencyKey": "response_01J...",
        "usage": {
          "input_tokens": 1280,
          "input_tokens_details": { "cached_tokens": 640 },
          "output_tokens": 220,
          "output_tokens_details": { "reasoning_tokens": 80 },
          "total_tokens": 1500
        }
      }
    ]
  }'
A successful HTTP status does not mean every row was inserted. Batch responses are intentionally granular—always inspect each results entry.

Event object

The documented wire contract uses the fields below. Unknown top-level fields are ignored except legacy customerId, which is explicitly rejected. Traket accepts usage and attribution metadata only, never prompt or model-output content.

provider
Required. One of openai, azure_openai, anthropic, aws_bedrock, google_vertex, mistral, openrouter, other. Normalized to a lowercase underscore slug before validation.
externalCustomerId
Required. An imported Stripe customer ID matching cus_....
attributionQuality
Optional: none, model, user, or customer. Defaults to customer.
cost
Optional explicit cost object. It takes precedence over a local catalog estimate.
durationMs
Optional non-negative duration. Finite values are rounded to an integer.
environment
Optional deployment label, up to 80 characters.
feature
Optional stable product feature slug, up to 120 characters.
granularity
Optional: request, hour, or day. Defaults to request.
idempotencyKey
Optional stable provider response, request, run, or job ID. SDK clients generate one when omitted.
metadata
Optional allowlisted scalar operational metadata. Privacy and size rules apply.
model
Optional provider model ID, up to 160 characters. Unknown IDs remain valid but may not receive an estimated cost.
occurredAt
Optional ISO-8601 timestamp. A missing or invalid value falls back to server receipt time.
operation
Optional provider method or gateway operation, up to 120 characters.
providerRequestId
Optional provider request ID, up to 160 characters.
providerResponseId
Optional provider response ID, up to 160 characters.
status
Optional: success, error, cancelled, or timeout. Defaults to success.
traceId
Optional trace or workflow correlation ID, up to 160 characters.
units
Optional array of provider-neutral token, image, audio, embedding, or tool-call units.
usage
Optional OpenAI-style token usage. Normalized for OpenAI and Azure OpenAI events.

Cost, units, and OpenAI usage

Cost object

Send cost when your provider or gateway already knows the charge. A valid explicit amount wins over a catalog estimate.

amount
Required finite, non-negative number. Zero suppresses estimation without creating a cost row.
currency
usd by default; normalized to lowercase and stored up to 8 characters.
source
estimated_catalog, csv_import, or manual_override; defaults to manual_override.
priceVersion
Optional price source or version label, up to 80 characters.
metadata
Optional scalar metadata with the same privacy rules as event metadata.

Units array

Every event receives one request unit automatically. Use the optional array for additional billable quantities.

quantity
Required finite, non-negative number. Invalid values are rejected; zero-value units are omitted.
unitName
Stable unit label, up to 80 characters. A blank or missing value becomes unknown.
unitType
request, token, image, audio_second, embedding_token, or tool_call.
billableQuantity
Optional finite, non-negative provider-adjusted quantity. Invalid supplied values are rejected.
providerRawKey
Optional source-field name, up to 120 characters.
metadata
Optional scalar metadata with the same privacy rules as event metadata.

OpenAI-style usage

OpenAI and Azure OpenAI events normalize these fields into token units. Known catalog models can receive a local USD estimate when no explicit cost is supplied.

input_tokens
Input token count.
input_tokens_details.cached_tokens
Cached input tokens, capped at the input token count.
output_tokens
Output token count.
output_tokens_details.reasoning_tokens
Reasoning token count when supplied by the provider.
total_tokens
Accepted for provider compatibility; it does not create a separate unit or change the estimate.
Do not send a legacy aggregate units object. units must be an array of unit records; usage is the OpenAI-style token object.

Resolve the paying customer

externalCustomerId is required and must be a Stripe customer ID beginning with cus_. Before live metering, import or connect Stripe so that identity resolves to exactly one customer in the write key's project.

No match

The event is rejected when the Stripe customer has not been imported into this project.

Ambiguous match

The event is rejected when the external ID maps to multiple canonical customers.
Internal workspace, tenant, or user IDs are not substitutes. Revenue attribution is based on the canonical imported Stripe identity.

Responses and errors

A response envelope reports new inserts in accepted, event failures in rejected, and the outcome of every submitted index in results. Duplicate events appear only in results.

Mixed batch response
{
  "accepted": 1,
  "rejected": 1,
  "results": [
    {
      "eventId": "b06c67d5-...",
      "index": 0,
      "status": "inserted"
    },
    {
      "eventId": "90ef2161-...",
      "index": 1,
      "status": "duplicate"
    },
    {
      "error": "Stripe customer cus_missing is not imported into this project.",
      "index": 2,
      "status": "rejected"
    }
  ]
}
inserted
A new event committed. eventId is present and accepted increases by one.
duplicate
The project already has the same idempotency key. eventId is present; accepted and rejected do not increase.
rejected
The event was invalid, unresolved, or could not be saved. error explains the event-level failure.
200
At least one event was inserted, the batch was partially accepted, or every event was a duplicate. Always inspect results.
400
Invalid JSON, non-object body, or events is missing, empty, or larger than 100 items.
401
The bearer write key is missing, invalid, revoked, or inactive.
413
The request body or at least one serialized event exceeds its byte ceiling.
422
Every event failed validation or Stripe customer resolution.
429
The client-address or authenticated project abuse ceiling was reached. Honor Retry-After.
503
Ingest is temporarily unavailable, or every event was rejected and at least one rejection was a persistence failure.
A 503 response can be a small top-level { "error": "..." } object or the normal result envelope when every event was rejected and at least one rejection was a persistence failure. Treat both forms as retryable.

Limits, quotas, and retries

Events per request
1–100
Request body
8 MiB
Serialized event
64 KiB

Authenticated project abuse ceilings use fixed one-minute buckets. Submitted requests and event counts consume the bucket before per-event validation, so rejected rows still count.

Free
6,000 requests and 300,000 submitted events per minute.
Pro
30,000 requests and 2,000,000 submitted events per minute.
Enterprise
60,000 requests and 4,000,000 submitted events per minute, or a trusted explicit override.

A separate in-process client-address ceiling allows 20,000 requests per minute. It dampens obvious unauthenticated floods before project-level quota enforcement.

  • On 429, wait for the integer seconds in Retry-After.
  • Authenticated quota responses also include X-Traket-Ingest-Limit-Class.
  • Retry network failures, timeouts, 408, 429, and 5xx with bounded exponential jitter.
  • Preserve each event's idempotency key across every retry.

When idempotencyKey is omitted, SDKs assign one before delivery and the raw API derives a stable payload hash. Supplying a provider request or response ID is safer when the same logical event might be reconstructed differently.

GET provider catalog

The public Catalog endpoint returns the accepted provider IDs and the base OpenAI-family models that have local pricing. It is a pricing catalog, not a model allowlist.

No authentication required
GET https://traket.ai/api/v1/usage/catalog
Response shape · abridged provider and model arrays
{
  "modelCatalogVersion": "openai-text-2026-07-19",
  "providers": [
    {
      "id": "openai",
      "label": "OpenAI",
      "modelPolicy": "catalog",
      "notes": "Listed base models and their date-suffixed snapshots are priced locally; other unknown IDs are stored without an estimate.",
      "models": [
        "gpt-4.1",
        "gpt-4.1-mini",
        "gpt-4.1-nano"
      ]
    },
    {
      "id": "azure_openai",
      "label": "Azure OpenAI",
      "modelPolicy": "catalog",
      "notes": "Send the underlying OpenAI model, not only an Azure deployment name; listed bases and date-suffixed snapshots use local pricing.",
      "models": [
        "gpt-4.1",
        "gpt-4.1-mini",
        "gpt-4.1-nano"
      ]
    }
  ]
}

Current model catalog version: openai-text-2026-07-19.

openai
Listed base models and their date-suffixed snapshots are priced locally; other unknown IDs are stored without an estimate.
azure_openai
Send the underlying OpenAI model, not only an Azure deployment name; listed bases and date-suffixed snapshots use local pricing.
anthropic
Provider is allowed; model names are accepted as reported.
aws_bedrock
Provider is allowed; Bedrock model IDs are accepted as reported.
google_vertex
Provider is allowed; Vertex model IDs are accepted as reported.
mistral
Provider is allowed; model names are accepted as reported.
openrouter
Provider is allowed; routed model IDs are accepted as reported.
other
Use only when a supported provider does not fit yet.

Locally priced OpenAI-family models in this build:

gpt-4.1gpt-4.1-minigpt-4.1-nanogpt-4ogpt-4o-minigpt-5gpt-5-minigpt-5-nanogpt-5.1gpt-5.2gpt-5.3-codexgpt-5.4gpt-5.4-minigpt-5.4-nanogpt-5.4-progpt-5.5gpt-5.5-progpt-5.6gpt-5.6-lunagpt-5.6-solgpt-5.6-terrao1o1-minio1-proo3o3-minio3-proo4-mini
A listed model and its trailing YYYY-MM-DD snapshot variant use the same local price. Other unknown OpenAI and Azure OpenAI IDs are accepted and stored without an estimated cost.

Prompts are never collected

Traket never collects or stores prompts, messages, model outputs, or full provider request and response bodies. There is no prompt-capture mode. Only usage counts, costs, operational identifiers, and customer attribution are sent to Traket.

  • Never send prompts, messages, model output, files, images, tool arguments, full provider responses, or provider headers.
  • Never send API keys, authorization values, passwords, secrets, or tokens.
  • Metadata is limited to 24 scalar entries. Keys are trimmed to 64 characters and string values to 512 characters.
  • A direct API event is rejected when a metadata key resembles private content or credentials.
Prefer an SDK client when possible. It sanitizes suspicious metadata before delivery and gives transient failures bounded retry and queue restoration behavior.