api-version

This skill helps you manage API versions in apps/api/src/v1/ and prepare for future versions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "api-version" with this command: npx skills add sgcarstrends/sgcarstrends/sgcarstrends-sgcarstrends-api-version

API Versioning Skill

This skill helps you manage API versions in apps/api/src/v1/ and prepare for future versions.

When to Use This Skill

  • Creating a new API version (v2, v3, etc.)

  • Deprecating old API endpoints

  • Migrating endpoints between versions

  • Planning breaking changes

  • Maintaining backward compatibility

Current API Structure

apps/api/src/ ├── v1/ # Current API version │ ├── routes/ │ │ ├── cars.ts # Car registration endpoints │ │ ├── coe.ts # COE bidding endpoints │ │ ├── pqp.ts # PQP data endpoints │ │ └── health.ts # Health check │ └── index.ts # v1 router assembly └── index.ts # Main Hono app with versioned routes

Versioning Strategy

URL-Based Versioning

The project uses URL path versioning:

Benefits

  • Clear, explicit versioning visible in URLs

  • Easy to cache and monitor per version

  • Clients can migrate at their own pace

  • Multiple versions can coexist

Creating a New API Version

Step 1: Create Version Directory

mkdir -p apps/api/src/v2/routes

Step 2: Copy Existing Routes

Start with current v1 routes as a base:

