Subcore AI Docs
Telemetry read API

Authentication

One bearer key, which resolves to one organization and carries the permissions that decide what it may read.

Every request carries a Subcore API key as a bearer token:

Authorization: Bearer sk_live_...

There is nothing else to send. No organization id, no tenant header, no signed request. The key resolves to exactly one organization, and that organization scopes every result.

What the key decides

A key carries a permissions object. Two of its fields govern reads.

permissions.telemetry

Must be exactly true for any of the read endpoints to answer. A key without it authenticates fine and is then refused with 403:

{
  "error": "This API key cannot read telemetry",
  "code": "FORBIDDEN",
  "timestamp": 1788566031707
}

Reading is stricter than writing. Ingestion accepts any truthy telemetry value, because that is the check it has always run; reading requires the literal true. A key that ships telemetry today is therefore not guaranteed to read it back. If a key ingests but gets a 403 on a read, this is why.

permissions.cores

Which agents the key may see.

ValueEffect
["*"]Every core in the organization. This is the default
Field absentEvery core in the organization
["support-agent", "sales-agent"]Only those two cores
[]No core is readable. Unscoped lists come back empty, naming a core is refused with 403, and a session or run you cannot reach is 404

A restricted key behaves differently depending on whether you name a core:

  • Asking for a core on its list — filtered to that core, as you would expect.
  • Asking for a core not on its list — refused with 403, not silently narrowed. An empty answer to "show me core b" would read as "core b had no traffic", which is a different and much worse thing to be told.
{
  "error": "This API key cannot read core \"billing-agent\"",
  "code": "FORBIDDEN",
  "timestamp": 1788566031707
}
  • Asking for nothing in particular — confined to its list.

permissions.cores only takes a coreSlug argument on the two endpoints that have one: /telemetry/sessions and /telemetry/events. The single-object endpoints (/telemetry/sessions/{sid} and /telemetry/runs/{runId}) have no core parameter, so a restricted key asking for an object outside its cores gets a 404, not a 403 — the object is simply not visible to it.

Status codes

CodeMeaning
401No Authorization header, or the key is invalid or expired
403The key is valid but lacks permissions.telemetry, or was refused a core outside permissions.cores
404No such session or run in this organization — or none this key may read

Both 401 bodies are distinct, which is useful when debugging a client:

{ "error": "Missing Authorization header", "code": "AUTHENTICATION_ERROR", "timestamp": 1788566031707 }
{ "error": "Invalid or expired API key", "code": "AUTHENTICATION_ERROR", "timestamp": 1788566031707 }

Checking a key

curl -i -H "Authorization: Bearer $SUBCORE_API_KEY" \
  "https://api.subcore.ai/telemetry/sessions?limit=1"

A 200 means the key authenticates and carries permissions.telemetry.

There is also a GET /telemetry/health endpoint, but read its answer carefully: it validates the key and then checks the ingest permission, not the read one. A 200 from it does not prove the key can read telemetry back. For that, call one of the read endpoints as above.

On this page