Expert in creating comprehensive OpenAPI/Swagger specifications and API documentation aligned with OpenAPI 3.0+ standards.
Core Principles
Specification Standards
-
Use OpenAPI 3.0.3 or 3.1.0
-
Consistent naming conventions (kebab-case for paths, camelCase for properties)
-
Organize endpoints through tags
-
Maintain reusable component schemas
-
Document all response codes
Documentation Quality
-
Provide business logic context
-
Include extensive realistic examples
-
Document all error scenarios
-
Define rate-limiting specifications
-
Explicit data format definitions
OpenAPI 3.0 Structure
Basic Specification
openapi: "3.0.3"
info:
title: "User Management API"
description: |
REST API for managing users in the platform.
## Authentication
All endpoints require Bearer token authentication.
## Rate Limiting
- Standard: 100 requests/minute
- Premium: 1000 requests/minute
## Versioning
API version is included in the URL path (/v1/).
version: "1.0.0"
contact:
name: "API Support"
email: "api-support@example.com"
url: "https://developer.example.com/support"
license:
name: "Apache 2.0"
url: "https://www.apache.org/licenses/LICENSE-2.0"
termsOfService: "https://example.com/terms"
servers:
- url: "https://api.example.com/v1"
description: "Production server"
- url: "https://staging-api.example.com/v1"
description: "Staging server"
- url: "http://localhost:3000/v1"
description: "Development server"
tags:
- name: "users"
description: "User management operations"
- name: "authentication"
description: "Authentication and authorization"
- name: "admin"
description: "Administrative operations"
security:
- bearerAuth: []
Path Documentation
paths:
/users:
get:
operationId: "listUsers"
tags:
- "users"
summary: "List all users"
description: |
Retrieve a paginated list of users.
Results can be filtered by status and sorted by various fields.
Pagination is cursor-based for optimal performance.
parameters:
- $ref: "#/components/parameters/PageSize"
- $ref: "#/components/parameters/PageCursor"
- name: "status"
in: "query"
description: "Filter by user status"
required: false
schema:
type: "string"
enum: ["active", "inactive", "pending"]
default: "active"
- name: "sort"
in: "query"
description: "Sort field and direction"
required: false
schema:
type: "string"
enum: ["created_at:asc", "created_at:desc", "name:asc", "name:desc"]
default: "created_at:desc"
responses:
"200":
description: "Successful response"
content:
application/json:
schema:
$ref: "#/components/schemas/UserListResponse"
examples:
success:
$ref: "#/components/examples/UserListSuccess"
headers:
X-RateLimit-Limit:
$ref: "#/components/headers/X-RateLimit-Limit"
X-RateLimit-Remaining:
$ref: "#/components/headers/X-RateLimit-Remaining"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
post:
operationId: "createUser"
tags:
- "users"
summary: "Create a new user"
description: |
Create a new user account.
A verification email will be sent to the provided email address.
The user must verify their email before they can log in.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateUserRequest"
examples:
basic:
summary: "Basic user creation"
value:
email: "user@example.com"
name: "John Doe"
password: "SecurePassword123!"
withProfile:
summary: "User with profile data"
value:
email: "user@example.com"
name: "John Doe"
password: "SecurePassword123!"
profile:
bio: "Software developer"
location: "San Francisco, CA"
responses:
"201":
description: "User created successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/User"
example:
id: "usr_1234567890"
email: "user@example.com"
name: "John Doe"
status: "pending"
createdAt: "2024-03-15T10:30:00Z"
headers:
Location:
description: "URL of the created user"
schema:
type: "string"
format: "uri"
example: "/users/usr_1234567890"
"400":
$ref: "#/components/responses/BadRequest"
"409":
description: "User already exists"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "USER_EXISTS"
message: "A user with this email already exists"
"422":
$ref: "#/components/responses/ValidationError"
/users/{userId}:
parameters:
- $ref: "#/components/parameters/UserId"
get:
operationId: "getUser"
tags:
- "users"
summary: "Get user by ID"
description: "Retrieve detailed information about a specific user"
responses:
"200":
description: "Successful response"
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"404":
$ref: "#/components/responses/NotFound"
patch:
operationId: "updateUser"
tags:
- "users"
summary: "Update user"
description: |
Partially update a user's information.
Only the fields provided in the request body will be updated.
To remove a field, set it to null explicitly.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateUserRequest"
responses:
"200":
description: "User updated successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
delete:
operationId: "deleteUser"
tags:
- "users"
summary: "Delete user"
description: |
Permanently delete a user account.
This action cannot be undone. All associated data will be removed.
responses:
"204":
description: "User deleted successfully"
"404":
$ref: "#/components/responses/NotFound"
Components
components:
schemas:
User:
type: "object"
description: "User account information"
required:
- "id"
- "email"
- "name"
- "status"
- "createdAt"
properties:
id:
type: "string"
description: "Unique user identifier"
pattern: "^usr_[a-zA-Z0-9]{10}$"
example: "usr_1234567890"
readOnly: true
email:
type: "string"
format: "email"
description: "User's email address"
example: "user@example.com"
name:
type: "string"
description: "User's display name"
minLength: 1
maxLength: 100
example: "John Doe"
status:
type: "string"
description: "Account status"
enum: ["active", "inactive", "pending", "suspended"]
example: "active"
profile:
$ref: "#/components/schemas/UserProfile"
createdAt:
type: "string"
format: "date-time"
description: "Account creation timestamp"
readOnly: true
example: "2024-03-15T10:30:00Z"
updatedAt:
type: "string"
format: "date-time"
description: "Last update timestamp"
readOnly: true
example: "2024-03-15T10:30:00Z"
UserProfile:
type: "object"
description: "Extended user profile information"
properties:
bio:
type: "string"
description: "User biography"
maxLength: 500
example: "Software developer passionate about APIs"
location:
type: "string"
description: "User's location"
maxLength: 100
example: "San Francisco, CA"
avatarUrl:
type: "string"
format: "uri"
description: "URL to user's avatar image"
example: "https://cdn.example.com/avatars/usr_123.jpg"
timezone:
type: "string"
description: "User's timezone"
example: "America/Los_Angeles"
CreateUserRequest:
type: "object"
description: "Request body for creating a new user"
required:
- "email"
- "name"
- "password"
properties:
email:
type: "string"
format: "email"
description: "User's email address"
example: "user@example.com"
name:
type: "string"
description: "User's display name"
minLength: 1
maxLength: 100
example: "John Doe"
password:
type: "string"
format: "password"
description: "User's password"
minLength: 8
maxLength: 128
pattern: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$"
example: "SecurePassword123!"
profile:
$ref: "#/components/schemas/UserProfile"
UpdateUserRequest:
type: "object"
description: "Request body for updating a user"
properties:
name:
type: "string"
description: "User's display name"
minLength: 1
maxLength: 100
nullable: true
profile:
$ref: "#/components/schemas/UserProfile"
UserListResponse:
type: "object"
description: "Paginated list of users"
required:
- "data"
- "pagination"
properties:
data:
type: "array"
items:
$ref: "#/components/schemas/User"
pagination:
$ref: "#/components/schemas/Pagination"
Pagination:
type: "object"
description: "Pagination metadata"
required:
- "total"
- "hasMore"
properties:
total:
type: "integer"
description: "Total number of items"
example: 150
hasMore:
type: "boolean"
description: "Whether more items exist"
example: true
nextCursor:
type: "string"
description: "Cursor for next page"
example: "eyJpZCI6MTAwfQ=="
prevCursor:
type: "string"
description: "Cursor for previous page"
example: "eyJpZCI6NTB9"
Error:
type: "object"
description: "Error response"
required:
- "code"
- "message"
properties:
code:
type: "string"
description: "Machine-readable error code"
example: "VALIDATION_ERROR"
message:
type: "string"
description: "Human-readable error message"
example: "The request body is invalid"
details:
type: "array"
description: "Detailed error information"
items:
type: "object"
properties:
field:
type: "string"
description: "Field that caused the error"
example: "email"
message:
type: "string"
description: "Error message for this field"
example: "Must be a valid email address"
requestId:
type: "string"
description: "Request ID for support"
example: "req_abc123xyz"
timestamp:
type: "string"
format: "date-time"
description: "Error timestamp"
example: "2024-03-15T10:30:00Z"
parameters:
UserId:
name: "userId"
in: "path"
description: "User ID"
required: true
schema:
type: "string"
pattern: "^usr_[a-zA-Z0-9]{10}$"
example: "usr_1234567890"
PageSize:
name: "limit"
in: "query"
description: "Number of items per page"
required: false
schema:
type: "integer"
minimum: 1
maximum: 100
default: 20
PageCursor:
name: "cursor"
in: "query"
description: "Pagination cursor"
required: false
schema:
type: "string"
headers:
X-RateLimit-Limit:
description: "Request limit per minute"
schema:
type: "integer"
example: 100
X-RateLimit-Remaining:
description: "Remaining requests in current window"
schema:
type: "integer"
example: 95
X-RateLimit-Reset:
description: "Unix timestamp when limit resets"
schema:
type: "integer"
example: 1710500000
responses:
BadRequest:
description: "Bad request"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "BAD_REQUEST"
message: "The request could not be processed"
requestId: "req_abc123xyz"
Unauthorized:
description: "Authentication required"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "UNAUTHORIZED"
message: "Authentication credentials are missing or invalid"
NotFound:
description: "Resource not found"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "NOT_FOUND"
message: "The requested resource was not found"
ValidationError:
description: "Validation error"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "VALIDATION_ERROR"
message: "Request validation failed"
details:
- field: "email"
message: "Must be a valid email address"
- field: "password"
message: "Must be at least 8 characters"
TooManyRequests:
description: "Rate limit exceeded"
headers:
Retry-After:
description: "Seconds until rate limit resets"
schema:
type: "integer"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "RATE_LIMIT_EXCEEDED"
message: "Too many requests. Please try again later."
securitySchemes:
bearerAuth:
type: "http"
scheme: "bearer"
bearerFormat: "JWT"
description: |
JWT authentication token.
Include in the Authorization header:
`Authorization: Bearer <token>`
Tokens expire after 1 hour. Use the refresh token endpoint
to obtain a new access token.
apiKey:
type: "apiKey"
in: "header"
name: "X-API-Key"
description: "API key for server-to-server communication"
examples:
UserListSuccess:
summary: "Successful user list"
value:
data:
- id: "usr_1234567890"
email: "user1@example.com"
name: "John Doe"
status: "active"
createdAt: "2024-03-15T10:30:00Z"
- id: "usr_0987654321"
email: "user2@example.com"
name: "Jane Smith"
status: "active"
createdAt: "2024-03-14T09:00:00Z"
pagination:
total: 150
hasMore: true
nextCursor: "eyJpZCI6MTAwfQ=="
Advanced Features
Webhooks (OpenAPI 3.1)
webhooks:
userCreated:
post:
operationId: "userCreatedWebhook"
summary: "User created event"
description: |
Triggered when a new user account is created.
Your endpoint must respond with a 2xx status code within 30 seconds.
Failed deliveries will be retried up to 5 times with exponential backoff.
requestBody:
required: true
content:
application/json:
schema:
type: "object"
required:
- "event"
- "timestamp"
- "data"
properties:
event:
type: "string"
const: "user.created"
timestamp:
type: "string"
format: "date-time"
data:
$ref: "#/components/schemas/User"
responses:
"200":
description: "Webhook received successfully"
security:
- webhookSignature: []
userUpdated:
post:
operationId: "userUpdatedWebhook"
summary: "User updated event"
description: "Triggered when a user's information is modified"
requestBody:
required: true
content:
application/json:
schema:
type: "object"
properties:
event:
type: "string"
const: "user.updated"
timestamp:
type: "string"
format: "date-time"
data:
type: "object"
properties:
user:
$ref: "#/components/schemas/User"
changes:
type: "object"
description: "Fields that were changed"
responses:
"200":
description: "Webhook received successfully"
Custom Extensions
x-code-samples: - lang: "curl" label: "cURL" source: | curl -X GET "https://api.example.com/v1/users" \ -H "Authorization: Bearer your_token_here" \ -H "Accept: application/json"
-
lang: "javascript" label: "JavaScript" source: | const response = await fetch('https://api.example.com/v1/users', { headers: { 'Authorization': 'Bearer your_token_here', 'Accept': 'application/json' } }); const users = await response.json();
-
lang: "python" label: "Python" source: | import requests
response = requests.get( 'https://api.example.com/v1/users', headers={'Authorization': 'Bearer your_token_here'} ) users = response.json()
<span c