HTTP API
Base URL, the two kinds of credential, error shape, and the ingest, log and read endpoints.
On this page
There are two credentials and they do different jobs. An ingest key writes runs for one project and environment. A personal access token reads your own data, as you, with the scopes you granted it. Neither can do the other's job.
- Base URL
https://api.tracehatch.com/api/v1- Ingest key
- Authorization: Bearer th_live_… / th_test_…
- Read token
- Authorization: Bearer th_pat_…
- Interactive reference
https://api.tracehatch.com/api/docs
The complete, always-current reference for all 100+ operations — parameters,
schemas and responses — is the OpenAPI document the API generates from its own
decorators. Open https://api.tracehatch.com/api/docs in the browser, or read the same document as
JSON at the /docs-json path beside it. This page covers the conventions and
the endpoints you are most likely to call by hand.
Writing: ingest
POST /ingest
The SDK's own endpoint. Wire format v1: an sdk block, optional traces[]
envelopes and 1–1,000 spans[], up to 5 MB decompressed, with
Content-Encoding: gzip accepted.
Spans are idempotent by id, so retrying a batch never double counts. 202 means
the batch is stored; processing is asynchronous.
Above the workspace's monthly allowance the response carries an advisory
sampling rate; at three times the allowance batches are rejected with
429 quota_exceeded and Retry-After.
POST /log
One JSON object per model call, for stacks without an SDK. Full documentation: Log endpoint.
Reading: personal access tokens
Create a token in Account → Tokens. The secret is returned once, in the response that creates it. A token acts as its owner: it can never reach a workspace you are not a member of, and your role still applies.
curl -sS "$TRACEHATCH_API/projects/proj_abc/traces?range=24h&limit=20" \
-H "Authorization: Bearer $TRACEHATCH_TOKEN"Set TRACEHATCH_API to https://api.tracehatch.com/api/v1 and TRACEHATCH_TOKEN to the secret you
saved when the token was created.
Tokens cannot mint or revoke tokens — that needs a signed-in session. Revoking takes effect on the next request that presents the token.
Scopes
admin implies every other scope.
| Scope | Reaches |
|---|---|
traces:read | Traces, spans, events, scores, saved views, share links, comments, tools, prompts, performance |
traces:write | Create and edit scores, saved views, share links and span comments |
sessions:read | Sessions, transcripts and end users |
metrics:read | Dashboard summary, timeseries, breakdown and recent panels |
costs:read | Cost summary, timeseries, breakdown and top traces |
projects:read | Projects, environments, agents and key metadata |
projects:write | Create, rename, re-slug, recolour and delete projects |
keys:write | Create and revoke ingest keys |
Some endpoints need more than one. Models and the Spans explorer need
traces:read and costs:read; the dashboard's recent panels need
metrics:read and traces:read; a user's runs need sessions:read and
traces:read. Grant admin if you would rather not track the combinations.
A token also carries your role and the workspace's plan: a viewer token cannot
write whatever its scopes say, and a Free workspace still answers
403 feature_not_available for a Pro surface.
Conventions
Ids
Prefixed and lexically sortable: run_01j9xk3m4np6q7r8s9t0v1w2x3, and likewise
span_, sess_, proj_, env_, ws_, usr_, key_, tok_, shr_,
scr_, eusr_.
Time ranges
Analytics endpoints take either a rolling range (1h, 24h, 7d, 30d)
or an explicit from/to pair — inclusive from, exclusive to, at most
90 days apart. They are mutually exclusive.
env selects one environment by id; omit it for all environments.
Pagination
Cursor-based. A list response is:
{
"data": [],
"next_cursor": "…",
"has_more": true
}Pass next_cursor back as cursor with the same filters. limit bounds the
page. Each table on a page cursors independently.
Errors
Every non-2xx response is RFC 9457 application/problem+json:
{
"type": "urn:tracehatch:problem:validation_failed",
"title": "Validation failed",
"status": 422,
"detail": "Supply from and to together.",
"code": "validation_failed",
"request_id": "req_01j9xk3m4np6q7r8s9t0v1w2x3",
"errors": [{ "path": "to", "message": "Required with from" }]
}Switch on code, not on the message. Quote request_id when reporting a
problem.
| Status | Codes |
|---|---|
401 | unauthenticated, key_revoked |
403 | forbidden, feature_not_available, plan_limit_reached |
404 | not_found |
409 | conflict, idempotency_mismatch |
412 | precondition_failed |
413 | payload_too_large |
422 | validation_failed, oauth_email_unverified, too_many_spans_for_bodies |
426 | sdk_upgrade_required |
429 | rate_limited, quota_exceeded, overloaded |
503 | kill_switch, upstream_unavailable |
500 | internal |
feature_not_available means the workspace's plan does not include the
capability — not that you lack permission. See
Plans, quotas and retention.
Endpoint families
| Family | What it reads |
|---|---|
/projects/{id}/traces | List, detail, spans, events; counts and summary refreshes |
/projects/{id}/traces/{traceId}/scores | Human feedback and SDK scores |
/projects/{id}/traces/{traceId}/share-links | Create and revoke public links |
/projects/{id}/traces/{traceId}/spans/{id}/annotations | Private span comments |
/projects/{id}/sessions, /users/{userId} | Sessions, transcripts, end users and their runs |
/projects/{id}/dashboard/* | Summary, timeseries, breakdown, recent traces and failures |
/projects/{id}/costs/* | Summary, timeseries, breakdown, most expensive traces |
/projects/{id}/models, /tools, /spans, /prompts | Analyze comparisons, details and samples |
/projects/{id}/performance/* | Latency percentiles and slowest runs |
/projects/{id}/api-keys, /environments, /agents | Project configuration |
/workspaces/{id}/* | Projects, members, invitations, usage and onboarding |
/me, /me/tokens, /me/preferences, /me/sessions | Your account |
/share/{token} | Public, redacted read of a shared trace. No credential. |
/health | Readiness: PostgreSQL, the ingestion worker and its backlog |
Health
GET /health reports readiness — the database, the ingestion worker and its
backlog. It needs no credential and is the right target for an uptime check.
Not available yet
Alerting and alert channels, outbound webhooks, service tokens for machine access separate from a person, data export, and per-project retention controls. The scope names exist in the codebase; the endpoints do not.