# RealWorld API Versioning Strategy: OpenAPI-Driven Semantic Versioning Without Path Prefixes

> Discover the RealWorld API versioning strategy: OpenAPI-driven semantic versioning without path prefixes, using version-agnostic endpoints for seamless updates.

- Repository: [Thinkster/realworld](https://github.com/gothinkster/realworld)
- Tags: best-practices
- Published: 2026-02-28

---

**The RealWorld API employs OpenAPI-driven semantic versioning without embedding version identifiers in URL paths, declaring version 2.0.0 in the specification file while maintaining version-agnostic `/api/` endpoints.**

The `gothinkster/realworld` repository serves as the reference implementation for full-stack application demos, and its **RealWorld API versioning strategy** deliberately avoids traditional URL path versioning. Instead, the project centralizes version control within the OpenAPI specification, enabling seamless contract evolution without breaking existing endpoint URLs.

## OpenAPI-Driven Versioning Without Path Prefixes

Unlike conventional REST APIs that embed version identifiers directly into URL paths (e.g., `/api/v1/users`), the RealWorld reference implementation keeps all routes version-agnostic. The entire API contract— including the version number— lives in the OpenAPI specification file at [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml).

According to the source code, the `info.version` field at line 11 of [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) is set to **`2.0.0`**【/cache/repos/github.com/gothinkster/realworld/main/specs/api/openapi.yml#L11】. This value represents the single source of truth for the API's current version, meaning **clients must reference the spec version rather than URL prefixes** to determine compatibility.

### Semantic Versioning in the Specification

The RealWorld API follows **semantic versioning** (MAJOR.MINOR.PATCH) as defined in the OpenAPI document:

- **Major version bumps** (e.g., 2.0.0 → 3.0.0) indicate breaking changes that require client updates
- **Minor and patch changes** (e.g., 2.0.0 → 2.1.0 or 2.0.1) represent backward-compatible additions or bug fixes
- Because routes never change, existing deployments continue functioning while new clients target updated specs

This approach allows the API contract to evolve independently of the endpoint URLs, ensuring that front-end implementations remain compatible with any back-end that conforms to their targeted spec version.

### Version-Agnostic Route Structure

All HTTP routes in the RealWorld API start with the prefix `/api/` regardless of the specification version. For example:

- `/api/user` returns the current user profile
- `/api/articles` lists recent articles
- `/api/profiles/:username` retrieves public profile data

The absence of version prefixes (like `v1` or `v2`) means **the URL structure remains permanently stable**. When the spec advances to 3.0.0, the endpoints stay at `/api/...`, but the schema contract defined in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) changes to reflect new requirements.

## Key Files Defining the Versioning Strategy

Several files in the repository confirm and reinforce this versioning approach:

- **[`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml)**: Contains the authoritative `info.version: 2.0.0` field and defines the complete API contract
- **[`specs/api/legacy_Conduit.postman_collection.json`](https://github.com/gothinkster/realworld/blob/main/specs/api/legacy_Conduit.postman_collection.json)**: Demonstrates the historical "Conduit" API collection, which also lacks versioned base paths, confirming the long-standing version-agnostic philosophy
- **[`specs/api/README.md`](https://github.com/gothinkster/realworld/blob/main/specs/api/README.md)**: Provides guidance for consumers on referencing the OpenAPI spec and understanding versioning semantics
- **[`README.md`](https://github.com/gothinkster/realworld/blob/main/README.md)** (repo root): States that front-ends can be swapped between back-ends because all implementations share the same API spec, reinforcing that versioning is tied to the specification document rather than deployment URLs

## Programmatically Detecting API Versions

Because the version lives in the YAML specification rather than the URL, clients must query the spec file directly to determine the current API contract version.

### Fetching the Current Spec Version

Use the raw GitHub URL to retrieve the OpenAPI file and parse the version line:

```javascript
import fetch from 'node-fetch';

async function getSpecVersion() {
  const resp = await fetch(
    'https://raw.githubusercontent.com/gothinkster/realworld/main/specs/api/openapi.yml'
  );
  const text = await resp.text();
  const versionLine = text.split('\n').find(l => l.trim().startsWith('version:'));
  console.log('API spec version →', versionLine.split(':')[1].trim());
}

getSpecVersion(); // prints “2.0.0”

```

### Calling Version-Agnostic Endpoints

Client requests never include version prefixes, regardless of which spec version the server implements:

```javascript
async function getCurrentUser(token) {
  const resp = await fetch('https://api.realworld.show/api/user', {
    headers: { Authorization: `Token ${token}` },
  });
  return resp.json(); // conforms to the schema described in the 2.0.0 spec
}

```

### Preparing for Major Version Updates

When the maintainers release a breaking change (hypothetical 3.0.0), update your client code to validate against the new schema while keeping the same base URL:

```javascript
// When the spec is bumped to 3.0.0, update the import URL:
const SPEC_URL = 'https://raw.githubusercontent.com/gothinkster/realworld/main/specs/api/openapi.yml';
// After the bump, SPEC_URL will return a file whose `version:` line reads “3.0.0”.

```

## Summary

- The RealWorld API uses **OpenAPI-driven semantic versioning** without URL path prefixes, making [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) the single source of truth
- Current version **2.0.0** follows MAJOR.MINOR.PATCH semantics, where breaking changes trigger major version increments
- All endpoints remain **version-agnostic** under `/api/`, requiring clients to track specification versions independently of deployment URLs
- The [`legacy_Conduit.postman_collection.json`](https://github.com/gothinkster/realworld/blob/main/legacy_Conduit.postman_collection.json) and root [`README.md`](https://github.com/gothinkster/realworld/blob/main/README.md) confirm that the versioning strategy prioritizes specification consistency over URL structure changes

## Frequently Asked Questions

### Does the RealWorld API use URL path versioning like /api/v1/?

No. According to the source code in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml), the RealWorld API intentionally avoids embedding version identifiers in URL paths. All routes start with `/api/` regardless of the specification version, making the strategy **"OpenAPI-driven semantic versioning without path versioning."**

### What is the current RealWorld API version?

The OpenAPI specification at [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) declares version **2.0.0** in the `info.version` field. This follows semantic versioning conventions where breaking changes would increment the major version to 3.0.0, while backward-compatible additions only modify the minor or patch components.

### How should client applications handle RealWorld API version changes?

Clients should reference the specific OpenAPI spec version they were built against. When the spec advances to a new major version (e.g., 3.0.0), developers must update their client libraries or front-end code to match the new schema, while existing deployments continue functioning against the same `/api/` endpoints.

### Where is the RealWorld API version defined in the codebase?

The single source of truth resides in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) at the `info.version` field. The [`specs/api/legacy_Conduit.postman_collection.json`](https://github.com/gothinkster/realworld/blob/main/specs/api/legacy_Conduit.postman_collection.json) file and root [`README.md`](https://github.com/gothinkster/realworld/blob/main/README.md) further confirm that the API contract is versioned through the specification document rather than URL paths.