Skip to content
GitHub
Decisions

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}/changesets

The 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:

ScopeDescription
read:workspaceRead workspace data (scans, changesets, traces)
write:workspaceCreate/update workspace data
approve:agentsAccept changesets, promote agent configs
admin:workspaceWorkspace settings, API keys, invites
admin:accountAccount-level management
read:agentsFetch agent configuration (API key)
write:tracesPush OTEL traces (API key)
read:operationsRead operations-level data (renamed from read:platform per ADR-039 D11)
write:operationsWrite operations-level data (renamed from write:platform per ADR-039 D11)

5. Roles

Workspace roles:

RoleScopes
adminread:workspace, write:workspace, approve:agents, admin:workspace, read:agents
contributorread:workspace, write:workspace, read:agents
observerread:workspace

Account roles:

RoleScopes
owneradmin:account + implicit admin-level workspace access
operationsAll scopes (Spectral staff)

6. Router Structure

20 modules organized by domain resource (v0.2 baseline; the post-rebuild API surface lives in apps/api/):

ModuleDescription
authLogin, register, logout, OAuth, password reset, profile
accountsAccount details, member management, invites
workspacesWorkspace CRUD, member management, autonomy settings, health
keysAPI key lifecycle
agentsAgent CRUD, configuration, templates
assistantTuning assistant chat, mode, history
scansScan lifecycle, schedules, analysis, reports, cost
changesetsChangeset lifecycle (accept, apply, reject, rollback)
changesets/clustersFailure cluster browsing and curation
changesets/experimentsExperiment tracking
changesets/validationHoldout validation runs
evaluations/rubricsRubric CRUD, generation, suggestions
evaluations/objectivesObjective function CRUD
tracesTrace browsing, feedback
samplesSample set management
dashboardControl plane, morning briefing, workflow overview
supervisorState, next-action, nightly-plan, frontier-report, failures
inferenceTemplate inference from scan context
operationsModel health, model config (platform-only)
otelOTLP 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