cp -r apps/api/src/v1/routes/* apps/api/src/v2/routes/

Step 3: Create Version Router

Create apps/api/src/v2/index.ts :

import { Hono } from "hono"; import { carsRouter } from "./routes/cars"; import { coeRouter } from "./routes/coe"; import { pqpRouter } from "./routes/pqp";

const v2 = new Hono();

// Mount routes v2.route("/cars", carsRouter); v2.route("/coe", coeRouter); v2.route("/pqp", pqpRouter);

export default v2;

Step 4: Mount in Main App

Update apps/api/src/index.ts :

import { Hono } from "hono"; import v1 from "./v1"; import v2 from "./v2";

const app = new Hono();

// Mount API versions app.route("/v1", v1); app.route("/v2", v2); // Add new version

// Default to latest stable version app.route("/", v1); // Keep v1 as default or change to v2 when stable

export default app;

Step 5: Implement Breaking Changes

Make necessary changes in v2 routes:

// v1 response format { "success": true, "data": [...], "count": 10 }

// v2 response format (breaking change) { "data": [...], "meta": { "total": 10, "page": 1, "pageSize": 10 } }

Migration Patterns

  1. Gradual Migration

Keep both versions running:

// v1/routes/cars.ts - deprecated but maintained export const carsRouter = new Hono();

carsRouter.get("/", async (c) => { // Old logic return c.json({ success: true, data: await getCars(), }); });

// v2/routes/cars.ts - new implementation export const carsRouter = new Hono();

carsRouter.get("/", async (c) => { // New logic with pagination const { page = 1, limit = 10 } = c.req.query(); const result = await getCars({ page, limit });

return c.json({ data: result.items, meta: { total: result.total, page, pageSize: limit, }, }); });

  1. Feature Flag Pattern

Use feature flags to test changes:

import { Hono } from "hono";

export const carsRouter = new Hono();

carsRouter.get("/", async (c) => { const useV2Format = c.req.header("X-API-Version") === "2";

const data = await getCars();

if (useV2Format) { return c.json({ data, meta: { ... } }); }

// v1 format return c.json({ success: true, data }); });

  1. Deprecation Warnings

Add deprecation headers to v1:

import { Hono } from "hono";

export const carsRouter = new Hono();

// Add deprecation middleware carsRouter.use("*", async (c, next) => { await next(); c.header("X-API-Deprecation", "true"); c.header("X-API-Sunset", "2025-12-31"); c.header("Link", '<https://api.sgcarstrends.com/v2/cars>; rel="successor-version"'); });

carsRouter.get("/", async (c) => { // Existing logic });

Breaking Changes Checklist

When introducing breaking changes, consider:

  • Response structure changes

  • Required parameter additions

  • Authentication method changes

  • URL structure modifications

  • HTTP method changes

  • Header requirement changes

  • Error format modifications

  • Data type changes

Version Documentation

Document versions in OpenAPI/Swagger:

// apps/api/src/v2/openapi.ts import { OpenAPIHono } from "@hono/zod-openapi";

const app = new OpenAPIHono();

app.openapi( { method: "get", path: "/cars", summary: "Get car registrations (v2)", deprecated: false, tags: ["Cars"], responses: { 200: { description: "Success", content: { "application/json": { schema: carResponseSchema, }, }, }, }, }, async (c) => { // Handler } );

Version Sunset Process

  1. Announce Deprecation
  • Update documentation

  • Add deprecation headers

  • Notify API consumers

  • Set sunset date

  1. Monitor Usage

Track v1 usage metrics:

import { middleware } from "hono/middleware";

v1.use("*", async (c, next) => { // Log usage for monitoring console.log("v1 API usage:", { path: c.req.path, user: c.get("user")?.id, timestamp: new Date(), });

await next(); });

  1. Provide Migration Guide

Create migration documentation:

Migrating from v1 to v2

Breaking Changes

Response Format

v1: ```json { "success": true, "data": [...] } ```

v2: ```json { "data": [...], "meta": { ... } } ```

Pagination

v2 includes built-in pagination:

  • Query params: ?page=1&#x26;limit=10
  • Response includes meta with pagination info

Migration Steps

  1. Update base URL from /v1 to /v2

  2. Update response parsing to handle new format

  3. Add pagination parameters if needed

  4. Update error handling for new error format

  5. Remove Old Version

After sunset date:

Remove v1 directory

rm -rf apps/api/src/v1

Update main app

Remove v1 mounting from apps/api/src/index.ts

Testing Multiple Versions

Test all active versions:

Test v1

curl https://api.sgcarstrends.com/v1/cars

Test v2

curl https://api.sgcarstrends.com/v2/cars

Run version-specific tests

pnpm -F @sgcarstrends/api test -- src/v1 pnpm -F @sgcarstrends/api test -- src/v2

Deployment Considerations

Zero-Downtime Deployment

  • Deploy v2 alongside v1

  • Test v2 in production

  • Gradually route traffic to v2

  • Monitor error rates

  • Rollback if issues occur

Environment Variables

Version-specific config:

v1 settings

V1_RATE_LIMIT=100 V1_CACHE_TTL=300

v2 settings

V2_RATE_LIMIT=200 V2_CACHE_TTL=600

Common Scenarios

Scenario 1: Add Required Parameter

v1: Optional parameter

carsRouter.get("/", async (c) => { const make = c.req.query("make"); // optional return c.json(await getCars({ make })); });

v2: Required parameter (breaking change)

carsRouter.get("/", async (c) => { const make = c.req.query("make"); if (!make) { return c.json({ error: "make parameter required" }, 400); } return c.json(await getCars({ make })); });

Scenario 2: Change Data Format

v1: Flat structure

{ id: 1, make: "Toyota", model: "Camry" }

v2: Nested structure (breaking change)

{ id: 1, vehicle: { make: "Toyota", model: "Camry" } }

Scenario 3: Rename Endpoint

v1: /cars/list

v2: /cars (breaking change - URL structure)

Solution: Redirect in v1

v1.get("/cars/list", async (c) => { c.header("X-API-Deprecated", "true"); c.header("Location", "/v2/cars"); return c.redirect("/v2/cars", 301); });

References

  • Hono documentation: Use Context7 for latest docs

  • Related files:

  • apps/api/src/v1/

  • Current API version

  • apps/api/src/index.ts

  • Main app with version mounting

  • apps/api/CLAUDE.md

  • API service documentation

Best Practices

  • Semantic Versioning: Use v1, v2, v3 (not v1.1, v1.2)

  • Backward Compatibility: Maintain old versions during migration period

  • Documentation: Document all breaking changes clearly

  • Communication: Announce deprecations well in advance

  • Monitoring: Track usage of deprecated endpoints

  • Testing: Maintain tests for all active versions

  • Graceful Sunset: Provide sufficient migration time (6-12 months)

  • Error Messages: Help users migrate with clear error messages

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

framer-motion-animations

No summary provided by upstream source.

Repository SourceNeeds Review
General

shadcn-components

No summary provided by upstream source.

Repository SourceNeeds Review
General

api-testing

No summary provided by upstream source.

Repository SourceNeeds Review