openapi-governance
Comprehensive guide to OpenAPI governance, API design standards, automated linting, breaking change detection, and API lifecycle management
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
OpenAPI Governance
What is OpenAPI Governance?
Definition: Enforcing API design standards across an organization through automated validation and lifecycle management.
Key Components
- API Design Standards: Consistent patterns (naming, structure, errors)
- Automated Validation: Linting rules enforced in CI/CD
- Breaking Change Detection: Prevent accidental breaking changes
- API Lifecycle Management: Design → Deploy → Deprecate
Example
Developer creates API endpoint:
POST /api/users (wrong - should be /api/v1/users)
Linter catches in CI:
❌ Error: Missing version prefix in URL
❌ Error: Missing operation description
❌ Error: No example provided
Developer fixes → CI passes → Merge allowed
Why Governance Matters
1. Consistency (Developers Know What to Expect)
Without Governance:
Service A: GET /api/v1/users?page=1&limit=20
Service B: GET /users?offset=0&count=20
Service C: GET /api/users?p=1&size=20
→ Every API is different, hard to learn
With Governance:
All services: GET /api/v1/{resource}?page=1&limit=20
→ Consistent patterns, easy to learn
2. Quality (Catch Issues Before Production)
Automated Checks:
- Missing descriptions
- Inconsistent naming
- Missing examples
- Security schemes not defined
- Breaking changes
3. Documentation (Auto-Generated, Always in Sync)
Flow:
OpenAPI spec → Swagger UI (interactive docs)
→ ReDoc (beautiful static docs)
→ Postman collection
→ Client SDKs
Spec is source of truth → Docs always accurate
4. Breaking Change Prevention
Example:
Developer removes field from response:
- name: string (removed)
+ email: string (added)
Breaking change detector:
❌ Breaking change: Field 'name' removed from response
→ Requires major version bump (v1 → v2)
OpenAPI Specification (OAS) 3.0/3.1
Structure
openapi: 3.0.3
info:
title: User API
version: 1.0.0
description: API for managing users
contact:
name: API Team
email: api@example.com
servers:
- url: https://api.example.com/v1
description: Production
- url: https://staging-api.example.com/v1
description: Staging
paths:
/users:
get:
summary: List users
operationId: listUsers
tags: [Users]
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
'400':
$ref: '#/components/responses/BadRequest'
components:
schemas:
User:
type: object
required: [id, email, name]
properties:
id:
type: string
format: uuid
example: "123e4567-e89b-12d3-a456-426614174000"
email:
type: string
format: email
example: "user@example.com"
name:
type: string
example: "John Doe"
createdAt:
type: string
format: date-time
example: "2024-01-15T10:00:00Z"
UserList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/Pagination'
Pagination:
type: object
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []
Data Types and Schemas
Primitive Types:
string:
type: string
minLength: 1
maxLength: 255
integer:
type: integer
minimum: 0
maximum: 100
number:
type: number
format: float
boolean:
type: boolean
date:
type: string
format: date-time # ISO 8601
Complex Types:
array:
type: array
items:
type: string
minItems: 1
maxItems: 10
object:
type: object
properties:
name:
type: string
required: [name]
enum:
type: string
enum: [ACTIVE, INACTIVE, PENDING]
Request/Response Definitions
Request Body:
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email, name]
properties:
email:
type: string
format: email
name:
type: string
examples:
example1:
value:
email: "user@example.com"
name: "John Doe"
Response:
responses:
'201':
description: User created
headers:
Location:
schema:
type: string
description: URL of created user
content:
application/json:
schema:
$ref: '#/components/schemas/User'
Authentication Schemes
Bearer Token:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
API Key:
securitySchemes:
apiKey:
type: apiKey
in: header
name: X-API-Key
OAuth 2.0:
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/oauth/authorize
tokenUrl: https://auth.example.com/oauth/token
scopes:
read: Read access
write: Write access
API Design Standards
RESTful Conventions
Resource Naming:
✅ Good:
GET /api/v1/users
POST /api/v1/users
GET /api/v1/users/{id}
PUT /api/v1/users/{id}
DELETE /api/v1/users/{id}
❌ Bad:
GET /api/v1/getUsers
POST /api/v1/createUser
GET /api/v1/user/{id} (singular)
HTTP Methods:
- GET: Retrieve resource (idempotent, safe)
- POST: Create resource
- PUT: Replace resource (idempotent)
- PATCH: Update resource (partial)
- DELETE: Delete resource (idempotent)
URL Structure
Standard:
https://api.example.com/v1/resources/{id}/subresources/{subId}
Examples:
GET /api/v1/users/123
GET /api/v1/users/123/orders
GET /api/v1/users/123/orders/456
Rules:
- Always include version (
/v1/,/v2/) - Use plural nouns (
users, notuser) - Use kebab-case for multi-word resources (
user-profiles) - No trailing slashes
- Keep URLs short (max 3 levels deep)
Query Parameters
Pagination:
GET /api/v1/users?page=1&limit=20
Response:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 100,
"totalPages": 5
}
}
Filtering:
GET /api/v1/users?status=active&role=admin
GET /api/v1/users?createdAfter=2024-01-01
Sorting:
GET /api/v1/users?sort=createdAt:desc
GET /api/v1/users?sort=-createdAt (- means desc)
Field Selection:
GET /api/v1/users?fields=id,name,email
Request/Response Format
Request (JSON):
POST /api/v1/users
Content-Type: application/json
{
"email": "user@example.com",
"name": "John Doe",
"role": "member"
}
Response (JSON):
201 Created
Location: /api/v1/users/123
Content-Type: application/json
{
"id": "123",
"email": "user@example.com",
"name": "John Doe",
"role": "member",
"createdAt": "2024-01-15T10:00:00Z"
}
Error Format (RFC 7807 Problem Details)
Standard Error:
400 Bad Request
Content-Type: application/problem+json
{
"type": "https://example.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Email is required",
"instance": "/api/v1/users",
"errors": [
{
"field": "email",
"message": "Email is required"
}
]
}
OpenAPI Schema:
components:
schemas:
Error:
type: object
required: [type, title, status]
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
errors:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
Date Format (ISO 8601)
Standard:
2024-01-15T10:00:00Z (UTC)
2024-01-15T10:00:00+07:00 (with timezone)
OpenAPI:
createdAt:
type: string
format: date-time
example: "2024-01-15T10:00:00Z"
Pagination
Cursor-Based (Recommended for Large Datasets):
GET /api/v1/users?cursor=abc123&limit=20
Response:
{
"data": [...],
"pagination": {
"nextCursor": "def456",
"prevCursor": "xyz789",
"hasMore": true
}
}
Offset-Based (Simple):
GET /api/v1/users?page=1&limit=20
Response:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 100
}
}
Naming Conventions
Resource Names: Plural Nouns
✅ Good:
/users
/projects
/orders
/user-profiles
❌ Bad:
/user (singular)
/getUsers (verb)
/userList (not RESTful)
Fields: camelCase or snake_case (Be Consistent)
camelCase (JavaScript, Java):
{
"userId": "123",
"firstName": "John",
"createdAt": "2024-01-15T10:00:00Z"
}
snake_case (Python, Ruby):
{
"user_id": "123",
"first_name": "John",
"created_at": "2024-01-15T10:00:00Z"
}
Rule: Pick one, use everywhere
Enums: UPPER_SNAKE_CASE
status:
type: string
enum:
- ACTIVE
- INACTIVE
- PENDING
Boolean Fields: is/has Prefix
isActive:
type: boolean
hasAccess:
type: boolean
canEdit:
type: boolean
OpenAPI Linting
Spectral (Popular Linter)
Install:
npm install -g @stoplight/spectral-cli
Run:
spectral lint openapi.yaml
Output:
openapi.yaml
10:5 warning operation-description Operation must have a description
25:7 error no-$ref-siblings $ref cannot be placed next to other properties
40:3 warning operation-tags Operation must have tags
✖ 3 problems (1 error, 2 warnings, 0 infos, 0 hints)
Custom Rules (Organization-Specific)
.spectral.yaml:
extends: spectral:oas
rules:
# Require version in URL
path-must-have-version:
description: Paths must include version (e.g., /v1/)
given: $.paths[*]~
then:
function: pattern
functionOptions:
match: "^/v[0-9]+/"
# Require examples
operation-examples:
description: Operations must have examples
given: $.paths[*][*].responses[*].content[*]
then:
field: examples
function: truthy
# Require pagination for list endpoints
list-must-paginate:
description: List endpoints must have pagination parameters
given: $.paths[*].get
then:
field: parameters
function: schema
functionOptions:
schema:
type: array
contains:
properties:
name:
enum: [page, limit]
# Consistent error format
error-must-use-problem-json:
description: Errors must use RFC 7807 Problem Details
given: $.paths[*][*].responses[?(@property >= 400)]
then:
field: content.application/problem+json
function: truthy
CI/CD Integration
GitHub Actions:
name: API Governance
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Spectral
run: npm install -g @stoplight/spectral-cli
- name: Lint OpenAPI spec
run: spectral lint openapi.yaml --fail-severity warn
- name: Check breaking changes
run: |
npm install -g oasdiff
oasdiff breaking main:openapi.yaml HEAD:openapi.yaml
Common Linting Rules
All Operations Have Description
rules:
operation-description:
description: Operations must have a description
given: $.paths[*][*]
then:
field: description
function: truthy
Example:
paths:
/users:
get:
description: List all users # Required
summary: List users
All Parameters Have Description
rules:
parameter-description:
description: Parameters must have a description
given: $.paths[*][*].parameters[*]
then:
field: description
function: truthy
All Responses Have Schema
rules:
response-schema:
description: Responses must have a schema
given: $.paths[*][*].responses[*].content[*]
then:
field: schema
function: truthy
No Empty Descriptions
rules:
no-empty-description:
description: Descriptions must not be empty
given: $..description
then:
function: pattern
functionOptions:
notMatch: "^\\s*$"
Consistent Naming Conventions
rules:
path-kebab-case:
description: Paths must use kebab-case
given: $.paths[*]~
then:
function: pattern
functionOptions:
match: "^(/[a-z0-9-]+)+$"
property-camelCase:
description: Properties must use camelCase
given: $..properties[*]~
then:
function: casing
functionOptions:
type: camel
Security Schemes Defined
rules:
security-defined:
description: Security schemes must be defined
given: $.components
then:
field: securitySchemes
function: truthy
Examples Provided
rules:
schema-examples:
description: Schemas must have examples
given: $.components.schemas[*]
then:
field: example
function: truthy
Breaking Change Detection
openapiDiff Tool
Install:
npm install -g oasdiff
Check Breaking Changes:
oasdiff breaking old.yaml new.yaml
Output:
Breaking changes:
1. DELETE /api/v1/users/{id}/profile
Endpoint removed
2. GET /api/v1/users
Response field 'name' removed
3. POST /api/v1/users
Request field 'email' is now required
Non-breaking changes:
1. GET /api/v1/users
Response field 'avatar' added
2. GET /api/v1/projects
New endpoint added
Breaking Changes
Examples:
- Remove endpoint
- Remove field from response
- Add required field to request
- Change field type (string → integer)
- Rename field
- Change semantics (field means something different)
- Remove enum value
- Tighten validation (maxLength 100 → 50)
Non-Breaking Changes
Examples:
- Add new endpoint
- Add optional field to request
- Add field to response
- Add enum value (at end)
- Relax validation (maxLength 50 → 100)
- Add new response code
Semver for API Versions
Versioning:
v1.0.0 → v1.1.0 (non-breaking: add endpoint)
v1.1.0 → v1.1.1 (patch: bug fix)
v1.1.1 → v2.0.0 (breaking: remove field)
URL Versioning:
/v1/users (major version in URL)
/v2/users (breaking changes)
API Documentation Generation
Swagger UI (Interactive Docs)
Setup:
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const swaggerDocument = YAML.load('./openapi.yaml');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
Features:
- Interactive (try API in browser)
- Auto-generated from OpenAPI spec
- OAuth support
- Examples
URL: https://api.example.com/api-docs
ReDoc (Beautiful Static Docs)
Setup:
<!DOCTYPE html>
<html>
<head>
<title>API Documentation</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<style>
body { margin: 0; padding: 0; }
</style>
</head>
<body>
<redoc spec-url='openapi.yaml'></redoc>
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
</body>
</html>
Features:
- Beautiful design
- Three-panel layout
- Search
- Responsive
Stoplight (Design-First Platform)
Features:
- Visual OpenAPI editor
- Mock servers
- Documentation hosting
- Collaboration
Pricing: $49-199/user/month
Postman (Import OpenAPI)
Import:
Postman → Import → OpenAPI spec → Auto-generate collection
Features:
- Test API
- Generate code snippets
- Share with team
Design-First vs Code-First
Design-First (Write OpenAPI Spec, Generate Code)
Process:
1. Write OpenAPI spec (openapi.yaml)
2. Review with stakeholders
3. Generate server stubs (openapi-generator)
4. Implement business logic
5. Generate client SDKs
Pros:
- API design reviewed before implementation
- Spec is source of truth
- Auto-generate clients
Cons:
- Extra step (write spec)
- Need to keep spec in sync with code
Tools:
- openapi-generator (generate servers, clients)
- Stoplight Studio (visual editor)
Code-First (Write Code, Generate OpenAPI Spec)
Process:
1. Write code with annotations
2. Generate OpenAPI spec from code
3. Publish docs
Example (NestJS):
@Controller('users')
@ApiTags('users')
export class UsersController {
@Get()
@ApiOperation({ summary: 'List users' })
@ApiResponse({ status: 200, type: [User] })
async findAll(): Promise<User[]> {
return this.usersService.findAll();
}
}
Pros:
- No separate spec to maintain
- Spec always in sync with code
Cons:
- API design happens in code (less review)
- Harder to review API design
Hybrid (Write Spec + Code, Keep in Sync)
Process:
1. Write OpenAPI spec (design)
2. Implement code
3. Validate code matches spec (automated)
Tools:
- Specmatic (contract testing)
- openapi-validator
Recommendation: Design-first for public APIs, code-first for internal
OpenAPI Tooling
Editor
Swagger Editor:
- Online: https://editor.swagger.io
- Features: Live preview, validation, export
Stoplight Studio:
- Desktop app
- Visual editor
- Mock servers
- Pricing: Free for open source, $49+/user/month
Linter
Spectral:
npm install -g @stoplight/spectral-cli
spectral lint openapi.yaml
Validator
openapi-validator:
npm install -g ibm-openapi-validator
lint-openapi openapi.yaml
Generator
openapi-generator:
npm install -g @openapitools/openapi-generator-cli
# Generate server
openapi-generator-cli generate \
-i openapi.yaml \
-g nodejs-express-server \
-o ./server
# Generate client
openapi-generator-cli generate \
-i openapi.yaml \
-g typescript-axios \
-o ./client
Supported Languages:
- Servers: Node.js, Python, Java, Go, Ruby, PHP
- Clients: TypeScript, JavaScript, Python, Java, Go, Swift, Kotlin
Diff
oasdiff:
npm install -g oasdiff
oasdiff breaking old.yaml new.yaml
openapi-diff:
npm install -g openapi-diff
openapi-diff old.yaml new.yaml
Governance Workflow
Step 1: Developer Writes/Updates OpenAPI Spec
Process:
1. Create feature branch
2. Update openapi.yaml
3. Add new endpoint or modify existing
4. Add examples
5. Commit and push
Step 2: Automated Linting (CI)
GitHub Actions:
- name: Lint OpenAPI
run: spectral lint openapi.yaml --fail-severity warn
Checks:
- All operations have descriptions
- All parameters have descriptions
- Consistent naming
- Examples provided
Step 3: Breaking Change Check (CI)
- name: Check breaking changes
run: |
oasdiff breaking origin/main:openapi.yaml HEAD:openapi.yaml
if [ $? -ne 0 ]; then
echo "Breaking changes detected. Requires major version bump."
exit 1
fi
Step 4: Review by API Guild
API Guild:
- Cross-team group of API experts
- Reviews API design
- Ensures consistency
- Approves changes
Review Checklist:
- Follows naming conventions
- RESTful design
- Proper error handling
- Examples provided
- No breaking changes (or justified)
Step 5: Merge to Main
After Approval:
- Merge PR
- Spec is now source of truth
Step 6: Auto-Publish Docs
GitHub Actions:
- name: Publish docs
run: |
# Generate Swagger UI
docker run -p 80:8080 -e SWAGGER_JSON=/openapi.yaml \
-v $(pwd):/usr/share/nginx/html/openapi.yaml \
swaggerapi/swagger-ui
# Deploy to docs site
aws s3 cp openapi.yaml s3://api-docs/
API Versioning Strategy
URL Versioning (/v1/, /v2/)
Format:
/api/v1/users
/api/v2/users
Pros:
- Clear and visible
- Easy to route
- Can run multiple versions simultaneously
Cons:
- URL changes
- Need to maintain multiple codebases
When to Use: Public APIs, major breaking changes
Header Versioning (Accept-Version: v1)
Format:
GET /api/users
Accept-Version: v1
Pros:
- URL doesn't change
- More RESTful
Cons:
- Less visible
- Harder to test (need to set header)
When to Use: Internal APIs, minor versioning
No Versioning (Only Non-Breaking Changes)
Strategy:
- Never make breaking changes
- Always backward compatible
- Deprecate old fields (but keep them)
Pros:
- Simple (no versioning needed)
- No migration needed
Cons:
- Technical debt accumulates
- Eventually need to clean up
When to Use: Internal APIs, early stage
Deprecation Policy (6-12 Months Notice)
Timeline:
Month 0: Announce deprecation
Month 3: Warn users (headers, emails)
Month 6: Final warning
Month 12: Remove deprecated version
Deprecation Headers
Sunset Header (RFC 8594):
HTTP/1.1 200 OK
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Link: <https://docs.example.com/migration>; rel="sunset"
Deprecation Header:
HTTP/1.1 200 OK
Deprecation: true
Link: <https://docs.example.com/migration>; rel="deprecation"
Warning Header:
HTTP/1.1 200 OK
Warning: 299 - "This endpoint is deprecated. Use /v2/users instead."
Multi-Team API Governance
Centralized API Registry
Purpose: Single source of truth for all APIs
Contents:
- All OpenAPI specs
- Ownership (which team owns which API)
- Status (active, deprecated, sunset)
- Dependencies (which APIs call which)
Tools:
- Backstage (Spotify's developer portal)
- Custom registry (database + UI)
API Review Board
Members:
- API architects
- Representatives from each team
- Product managers
Responsibilities:
- Review API designs
- Approve breaking changes
- Maintain style guide
- Resolve conflicts
Meeting: Weekly or bi-weekly
Style Guide Document
Contents:
- Naming conventions
- URL structure
- Error format
- Pagination format
- Authentication
- Examples
Location: Confluence, Notion, GitHub
Shared Spectral Ruleset
Repository:
api-governance/
.spectral.yaml (shared rules)
README.md (how to use)
Usage:
# team-a/.spectral.yaml
extends: ../api-governance/.spectral.yaml
rules:
# Team-specific rules
team-a-custom-rule:
...
Monitoring API Compliance
Spec Coverage (% of Endpoints Documented)
Metric:
Spec Coverage = Documented Endpoints / Total Endpoints
Target: 100%
How to Measure:
1. Scan code for API endpoints
2. Compare with OpenAPI spec
3. Report missing endpoints
Linting Violations Over Time
Dashboard:
Jan: 50 violations
Feb: 40 violations
Mar: 30 violations
Apr: 20 violations
Trend: Improving ✅
Breaking Changes Deployed
Metric:
Breaking Changes Deployed = Breaking Changes / Total Deployments
Target: 0% (no breaking changes without major version bump)
Real-World Governance Examples
Stripe API
Characteristics:
- Excellent consistency
- Comprehensive docs
- Versioning via headers
- Extensive examples
Learn From:
- Error format (detailed, helpful)
- Pagination (cursor-based)
- Idempotency keys
- Webhooks (event-driven)
GitHub API
Characteristics:
- RESTful design
- GraphQL alternative
- Deprecation notices
- Rate limiting
Learn From:
- Deprecation headers
- Preview features (opt-in)
- Comprehensive SDKs
Internal API Gateway Patterns
Pattern:
All APIs go through API gateway
→ Gateway enforces governance
→ Rate limiting, auth, logging
→ Consistent experience
Implementation
Spectral Ruleset (YAML)
See "Custom Rules" section above
CI/CD Pipeline (GitHub Actions)
name: API Governance
on:
pull_request:
paths:
- 'openapi.yaml'
jobs:
governance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Fetch all history for diff
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install tools
run: |
npm install -g @stoplight/spectral-cli
npm install -g oasdiff
- name: Lint OpenAPI spec
run: spectral lint openapi.yaml --fail-severity warn
- name: Check breaking changes
run: |
git show origin/main:openapi.yaml > old.yaml
oasdiff breaking old.yaml openapi.yaml
if [ $? -ne 0 ]; then
echo "::error::Breaking changes detected. Requires major version bump."
exit 1
fi
- name: Generate docs
run: |
npx redoc-cli bundle openapi.yaml -o docs.html
- name: Upload docs
uses: actions/upload-artifact@v2
with:
name: api-docs
path: docs.html
OpenAPI Spec Templates
Minimal Template:
openapi: 3.0.3
info:
title: My API
version: 1.0.0
description: API description
contact:
name: API Team
email: api@example.com
servers:
- url: https://api.example.com/v1
paths:
/resource:
get:
summary: List resources
operationId: listResources
tags: [Resources]
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Resource'
components:
schemas:
Resource:
type: object
required: [id, name]
properties:
id:
type: string
name:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
security:
- bearerAuth: []
Summary
Quick Reference
OpenAPI Governance: Enforcing API design standards through automated validation
Why:
- Consistency across APIs
- Quality (catch issues early)
- Documentation (auto-generated)
- Breaking change prevention
OpenAPI Structure:
- info, servers, paths, components, security
Design Standards:
- RESTful conventions
- URL:
/api/v1/resources/{id} - Pagination:
?page=1&limit=20 - Error format: RFC 7807 Problem Details
- Date format: ISO 8601
Naming:
- Resources: Plural nouns (
users) - Fields: camelCase or snake_case (consistent)
- Enums: UPPER_SNAKE_CASE
- Booleans: is/has prefix
Linting:
- Spectral (popular linter)
- Custom rules (organization-specific)
- CI/CD integration
Breaking Changes:
- Remove endpoint/field
- Change type
- Add required field
- Detect with oasdiff
Documentation:
- Swagger UI (interactive)
- ReDoc (beautiful)
- Auto-generated from spec
Versioning:
- URL:
/v1/,/v2/ - Header:
Accept-Version: v1 - Deprecation: 6-12 months notice
Tools:
- Editor: Swagger Editor, Stoplight Studio
- Linter: Spectral
- Generator: openapi-generator
- Diff: oasdiff
Workflow:
- Write/update spec
- Automated linting (CI)
- Breaking change check (CI)
- API guild review
- Merge
- Auto-publish docs
Overview
OpenAPI Governance is the practice of enforcing API design standards across an organization through automated validation and lifecycle management.
Key Components
- API Design Standards: Consistent patterns (naming, structure, errors)
- Automated Validation: Linting rules enforced in CI/CD
- Breaking Change Detection: Prevent accidental breaking changes
- API Lifecycle Management: Design → Deploy → Deprecate
Example
Developer creates API endpoint: POST /api/users (wrong - should be /api/v1/users)
Linter catches in CI: ❌ Error: Missing version prefix in URL ❌ Error: Missing operation description ❌ Error: No example provided
Developer fixes → CI passes → Merge allowed
Best Practices
API Design
- Follow RESTful conventions
- Use consistent naming patterns
- Document all endpoints
- Provide examples for all endpoints
- Use appropriate HTTP methods
- Implement proper error handling
- Use consistent error formats
- Use pagination for list endpoints
- Implement filtering and sorting
- Use appropriate status codes
- Document rate limits
- Use versioning in URLs
- [ ]
Validation
- Implement automated linting in CI/CD
- Use Spectral for OpenAPI validation
- Define custom organization rules
- Check for breaking changes
- Validate all operations have descriptions
- Validate all parameters have descriptions
- Validate all responses have schemas
- Ensure examples are provided
- Check for security schemes
- Validate consistent naming conventions
- [ ]
Documentation
- Use OpenAPI spec as source of truth
- Auto-generate documentation
- Use Swagger UI for interactive docs
- Use ReDoc for beautiful static docs
- Keep documentation in sync with code
- [ ]
Breaking Changes
- Use semantic versioning
- Communicate breaking changes early
- Provide migration guides
- Hold breaking change meetings
- Create data contracts with consumers
- Document breaking changes clearly
- Use multi-step migrations
- Use zero-downtime migration pattern
- [ ]
Governance
- Create API review board
- Establish API guild
- Define API lifecycle
- Maintain style guide
- Review API designs
- Approve breaking changes
- Resolve conflicts
- Maintain spec registry
- [ ]
Tools
- Use Spectral for linting
- Use openapi-diff for detecting breaking changes
- Use graphql-inspector for GraphQL
- Use buf for Protobuf
- Use Swagger Editor for visual editing
- Use Stoplight Studio for design-first
- Use openapi-generator for code generation
- [ ]
Versioning
- Use URL versioning (/v1/, /v2/)
- Use header versioning (Accept-Version: v1)
- Use semantic versioning (SemVer)
- Document version compatibility matrix
- Maintain backward compatibility
- Deprecate old versions properly
- Provide migration guides
- [ ]
Monitoring
- Monitor spec coverage
- Track linting violations
- Monitor breaking changes deployed
- Set up dashboards for API health
- Track consumer adoption
- [ ]
Checklist
- Define API design standards
- Implement automated linting
- Set up breaking change detection
- Create API review board
- Document all breaking changes
- Provide migration guides
- Use semantic versioning
- Maintain backward compatibility
- Set up deprecation process
- Monitor deprecated endpoint usage
- Test backward compatibility
- Use design-first approach
- Use consistent naming conventions
- Provide examples for all endpoints
- Document all API changes
- Train team on governance
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!