API keys and personal access tokens
You will learn stream ingest keys versus personal access tokens for REST and MCP.
Cordo uses two different secret types. Mixing them up is the most common auth mistake: ingest keys cannot query, and personal tokens cannot ship production logs.
Quick comparison
| Stream API key | Personal access token | |
|---|---|---|
| Format | lax_<prefix>_<secret> |
lxp_<prefix>_<secret> |
| Purpose | Ingest only | REST API + MCP (manage, query, views, agent tools) |
| Where in the app | Streams → API keys (selected stream) | Settings → API tokens |
| Create control | New API key | New token |
| Shown once | Yes | Yes |
| Lifetime | Required; standard 90-day default, with a deployment-configured maximum capped at one year | Optional expiry |
| Least privilege | One stream; optional native / OTLP / OpenSearch scopes and event ceiling | REST/MCP scopes plus optional stream allowlist |
| Rotation | Successor with 0–3600 second overlap | Successor with 0–3600 second overlap |
Stream API keys
Use these to send events into one stream.
- Native HTTP JSON: header
X-API-Key: lax_… - OpenSearch-compatible
_bulk: HTTP Basic — username ignored, password is the API key - OTLP Logs:
X-API-KeyorAuthorization: Bearer lax_…
Every new key expires. Keys can be restricted to only the ingest surfaces a collector uses and can carry a lower events-per-minute ceiling. The key table shows last use, expiry, rotation state, and stale/expiring/recent rate-limit warnings. Rotate before expiry with a safe overlap so collectors can switch without dropping logs.
Existing keys were given one bounded 90-day migration window when expiration shipped; rotate them to establish fresh lineage and settings.
Session JWTs from the web app cannot ingest. Expiry, overlap completion, or manual revocation stops authentication with that secret. These checks use the server database clock, not the collector clock.
Hands-on: Manage stream API keys.
Personal access tokens
Use these for scripts, Cursor, and other MCP clients.
- Header:
Authorization: Bearer lxp_… - Permissions: least-privilege scopes (or full access), optionally limited to selected streams you can already access
- Stream and saved-view inventories apply that limit before pagination, sidebar ordering, and name resolution, so hidden rows cannot change counts, cursors, or ambiguity candidates
- Stream limits follow indirect references too: a saved view can be created,
opened, previewed, or exported only when its home stream and every persisted
stream_idare in the token allowlist; Cordo never returns a partial result - Reading saved-view definitions uses
events:read; previewing or mutating a view, reading/changing its table layout, or changing sidebar order usesviews:write - Cannot call HTTP ingest endpoints (
/ingest, OpenSearch bulk, OTLP) — use a stream API key for production shippers; MCPingest_eventsneeds theevents:ingestscope - Cannot create, rotate, or broaden another PAT (interactive login required)
- Platform operators using PATs need
ops:read(or full access*) for/v1/ops/*; the scope is platform-wide but never grants operator status by itself
Existing tokens created before scopes shipped keep full access (*) so
agents keep working until you rotate them to narrower scopes.
Hands-on: Manage personal access tokens and Connect MCP.
Next
- Concepts: Streams and ingest
- Return to Concepts