API Documentation: OpenAPI vs AsyncAPI 2026
API Documentation: OpenAPI vs AsyncAPI 2026
Great API documentation is the difference between a 5-minute integration and a 5-hour one. The two dominant standards — OpenAPI for REST APIs and AsyncAPI for event-driven APIs — provide machine-readable specifications that power code generation, testing, and interactive documentation.
TL;DR
- Every REST API should have an OpenAPI 3.1 spec — it's the source of truth for contracts, SDK generation, and interactive docs
- AsyncAPI covers what OpenAPI can't: WebSockets, Kafka, MQTT, SSE streams, and webhook schemas
- TypeSpec (from Microsoft) is the emerging alternative for large API teams who want to generate OpenAPI from code instead of writing YAML
- Spectral linting + Redocly bundling + Scalar UI is the modern open-source documentation stack
- "Docs as code" — spec in Git, CI validation, auto-deploy — is table stakes for any API team shipping continuously
- Breaking change detection with oasdiff in CI prevents accidental contract violations before they reach production
OpenAPI 3.1
What: The standard specification for describing REST APIs. Previously called Swagger.
Format: YAML or JSON file describing endpoints, request/response schemas, authentication, and examples.
What it covers:
- Endpoints (paths, methods)
- Request/response schemas (JSON Schema)
- Authentication methods
- Parameters (query, path, header, cookie)
- Request bodies
- Response codes and shapes
- Examples
Tools powered by OpenAPI:
- Swagger UI / Redoc — interactive documentation
- openapi-generator — SDK generation in 50+ languages
- Postman — import spec, auto-create collection
- Prism — mock server from spec
- Spectral — lint/validate specs
OpenAPI 3.1 improvements (over 3.0):
- Full JSON Schema compatibility
webhookssection for webhook definitionspathItemsfor reusable path definitions- Better
oneOf/anyOf/allOfsupport
When to Use OpenAPI
Always. Every REST API should have an OpenAPI spec. It's the source of truth for your API contract and powers the entire tooling ecosystem.
AsyncAPI
What: The standard specification for describing event-driven APIs — WebSockets, MQTT, Kafka, AMQP, SSE, webhooks.
Format: YAML or JSON file describing channels, messages, schemas, and protocols.
What it covers:
- Channels (topics, queues, WebSocket endpoints)
- Messages (publish/subscribe)
- Message schemas
- Protocol bindings (Kafka, MQTT, WebSocket, HTTP)
- Servers (brokers, endpoints)
Tools powered by AsyncAPI:
- AsyncAPI Studio — visual editor
- AsyncAPI Generator — code generation
- AsyncAPI Bundler — combine specs
- Documentation generators — HTML docs from spec
When to Use AsyncAPI
When your API uses event-driven patterns: WebSocket APIs, message brokers (Kafka, RabbitMQ), webhook definitions, or SSE streams.
Comparison
| Feature | OpenAPI 3.1 | AsyncAPI 3.0 |
|---|---|---|
| API type | REST (request-response) | Event-driven (pub/sub, streaming) |
| Protocols | HTTP/HTTPS | WebSocket, Kafka, MQTT, AMQP, HTTP |
| Direction | Client → Server → Client | Bidirectional, async |
| Maturity | Very mature | Growing |
| Tooling | Extensive | Growing |
| Adoption | Industry standard | Emerging standard |
They complement each other. If your API has REST endpoints AND WebSocket channels, use both specs.
Documentation Best Practices
1. Start With a Quick Start
The first thing developers see should be a working example in 5 lines:
## Quick Start
Install the SDK:
npm install your-api
Make your first request:
Three steps: install, authenticate, make a call. Nothing else on the quick start page.
2. Show Real Examples, Not Schemas
Developers copy code, not read schemas. Every endpoint needs a complete, runnable example with a real response.
3. Interactive "Try It" Console
Let developers make API calls from the documentation page. Swagger UI, Redoc, and ReadMe all support this. Seeing a real response builds confidence faster than reading a schema.
4. Error Documentation
Document every error code your API can return, with:
- The error code
- When it occurs
- How to fix it
- An example response
5. Changelog
Maintain a changelog of API changes. Developers need to know when fields are added, deprecated, or removed.
6. SDKs and Code Examples in Multiple Languages
Show code examples in at least: cURL, JavaScript, Python. Ideally also: Go, Ruby, Java.
7. Authentication Guide
A dedicated page explaining:
- How to get API keys
- Where to find them in the dashboard
- How to include them in requests
- Common authentication errors
Documentation Platforms
| Platform | Best For | Pricing |
|---|---|---|
| ReadMe | Interactive docs with "Try It" | Free (1 project) |
| Redocly | Beautiful OpenAPI docs | Free (basic) |
| Mintlify | Modern, developer-focused | $150/mo |
| Swagger UI | Self-hosted, free | Free (open source) |
| GitBook | Markdown-based docs | Free (personal) |
| Stoplight | API design + docs | Free (basic) |
Writing an OpenAPI Spec: A Practical Example
Most developers have seen basic OpenAPI snippets but never a complete spec that covers the realistic patterns. Here's an annotated example for a simple user management endpoint:
openapi: 3.1.0
info:
title: User Management API
version: 1.0.0
description: Manage users and their profiles.
servers:
- url: https://api.example.com/v1
description: Production
- url: https://sandbox.api.example.com/v1
description: Sandbox
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
schemas:
User:
type: object
required: [id, name, email, createdAt]
properties:
id:
type: string
format: uuid
example: "usr_abc123"
readOnly: true
name:
type: string
minLength: 1
maxLength: 100
example: "Alice Chen"
email:
type: string
format: email
example: "alice@example.com"
createdAt:
type: string
format: date-time
readOnly: true
CreateUserRequest:
type: object
required: [name, email]
properties:
name:
type: string
minLength: 1
maxLength: 100
email:
type: string
format: email
Error:
type: object
required: [code, message]
properties:
code:
type: string
example: "validation_error"
message:
type: string
example: "Email address is already in use"
details:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
PaginatedUsers:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
type: object
properties:
cursor:
type: string
nullable: true
hasMore:
type: boolean
security:
- BearerAuth: []
paths:
/users:
get:
operationId: listUsers
summary: List users
tags: [Users]
parameters:
- name: cursor
in: query
schema:
type: string
description: Pagination cursor from previous response
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: Paginated list of users
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedUsers'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
operationId: createUser
summary: Create a user
tags: [Users]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
example:
name: "Alice Chen"
email: "alice@example.com"
responses:
'201':
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Email already exists
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Key patterns to notice: readOnly: true on computed fields (id, createdAt), separate CreateUserRequest schema from User response schema, operationId on every operation (required for code generation), and examples at both the schema level and request body level.
OpenAPI Toolchain
Spectral: Linting Your Spec
Spectral validates OpenAPI specs against a set of rules. The built-in ruleset catches common mistakes; custom rules enforce your API style guide:
# .spectral.yaml
extends: ["spectral:oas"]
rules:
# Require operationId on all operations
operation-operationId: error
# Require examples on all response schemas
response-examples:
given: $.paths[*][*].responses[*].content[*].schema
then:
field: example
function: defined
severity: warn
# Require descriptions on all properties
property-description:
given: $.components.schemas[*].properties[*]
then:
field: description
function: defined
severity: warn
Run Spectral in CI to catch spec violations before merge:
npx @stoplight/spectral-cli lint api.yaml --ruleset .spectral.yaml
Redocly: Multi-File Spec Management
Real API specs grow large — hundreds of paths, dozens of schemas. Redocly bundles multi-file specs into a single deployable file:
# redocly.yaml
apis:
main:
root: openapi/main.yaml
# openapi/main.yaml can $ref to:
# openapi/paths/users.yaml
# openapi/schemas/user.yaml
# etc.
Split your spec into manageable files organized by resource. redocly bundle produces a single file for tools that require it; redocly lint validates across the split files.
Scalar: The Modern Documentation UI
Scalar is the best free alternative to Swagger UI in 2026. It's faster, more attractive, and supports modern OpenAPI features that Swagger UI struggles with. Drop-in replacement for most setups:
<!DOCTYPE html>
<html>
<head>
<title>API Reference</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<script
id="api-reference"
data-url="/openapi.yaml"
></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
Scalar supports the "Try It" console, authentication, multiple spec files, and dark mode. It's actively maintained with frequent releases.
TypeSpec: Microsoft's API Description Language
TypeSpec is Microsoft's answer to the "writing OpenAPI YAML by hand is painful" problem. It's a TypeScript-like language that compiles to OpenAPI (and other formats). Azure's entire API surface is defined in TypeSpec.
import "@typespec/http";
using TypeSpec.Http;
@service({ title: "User API" })
@server("https://api.example.com/v1", "Production")
namespace UserAPI;
model User {
@key id: string;
name: string;
@format("email") email: string;
@visibility("read") createdAt: utcDateTime;
}
@route("/users")
interface Users {
@get list(): User[];
@post create(@body user: OmitProperties<User, "id" | "createdAt">): User;
@get read(@path id: string): User | NotFoundResponse;
@patch update(@path id: string, @body patch: UpdateableProperties<User>): User;
@delete remove(@path id: string): void;
}
TypeSpec generates a valid OpenAPI 3.0/3.1 spec from this definition. The advantages:
- No writing YAML by hand — TypeSpec is type-checked
- Reusable model definitions with TypeScript-style generics (
OmitProperties<User, ...>) - Single source generates OpenAPI, JSON Schema, and potentially gRPC proto files
- Better diff and merge behavior than YAML (TypeScript-style syntax is more conflict-friendly)
TypeSpec is currently most useful for large API teams managing complex surfaces. The tooling is mature but the learning curve is steeper than writing OpenAPI directly. Watch this space — it's likely to become the standard for enterprise API teams in 2026-2027.
Developer Portal Strategy
docs.company.com Setup
Your developer documentation should live on a memorable, stable subdomain. docs.yourapi.com or developers.yourcompany.com are standard. Avoid paths like yourcompany.com/api/docs — hard to bookmark, mixed with marketing content.
ReadMe vs Mintlify vs Self-Hosted
ReadMe is the most feature-rich commercial platform. It includes a "Try It" console, versioned documentation, API metrics (which endpoints developers test), and a changelog. The developer experience for consumers is excellent. Cost: from $99/month.
Mintlify targets modern developer tools companies with a cleaner aesthetic and MDX-based content. The navigation, search, and code blocks are polished. Cost: $150/month. Mintlify's template system means your docs look professional without design work.
Self-hosted with Redocly or Scalar: Free, full control, works as a static site. Deploy to Vercel or Netlify. Best choice for teams that want to own their docs infrastructure and integrate tightly with their CI pipeline.
Versioned Documentation
When you release API v2, you need to maintain documentation for both v1 and v2. Most platforms support versioned docs with a version selector. Key decisions:
- Keep v1 docs available but clearly mark them as legacy
- Redirect new users to the latest version by default
- Include migration guides when breaking changes require action
For API version management strategy, see how to version REST APIs and API breaking changes without breaking clients.
Docs as Code
Treating documentation as code — spec in Git, CI validation, automated deployment — is how serious API teams prevent documentation drift.
OpenAPI Spec in Git
Keep your OpenAPI spec in the same repository as your API code. When a developer changes an endpoint, they update the spec in the same PR. Code review catches spec changes that don't match implementation.
Structure that works:
api/
openapi/
main.yaml # Entry point
paths/
users.yaml
orders.yaml
schemas/
user.yaml
order.yaml
CI Validation with Spectral
Every PR that changes the spec runs Spectral validation:
# .github/workflows/api-spec.yml
name: Validate API Spec
on:
pull_request:
paths:
- 'api/openapi/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g @stoplight/spectral-cli
- run: spectral lint api/openapi/main.yaml
Breaking Change Detection with oasdiff
oasdiff compares two OpenAPI specs and reports breaking changes. Run it in CI to catch regressions before they ship:
# Install
brew install oasdiff # or go install github.com/tufin/oasdiff@latest
# Compare current spec against main branch
oasdiff breaking api/openapi/main.yaml https://raw.githubusercontent.com/org/repo/main/api/openapi/main.yaml
Breaking changes detected by oasdiff:
- Removed endpoints
- Removed required request parameters
- Added required request parameters (breaks existing callers)
- Changed response field types
- Removed response fields that were previously present
Make oasdiff failures block merges. A non-zero exit code means a breaking change was introduced — either document it properly or rethink the approach.
Auto-Deploy Docs on Spec Change
When the spec file changes, deploy updated documentation automatically:
- name: Deploy docs
if: github.ref == 'refs/heads/main'
run: |
redocly bundle api/openapi/main.yaml --output dist/openapi.yaml
# Deploy dist/openapi.yaml to your docs platform
This keeps documentation permanently in sync with the spec. Manual doc deploys that lag behind API releases are a common source of developer frustration.
For SDK generation from your spec, see how to build an API SDK. For testing your API against the spec, see API testing strategies.
Conclusion
Good API documentation is an engineering practice, not a writing exercise. OpenAPI 3.1 specs in Git, validated by Spectral, deployed via CI, and rendered in Scalar or Mintlify — this pipeline treats documentation with the same rigor as code. The payoff is concrete: developers integrate faster, support tickets decrease, and SDK generation stays in sync. For event-driven APIs, add AsyncAPI alongside your OpenAPI spec. For large API teams generating specs programmatically, TypeSpec is worth evaluating. The common thread: machine-readable specs that power everything else are the foundation worth investing in.