Browse documentation→
Docs/Usage & balance
Reference

Usage & balance

Track inference consumption, understand how cost is calculated, and handle billing-related errors and retries correctly.

Usage endpoint

GEThttps://inferenceapi.wethinkdigital.solutions/v1/usage

Aggregate request and token usage for a time window, grouped by day or model.

FieldTypeDescription
fromRFC 3339Optional. Inclusive start of the reporting window. Defaults to 30 days ago.
toRFC 3339Optional. Inclusive end of the reporting window. Defaults to now.
curl "https://inferenceapi.wethinkdigital.solutions/v1/usage?from=2026-10-01T00:00:00Z&to=2026-11-01T00:00:00Z&group_by=day" \
  -H "Authorization: Bearer sk_live_xxxxxxxx"
usage-response.json
{
  "totals": {
    "requests": 1284,
    "inputTokens": 948201,
    "outputTokens": 312940,
    "costMicro": 18400200,
    "upstreamCostMicro": 0
  },
  "series": [
    {
      "bucket": "2026-10-01",
      "label": "2026-10-01",
      "requests": 98,
      "inputTokens": 70214,
      "outputTokens": 23880,
      "costMicro": 1384200
    }
  ],
  "byModel": [
    {
      "modelId": "model-pro",
      "modelName": "Model Pro",
      "requests": 912,
      "inputTokens": 688120,
      "outputTokens": 241000,
      "costMicro": 14200100,
      "upstreamCostMicro": 0
    }
  ]
}

Usage is eventually consistent for the current day. Historical windows are stable and can be cached on your side. Never infer your balance from locally accumulated usage — query the balance endpoint.

Balance endpoint

GEThttps://inferenceapi.wethinkdigital.solutions/v1/balance

Current available balance in micro-dollars, normalized to USD.

curl https://inferenceapi.wethinkdigital.solutions/v1/balance \
  -H "Authorization: Bearer sk_live_xxxxxxxx"
balance-response.json
{
  "balanceMicro": 18420000,
  "heldMicro": 0,
  "currency": "USD"
}

A balance check is advisory. Concurrency can change the balance between your check and the inference request. The authoritative check happens at request admission and returns 402 insufficient_credit when funds are not sufficient.

Cost semantics

Pricing is published per million tokens for each model. A request has separate input and output rates, and some models expose cached read or cache write rates.

ComponentUnitNotes
Input tokensper 1M tokensPrompt and context tokens processed by the model.
Output tokensper 1M tokensGenerated tokens, including streaming output.
Cached readper 1M tokensApplied only when the model reports cache support and a cached read occurs.
Cached writeper 1M tokensApplied only where the model supports cache writes.
cost-calculation
input_cost  = input_tokens  / 1_000_000 * input_rate
output_cost = output_tokens / 1_000_000 * output_rate
cost        = input_cost + output_cost (+ cached components where applicable)

Accounting uses integer micro-dollars (1 USD = 1,000,000 micro). The response usage object reports tokens; the console request ledger and usage API report the settled micro-dollar cost. Rounding is applied at the ledger boundary, not per event.

Prices can change

Model pricing is versioned and surfaced in the Models catalog. The rate that applies to a request is the rate in effect when the request is admitted. Read GET /v1/models at startup or with a short cache TTL for accurate cost estimates.

Errors & status codes

Errors always return JSON in a single envelope. Capture error.requestId in logs; never log the token.

error-envelope.json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after the indicated interval.",
    "requestId": "req_01J8Z9..."
  }
}
StatusCodeMeaning
400invalid_requestMalformed JSON, missing required field, or unsupported parameter.
401unauthorizedToken is missing, malformed, expired, or revoked.
402insufficient_creditAvailable balance cannot cover the maximum expected cost of the request.
403model_unavailableThe model is not activated for inference.
404model_not_foundThe requested model ID is not in the catalog.
409idempotency_conflictThe Idempotency-Key was already used for another request.
429rate_limitedA rate limit was exceeded. Honor the Retry-After header.
500internal_errorThe request could not be completed. Retry with backoff and report the requestId.

Retry guidance

  • Retry 429 and 500 with exponential backoff and jitter. Honor Retry-After when present.
  • Do not retry 400, 401, 402, or 404 without changing the request or credential.
  • For streaming requests, a connection can close after output begins. Treat partial output as consumed and reconcile using the usage ledger.

Rate limits

Limits are applied per token: authentication endpoints are limited per IP address and inference endpoints per account. When a limit is exceeded the API returns 429 with a Retry-After header (seconds):

rate-limit-response
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{"error":{"code":"rate_limited","message":"Too many requests. Please slow down.","requestId":"..."}}

Sudden bursts and concurrent streaming requests can hit limits sooner than a request-per-second budget alone suggests; design a queue for high concurrency.

Idempotency

Send an Idempotency-Key header (up to 128 characters: letters, digits, -, _, . or :) on a billable POST to make duplicate submissions detectable.

idempotent-request
curl https://inferenceapi.wethinkdigital.solutions/v1/chat/completions   -H "Authorization: Bearer sk_live_xxxxxxxx"   -H "Idempotency-Key: 3f7c60b1-8b2a-4fcb-bdb6-8a8e2d28f201"   -H "Content-Type: application/json"   -d '{
    "model": "model-pro",
    "messages": [{ "role": "user", "content": "Generate a release title." }]
  }'

Keys are scoped to your account. Reusing a key returns 409 idempotency_conflict and never charges a second time. The platform does not replay the original response, so use a new key for a deliberate retry and inspect the request history to confirm whether the first attempt completed.

Do not retry blind

Under a network failure you cannot know whether a request reached the API. Record the request ID and check the dashboard or /v1/usage before retrying a billable call.