API Key Authentication
API keys provide stateless authentication for scripts, CI/CD pipelines, and external integrations. Keys are passed via the X-API-Key HTTP header.
Key format: osprey_<64-hex-chars> (e.g., osprey_a1b2c3d4...). The 64-character hex suffix is a cryptographically random 32-byte value.
Security model:
- Keys are SHA-256 hashed before storage in the
api_key table. The raw key is returned only once at creation time and cannot be retrieved afterward.
- Each key has a
key_prefix (first 8 hex characters) stored in plaintext for identification in list views.
- Keys have an optional
expires_at timestamp. Expired keys are rejected at authentication time.
- The
last_used_at field is updated asynchronously (non-blocking) on each successful authentication to avoid adding latency to every request.
- API key CRUD is restricted to admin users. Each key carries a
role (admin, engineer, or operator), but effective authorization is capped at the owner's current role. Demoting an owner therefore immediately reduces every existing key's privileges; deactivating the owner rejects the key.
- Authenticated route groups apply a per-IP limiter before credential lookup as well as the normal post-authentication limiter, so invalid API keys cannot create an unbounded PostgreSQL lookup stream.
Usage:
GET /api/v1/devices?area_id=... HTTP/1.1
X-API-Key: osprey_a1b2c3d4e5f6...