API and MCP
Everything the dashboard shows is also readable by code: a JSON API and an MCP server, both scoped to your organization and both read-only. There is no prompt content to return; every answer is labels and numbers.
Authentication
| Credential | Where it comes from | Use it for |
|---|---|---|
API key mm_live_… | Settings → API & MCP → Create key (owners and admins) | scripts, CI, dashboards you build |
| Sign-in token | your MCP client signs you in through auth.metermark.ai | Claude Code, Cursor, claude.ai connectors |
| Browser session | being signed in to the dashboard | calling the API from the same browser |
Send Authorization: Bearer <key or token>. A key acts with the role of the person who created
it; if they leave the organization the key stops working.
Who sees what. Owners and admins read the whole organization. Members of a company
organization read organization- and team-level aggregates, but person-level detail only about
themselves: other people appear as teammate-N and their sessions are pseudonymised. Cohort
benchmarks never name anyone below the minimum group size. Individual accounts contain only their
owner, so nothing is hidden from them. Every read of someone else's person-level detail by an
owner, admin or API key — a person, their sessions, benchmarks centred on them, a question that
named them, an export — is written to the organization's access log (GET /audit); reading your
own data is not.
Read API
Base URL https://metermark.ai/api/v1. Every endpoint accepts ?period=7d|30d|90d or
?from=YYYY-MM-DD&to=YYYY-MM-DD.
| Endpoint | Returns |
|---|---|
GET /me | your user, organization, role, plan and this month's classification quota |
GET /overview | spend versus the previous period, sessions, people, spend by intent / vendor / model tier / project / work kind, the headline KPIs and cache economics |
GET /people | everyone in the period with spend, sessions, top intent and model, outcomes per hundred dollars, tools, last active |
GET /people/{email} | one person: rank and share, profile, spend breakdowns, practice habits, per-day timeline |
GET /sessions | the ledger, newest first; filters email, tool, intent, project, work, automated, from, to, cursor |
GET /sessions/{id} | every label and number for one session |
GET /benchmarks | per intent cohort, the top quartile by outcomes per dollar against the rest, and the habit with the widest gap; team, intent, email narrow it |
GET /thinking | delivered thinking per model and effort setting: thinking tokens per invocation and per turn (p50 / p75 / p90), the longest uninterrupted run, the share of invocations that did no thinking, how fragmented large turns are, the earlier and later half of the period side by side, whether that change survives counting every day, session, or project equally, how thinking scales with the amount of text a turn received, a smoothed daily trend, and the raw daily series; model, effort narrow it |
| `GET | POST /query` |
GET /taxonomy | the classification scheme: intents, work kinds, the practice rubric, tool names, and your organization's own label dimensions |
GET /taxonomy/schema | the label schema for editing: published dimensions and version, the draft (owners and admins), and label coverage over the last 90 days |
GET /audit | owners and admins: the access log — who read whose person-level detail, through which channel; limit, offset |
GET /export | everything you may see, as one streamed JSON document: sessions and usage_days in the shapes above; no period |
DELETE /me | an individual account deletes itself and everything in it (not for API keys; company organizations write to hi@metermark.ai) |
While an organization has no data yet, every answer carries a hint that says what to run.
Label schema and saved views
These write endpoints take a signed-in session or an API key acting as the person who created it.
| Endpoint | Does |
|---|---|
PUT /taxonomy/schema | owners and admins: replace the draft label schema, { "dimensions": [...] }. Each dimension has a key, name, description and up to 24 values; a value is placed by rules on session metadata (repo, project, branch, cwd, remote with equals, prefix, contains or glob) or by its description, which the classifier matches. A draft changes no session. |
DELETE /taxonomy/schema | owners and admins: discard the draft |
POST /taxonomy/publish | owners and admins: the draft becomes the next version, { "backfill_days": 0 | 30 | 90 }. Rule values re-label every stored session before it answers; described values are labelled as agents classify, re-labelling the backfill window where the logs are still on disk (counted against the classification quota) |
POST /taxonomy/suggest | owners and admins: draft one dimension from a sentence, { "description": "…" }, previewed against recent sessions; saves nothing. 30 an hour |
POST /corrections | correct one label on one session: field is intent, work_relatedness, or label:<dimension>; a corrected dimension survives every re-upload and re-label |
GET|POST|PATCH|DELETE /views | saved dashboard views: card layouts, never numbers. scope is me, team (members on the same roster team) or org; only the owner edits, and an org owner or admin may delete a shared one |
MCP server
Streamable HTTP at https://metermark.ai/api/mcp. Add it to Claude Code without a key and it
signs you in through the browser:
claude mcp add --transport http --callback-port 3118 metermark https://metermark.ai/api/mcp
The fixed callback port matters: the sign-in registers Claude Code with Metermark's identity provider under that exact loopback address. With a key instead:
claude mcp add --transport http metermark https://metermark.ai/api/mcp --header "Authorization: Bearer mm_live_…"
Tools, all read-only: get_overview, list_people, get_person, list_sessions, get_session,
query_benchmarks, get_thinking, ask, get_taxonomy. They return the same shapes as the endpoints above and
obey the same role rules.
Errors
JSON { "error": "<code>", "message": "…" } with the HTTP status. 401 unauthenticated,
403 forbidden (a person-level read outside your role), 404 not_found, 402 quota_exceeded
(free plan cap; the body includes quota and upgrade_url), 429 rate_limited.