API Reference

Key Introspection

Look up what a key is allowed to record, without needing dashboard access.

GET /api/v1/keys/self

Returns metadata about the key making the request. Useful for confirming a key works and discovering what it is scoped to record.

Required scope: none — any valid key can introspect itself.


Request

curl https://app.trenchcoat.io/api/v1/keys/self \
  -H "X-API-Key: ct_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

Response — 200

{
  "data": {
    "key_prefix": "ct_live_a1b2",
    "name": "My MacBook",
    "scopes": ["read:full"],
    "rate_limit_tier": "ingestion",
    "expires_at": null
  },
  "meta": {
    "requestId": "req_msdf3l4f_lmjnos",
    "timestamp": "2026-01-15T10:30:00.000Z"
  }
}
FieldTypeDescription
key_prefixstringFirst 12 characters of the key, matching what the dashboard displays. Enough to identify which key this is.
namestringThe name you gave the key.
scopesstring[]The scopes as stored — see the caveat below.
rate_limit_tierstringstandard, premium, or ingestion.
expires_atstring | nullExpiry timestamp, or null if the key does not expire.

The response never contains the key itself, only its prefix.


Scopes are returned unexpanded

scopes lists what was stored when the key was created, not everything it effectively grants. A full-capture key returns exactly:

{ "scopes": ["read:full"] }

even though read:full implies read:prompts, read:events, and read:sessions.

If you are deciding what a key can do, expand the implications first:

Stored scopeAlso grants
read:fullread:prompts, read:events, read:sessions
read:promptsread:sessions
read:eventsread:sessions
admineverything

Reading scopes literally is a real source of bugs. A checker asking "does this key have read:prompts?" gets false for a read:full key, which is exactly backwards — that key has more access, not less.


Errors

401 — Invalid or missing key

Returned when the header is absent, or the key does not exist, is revoked, or has expired. Retrying will not help; issue a new key.

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid API key."
  }
}

Because this endpoint requires no scope, a 401 here means the key itself is bad — which makes it a clean way to distinguish "the key is rejected" from "the key lacks the scope this other endpoint needed."

On this page