Skip to content
mordn
Esc
↑↓navigate↵open⌘Jpreview
On this page

Usage & Analytics API

The current hosted usage endpoints, filters, response envelopes, and server-only authentication model.

The hosted API records per-turn token and cost data. These endpoints are served by @mordn/chat-api, not by your Next.js handler, and require a server-side mordn API key.

curl "https://api.mordn.com/v1/usage/summary?view=production" \
  -H "Authorization: Bearer $MORDN_CHAT_KEY"

Window and filters

The default window is the last 14 days. from is inclusive and to is exclusive. Both are ISO timestamps. view is production, preview, or all (the default).

Filters differ by endpoint:

Endpoint Additional filters
summary userId, model, view
timeseries `bucket=day
by-model userId, view
by-user limit, model, view
top-conversations limit, `sort=cost
unanswered optional consistency-check agentId

Endpoints

GET /v1/usage/summary

{
  "totals": {
    "events": 12840,
    "inputTokens": 8340221,
    "outputTokens": 2114880,
    "totalTokens": 10455101,
    "cachedInputTokens": 512000,
    "cacheReadTokens": 0,
    "cacheWriteTokens": 0,
    "costUsd": "42.1187",
    "inputCostUsd": "30.0000",
    "outputCostUsd": "12.1187",
    "marketCostUsd": "40.0000",
    "surchargeUsd": "2.1187"
  }
}

GET /v1/usage/timeseries?bucket=day

{
  "series": [
    {
      "ts": "2026-06-30T00:00:00.000Z",
      "events": 502,
      "inputTokens": 320000,
      "outputTokens": 90233,
      "totalTokens": 410233,
      "costUsd": "1.6644"
    }
  ]
}

GET /v1/usage/by-model

Returns { models: [{ model, events, totalTokens, costUsd }] } ordered by cost.

GET /v1/usage/by-user

Returns { users: [{ userId, events, totalTokens, costUsd }] }.

GET /v1/usage/top-conversations

Returns { conversations: [{ conversationId, events, totalTokens, costUsd }] }. The aggregate does not include userId.

GET /v1/usage/unanswered

Returns recent retrieval misses grouped by normalized query:

{
  "questions": [
    {
      "query": "How do I rotate a key?",
      "count": 7,
      "lastAskedAt": "2026-07-14T08:00:00.000Z",
      "avgTopScore": 0.08
    }
  ]
}

An optional agentId must match the key’s agent or the API returns 403. Because this endpoint returns end-user query text, apply the same access and retention controls as other analytics data.

Per-turn record

UsageRecord can also carry resolvedProvider, finish reason, step count, latency, generation id, exact decimal cost strings, and raw?: Record<string, unknown> provider metadata. Not every field is exposed by every aggregate endpoint.

For a self-hosted backend, use onChatFinish or persist SaveTurnInput.usage in your own store.