Files
BanGUI/Docs/API_VERSIONING.md
Lukas cc6dbcf3f0 feat: implement API versioning /api/v1/
- All backend routers moved to /api/v1/ prefix
- Frontend BASE_URL updated to /api/v1
- Setup redirect middleware updated to redirect to /api/v1/setup
- Health router path fixed: prefix=/api/v1/health, @router.get('')
- conftest.py: set server_status=online for test fixture
- Created Docs/API_VERSIONING.md with deprecation policy
- Updated Docs/Backend-Development.md with versioning section
- Updated Instructions.md curl examples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-02 21:29:30 +02:00

3.8 KiB

API Versioning Strategy

Status: Active — Current version: v1

All BanGUI API endpoints are versioned using URI path versioning (e.g., /api/v1/). This document explains when and how to version endpoints, how deprecation works, and what guarantees consumers can rely on.


1. Version Lifecycle

Stage Meaning
Current Active, receiving new features and bug fixes.
Deprecated Still functional but marked for removal. Clients receive Deprecation: true and Sunset: <date> response headers.
Removed Endpoint no longer exists. Clients must migrate to a newer version.

2. URL Structure

/api/v{major}/<resource>/<path>
  • v1 — current version (2026-05-02)
  • v2 — reserved for future breaking changes
  • PATCH versions (v1.1, v1.2) are not used; only major version bumps indicate breaking changes
  • The OpenAPI schema is always available at /api/openapi.json regardless of version

3. What Triggers a Version Bump

A new major version is required when a breaking change must be introduced, including:

  • Removing or renaming a field in a response model
  • Changing the type of a request or response field
  • Removing an endpoint entirely
  • Changing authentication/authorization semantics
  • Modifying the semantics of an existing operation

Non-breaking changes (backward-compatible):

  • Adding new optional request fields
  • Adding new response fields
  • Adding new endpoints
  • Fixing bugs that caused incorrect behavior

These do not require a version bump.


4. Deprecation Policy

When an endpoint is deprecated:

  1. The endpoint remains functional for a minimum of 6 months from the Sunset date
  2. Response headers are added:
    Deprecation: true
    Sunset: <RFC-5322 date>
    Link: <https://bangui.example.com/api/v2/...>; rel="successor-version"
    
  3. The OpenAPI schema marks the endpoint with deprecated: true
  4. Documentation is updated to show the endpoint as deprecated

5. Backend Development: Adding Versioned Endpoints

New endpoints

All new endpoints are added to the current version (/api/v1/). Prefix your router:

router = APIRouter(prefix="/api/v1/my-resource", tags=["My Resource"])

Breaking changes requiring v2

  1. Create a new router file (e.g., routers/my_resource_v2.py) with the v2 prefix:
    router = APIRouter(prefix="/api/v2/my-resource", tags=["My Resource"])
    
  2. Copy or adapt the v1 handler logic as needed
  3. Register the new router in app/main.py:
    app.include_router(my_resource_v2.router)
    
  4. Add deprecation headers to the old v1 router by marking it deprecated in the OpenAPI spec
  5. Update this document to reflect the new version lifecycle

Keeping routers DRY

If v1 and v2 share logic, extract business logic into a service layer function and call it from both router handlers. Routers should only contain HTTP concerns (parameters, responses, status codes).


6. Frontend Development

The frontend always uses the current version's base URL:

const BASE_URL: string = import.meta.env.VITE_API_URL ?? "/api/v1";

All endpoint paths in frontend/src/api/endpoints.ts are defined as relative paths (e.g., /bans, /jails) and are appended to BASE_URL at runtime.


7. OpenAPI / Documentation

  • Swagger UI: /api/docs
  • ReDoc: /api/redoc
  • OpenAPI schema: /api/openapi.json
  • Docs are not versioned; they always reflect the current (latest) API version

8. Version History

Version Status Released Sunset Date Notes
v1 Current 2026-05-02 Initial versioning; all endpoints moved from /api/ to /api/v1/