ADR-006: API Versioning Strategy and RESTful Conventions
ADR-006: API Versioning Strategy and RESTful Conventions
Status: Accepted Date: 2026-04-01 Context: Pre-launch API refactor — no external customers, all breaking changes safe.
Context
The Spectral API had no consistent versioning strategy. Routes were a mix of unversioned (/api/scans, /api/auth), legacy versioned (/api/v2/objective-functions, /api/v2/anti-deception/check), and OTLP standard (/otel/v1/traces). Workspace isolation was inconsistent: 19% of endpoints used workspace_id in the URL path while 81% derived it from the X-Workspace-Id header. Response envelopes varied across endpoints. 31 router files had overlapping concerns.
Decision
1. URL Path Versioning: /api/v1/
All API routes are prefixed with /api/v1/. This provides:
- Clear version boundary for breaking changes
- Forward-compatible path for
/api/v2/when needed - No ambiguity about which version a client is targeting
Exception: The OTLP ingestion endpoint stays at /otel/v1/traces per the OpenTelemetry standard.
Auth routes live under /api/v1/auth/. Legacy auth proxy routes (/api/auth/{path:path}) forward to Supabase and will be removed once all clients migrate.
Version bump policy: breaking response shape changes, removed fields, changed semantics. Deprecation via Sunset header + 90-day window.
2. Workspace ID in URL Path
All workspace-scoped endpoints include workspace_id in the URL:
/api/v1/workspaces/{workspace_id}/scans/api/v1/workspaces/{workspace_id}/agents/api/v1/workspaces/{workspace_id}/changesetsThe X-Workspace-Id header is still required for auth middleware validation but the URL path is the authoritative source for workspace context. This makes URLs self-describing and enables better caching, logging, and debugging.
Non-workspace routes (auth, account, health, operations, OTEL) remain at /api/v1/ without a workspace segment.
3. Response Envelope
- Collections:
{"results": [...], "pagination": {"total": N, "limit": N, "offset": N}} - Single items: flat object (no wrapper)
- Errors: RFC 9457 Problem Details
4. Scope Model: action:resource
9 scopes:
| Scope | Description |
|---|---|
read:workspace | Read workspace data (scans, changesets, traces) |
write:workspace | Create/update workspace data |
approve:agents | Accept changesets, promote agent configs |
admin:workspace | Workspace settings, API keys, invites |
admin:account | Account-level management |
read:agents | Fetch agent configuration (API key) |
write:traces | Push OTEL traces (API key) |
read:operations | Read operations-level data (renamed from read:platform per ADR-039 D11) |
write:operations | Write operations-level data (renamed from write:platform per ADR-039 D11) |
5. Roles
Workspace roles:
| Role | Scopes |
|---|---|
admin | read:workspace, write:workspace, approve:agents, admin:workspace, read:agents |
contributor | read:workspace, write:workspace, read:agents |
observer | read:workspace |
Account roles:
| Role | Scopes |
|---|---|
owner | admin:account + implicit admin-level workspace access |
operations | All scopes (Spectral staff) |
6. Router Structure
20 modules organized by domain resource (v0.2 baseline; the post-rebuild API surface lives in apps/api/):
| Module | Description |
|---|---|
auth | Login, register, logout, OAuth, password reset, profile |
accounts | Account details, member management, invites |
workspaces | Workspace CRUD, member management, autonomy settings, health |
keys | API key lifecycle |
agents | Agent CRUD, configuration, templates |
assistant | Tuning assistant chat, mode, history |
scans | Scan lifecycle, schedules, analysis, reports, cost |
changesets | Changeset lifecycle (accept, apply, reject, rollback) |
changesets/clusters | Failure cluster browsing and curation |
changesets/experiments | Experiment tracking |
changesets/validation | Holdout validation runs |
evaluations/rubrics | Rubric CRUD, generation, suggestions |
evaluations/objectives | Objective function CRUD |
traces | Trace browsing, feedback |
samples | Sample set management |
dashboard | Control plane, morning briefing, workflow overview |
supervisor | State, next-action, nightly-plan, frontier-report, failures |
inference | Template inference from scan context |
operations | Model health, model config (platform-only) |
otel | OTLP trace ingestion, stats |
Sub-modules for complex resources: changesets/clusters, changesets/experiments, changesets/validation, evaluations/rubrics, evaluations/objectives.
7. Legacy Endpoint Removal
All /api/v2/* endpoints removed. Deprecated aliases (/api/scan, /api/run, /api/evaluate) also removed. Legacy auth proxy routes (/api/auth/) coexist temporarily during migration to /api/v1/auth/.
Consequences
Positive
- All routes consistently versioned — clear contract for API consumers
- Workspace isolation enforced at URL level — no more header-only isolation
- Response envelope standardized — clients can rely on consistent structure
- Router consolidation reduces cognitive overhead and import chains
- Clean foundation for future
/api/v2/when breaking changes are needed
Negative
- Breaking change for all existing API consumers (dashboard must update)
- Test suite requires updates to new paths
- OTEL ingestion endpoint path diverges from API versioning (by design, per OTLP standard)
- Legacy auth proxy routes coexist temporarily during migration