Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
API versioning strategies — URL path, header, query param, content negotiation — with breaking change classification, deprecation timelines, migration patterns, and multi-version support. Use when evolving APIs, planning breaking changes, or managing version lifecycles.
API versioning strategies — URL path, header, query param, content negotiation — with breaking change classification, deprecation timelines, migration patterns, and multi-version support. Use when evolving APIs, planning breaking changes, or managing version lifecycles.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Evolve your API confidently. Version correctly, deprecate gracefully, migrate safely — without breaking existing consumers.
Pick one strategy and apply it consistently across your entire API surface. StrategyFormatVisibilityCacheabilityBest ForURL Path/api/v1/usersHighExcellentPublic APIs, third-party integrationsQuery Param/api/users?v=1MediumModerateSimple APIs, prototypingHeaderAccept-Version: v1LowGoodInternal APIs, coordinated consumersContent NegotiationAccept: application/vnd.api.v1+jsonLowGoodEnterprise, strict REST compliance
The most common strategy. Version lives in the URL, making it immediately visible. from fastapi import FastAPI, APIRouter v1 = APIRouter(prefix="/api/v1") v2 = APIRouter(prefix="/api/v2") @v1.get("/users") async def list_users_v1(): return {"users": [...]} @v2.get("/users") async def list_users_v2(): return {"data": {"users": [...]}, "meta": {...}} app = FastAPI() app.include_router(v1) app.include_router(v2) Rules: Always prefix: /api/v1/... not /v1/api/... Major version only: /api/v1/, never /api/v1.2/ or /api/v1.2.3/ Every endpoint must be versioned — no mixing versioned and unversioned paths
Version specified via request headers, keeping URLs clean. function versionRouter(req, res, next) { const version = req.headers['accept-version'] || 'v2'; // default to latest req.apiVersion = version; next(); } app.get('/api/users', versionRouter, (req, res) => { if (req.apiVersion === 'v1') return res.json({ users: [...] }); if (req.apiVersion === 'v2') return res.json({ data: { users: [...] }, meta: {} }); return res.status(400).json({ error: `Unsupported version: ${req.apiVersion}` }); }); Always define fallback behavior when no version header is sent — default to latest stable or return 400 Bad Request.
SemVer ComponentAPI MeaningAction RequiredMAJOR (v1 → v2)Breaking changes — remove field, rename endpoint, change authClients must migrateMINOR (v1.1 → v1.2)Additive, backward-compatible — new optional field, new endpointNo client changesPATCH (v1.1.0 → v1.1.1)Bug fixes, no behavior changeNo client changes Only MAJOR versions appear in URL paths. Communicate MINOR and PATCH through changelogs.
ChangeWhy It BreaksRemove a response fieldClients reading that field get undefinedRename a fieldSame as removal from the client's perspectiveChange a field's type"id": 123 → "id": "123" breaks typed clientsRemove an endpointClients calling it get 404Make optional param requiredExisting requests missing it start failingChange URL structureBookmarked/hardcoded URLs breakChange error response formatClient error-handling logic breaksChange authentication mechanismExisting credentials stop working
ChangeWhy It's SafeAdd new optional response fieldClients ignore unknown fieldsAdd new endpointDoesn't affect existing endpointsAdd new optional query/body paramExisting requests work without itAdd new enum valueSafe if clients handle unknown values gracefullyRelax a validation constraintPreviously valid requests remain validImprove performanceSame interface, faster response
Never remove a version without warning. Follow this timeline: Phase 1: ANNOUNCE • Sunset header on responses • Changelog entry • Email/webhook to consumers • Docs marked "deprecated" Phase 2: SUNSET PERIOD • v1 still works but warns • Monitor v1 traffic • Contact remaining consumers • Provide migration support Phase 3: REMOVAL • v1 returns 410 Gone • Response body includes migration guide URL • Redirect docs to v2 Minimum deprecation periods: Public API: 12 months · Partner API: 6 months · Internal API: 1–3 months
Include on every response from a deprecated version: HTTP/1.1 200 OK Sunset: Sat, 01 Mar 2025 00:00:00 GMT Deprecation: true Link: <https://api.example.com/docs/migrate-v1-v2>; rel="sunset" X-API-Warn: "v1 is deprecated. Migrate to v2 by 2025-03-01."
When past sunset, return 410 Gone: { "error": "VersionRetired", "message": "API v1 was retired on 2025-03-01.", "migration_guide": "https://api.example.com/docs/migrate-v1-v2", "current_version": "v2" }
Shared business logic, version-specific serialization: class UserService: async def get_user(self, user_id: str) -> User: return await self.repo.find(user_id) def to_v1(user: User) -> dict: return {"id": user.id, "name": user.full_name, "email": user.email} def to_v2(user: User) -> dict: return { "id": user.id, "name": {"first": user.first_name, "last": user.last_name}, "emails": [{"address": e, "primary": i == 0} for i, e in enumerate(user.emails)], "created_at": user.created_at.isoformat(), }
Single entry point delegates to the correct versioned handler: async def get_user(user_id: str, version: int): user = await user_service.get_user(user_id) serializers = {1: to_v1, 2: to_v2} serialize = serializers.get(version) if not serialize: raise UnsupportedVersionError(version) return serialize(user)
Separate controller files per version, shared service layer: api/ v1/ users.py # v1 request/response shapes orders.py v2/ users.py # v2 request/response shapes orders.py services/ user_service.py # version-agnostic business logic order_service.py
Route versions at infrastructure layer: routes: - match: /api/v1/* upstream: api-v1-service:8080 - match: /api/v2/* upstream: api-v2-service:8080
Architecture: Request → API Gateway → Version Router → v1 Handler → Shared Service Layer → DB → v2 Handler ↗ Principles: Business logic is version-agnostic. Services, repositories, and domain models are shared. Serialization is version-specific. Each version has its own request validators and response serializers. Transformations are explicit. A v1_to_v2 transformer documents every field mapping. Tests cover all active versions. Every supported version has its own integration test suite. Maximum concurrent versions: 2–3 active (current + 1–2 deprecated). More than 3 creates unsustainable maintenance burden.
For every major version bump, provide: Field-by-field mapping table (v1 → v2) Before/after request and response examples Code snippets for common languages/SDKs Timeline with key dates (announcement, sunset, removal)
Align SDK major versions with API major versions: api-client@1.x → /api/v1 api-client@2.x → /api/v2 Ship the new SDK before announcing API deprecation.
Anti-PatternFixVersioning too frequentlyBatch breaking changes into infrequent major releasesBreaking without noticeAlways follow the deprecation timelineEternal version supportSet and enforce sunset datesInconsistent versioningOne version scheme, applied uniformlyVersion per endpointVersion the entire API surface togetherUsing versions to gate featuresUse feature flags separately; versions are for contractsNo default versionAlways define a default or return explicit 400
NEVER remove a field, endpoint, or change a type without bumping the major version NEVER sunset a public API version with less than 6 months notice NEVER mix versioning strategies in the same API (URL path for some, headers for others) NEVER use minor or patch versions in URL paths (/api/v1.2/ is wrong — use /api/v1/) NEVER version individual endpoints independently — version the entire API surface as a unit NEVER deploy a breaking change under an existing version number, even if "nobody uses that field" NEVER skip documenting differences between versions — every breaking change needs a migration guide entry
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.