API Documentation Standards: OpenAPI, AsyncAPI & Structured Specifications
API documentation is structured data for developers. When your API documentation follows established standards like OpenAPI and AsyncAPI, it becomes machine-readable by default. This matters for two reasons: it makes your API easier to integrate with, and it makes your product's capabilities visible to AI engines that parse technical documentation to generate recommendations.
This guide covers the major API documentation standards, provides complete examples you can adapt, and explains how structured API docs relate to broader discoverability across search and AI systems.
The API Documentation Standards Landscape
Three specifications dominate the API documentation space in 2026:
| Standard | Use Case | Current Version | Governed By |
|---|---|---|---|
| OpenAPI | REST / HTTP APIs | 3.1.0 | OpenAPI Initiative (Linux Foundation) |
| AsyncAPI | Event-driven / message-based APIs | 3.0.0 | AsyncAPI Initiative (Linux Foundation) |
| JSON Schema | Data validation / schema definitions | 2020-12 | JSON Schema Organization |
OpenAPI handles the vast majority of API documentation needs. AsyncAPI extends the same philosophy to event-driven architectures. JSON Schema underpins both, providing the data model definitions that describe request bodies, response payloads, and message formats.
OpenAPI Specification (OAS)
The OpenAPI Specification is the industry standard for describing RESTful APIs. Originally known as Swagger, the specification was donated to the Linux Foundation's OpenAPI Initiative in 2015 and has since evolved through major versions.
Complete OpenAPI 3.1 Example
Here is a production-ready OpenAPI document for a visibility tracking API. This example demonstrates the core patterns you need:
openapi: "3.1.0"
info:
title: Brand Visibility API
version: "2.0.0"
description: |
REST API for tracking brand visibility across AI-generated
search responses. Provides endpoints for monitoring mention
rates, citation quality, and competitive positioning.
contact:
name: API Support
email: api-support@example.com
url: https://docs.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/v2
description: Production
- url: https://staging-api.example.com/v2
description: Staging
security:
- bearerAuth: []
tags:
- name: Brands
description: Brand entity management
- name: Visibility
description: AI visibility tracking and metrics
- name: Reports
description: Scheduled and on-demand reporting
paths:
/brands:
get:
operationId: listBrands
tags: [Brands]
summary: List all monitored brands
description: |
Returns a paginated list of all brands being monitored
in the current workspace. Supports filtering by status
and sorting by name or creation date.
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
description: Page number for pagination
- name: per_page
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 25
description: Number of results per page
- name: status
in: query
schema:
type: string
enum: [active, paused, archived]
description: Filter by monitoring status
- name: sort
in: query
schema:
type: string
enum: [name, created_at, visibility_score]
default: name
description: Sort field
responses:
"200":
description: Successful response with list of brands
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/Brand"
meta:
$ref: "#/components/schemas/PaginationMeta"
example:
data:
- id: "brand_abc123"
name: "Acme Corp"
domain: "acmecorp.com"
status: "active"
visibility_score: 72.4
created_at: "2026-01-15T10:30:00Z"
meta:
page: 1
per_page: 25
total: 12
total_pages: 1
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/RateLimited"
post:
operationId: createBrand
tags: [Brands]
summary: Add a new brand to monitor
description: |
Creates a new brand entity and begins monitoring its
visibility across AI-generated search responses.
Initial data collection takes 24-48 hours.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateBrandRequest"
example:
name: "Acme Corp"
domain: "acmecorp.com"
competitors:
- "competitor1.com"
- "competitor2.com"
keywords:
- "project management software"
- "team collaboration tool"
responses:
"201":
description: Brand created successfully
content:
application/json:
schema:
$ref: "#/components/schemas/Brand"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"409":
description: Brand with this domain already exists
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/brands/{brandId}/visibility:
get:
operationId: getVisibilityMetrics
tags: [Visibility]
summary: Get AI visibility metrics for a brand
description: |
Returns detailed visibility metrics including mention
rates, citation quality scores, and positional data
across multiple AI engines.
parameters:
- name: brandId
in: path
required: true
schema:
type: string
description: Unique brand identifier
- name: period
in: query
schema:
type: string
enum: [7d, 30d, 90d, 12m]
default: 30d
description: Time period for metrics
- name: engines
in: query
schema:
type: array
items:
type: string
enum: [chatgpt, claude, perplexity, google_aio]
style: form
explode: false
description: Filter by AI engine (comma-separated)
responses:
"200":
description: Visibility metrics
content:
application/json:
schema:
$ref: "#/components/schemas/VisibilityReport"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT token obtained from the /auth/token endpoint.
Include as: Authorization: Bearer <token>
schemas:
Brand:
type: object
required: [id, name, domain, status]
properties:
id:
type: string
description: Unique identifier
example: "brand_abc123"
name:
type: string
description: Brand display name
example: "Acme Corp"
domain:
type: string
format: hostname
description: Primary domain
example: "acmecorp.com"
status:
type: string
enum: [active, paused, archived]
description: Current monitoring status
visibility_score:
type: number
format: float
minimum: 0
maximum: 100
description: |
Composite AI visibility score (0-100).
Calculated from mention rate, citation quality,
and positional data across monitored engines.
example: 72.4
competitors:
type: array
items:
type: string
format: hostname
description: Competitor domains being tracked
created_at:
type: string
format: date-time
description: ISO 8601 creation timestamp
CreateBrandRequest:
type: object
required: [name, domain]
properties:
name:
type: string
minLength: 1
maxLength: 200
description: Brand display name
domain:
type: string
format: hostname
description: Primary domain to monitor
competitors:
type: array
items:
type: string
format: hostname
maxItems: 10
description: Competitor domains (max 10)
keywords:
type: array
items:
type: string
maxItems: 50
description: Keywords to track (max 50)
VisibilityReport:
type: object
properties:
brand_id:
type: string
period:
type: string
overall_score:
type: number
format: float
mention_count:
type: integer
description: Total mentions across all engines
avg_position:
type: number
format: float
description: |
Average mention position (1.0 = always first
mentioned, higher = mentioned later in responses)
engines:
type: array
items:
type: object
properties:
name:
type: string
mentions:
type: integer
avg_position:
type: number
format: float
citation_quality:
type: number
format: float
description: 0-100 score for citation accuracy
trend:
type: string
enum: [improving, stable, declining]
description: Visibility trend over the period
PaginationMeta:
type: object
properties:
page:
type: integer
per_page:
type: integer
total:
type: integer
total_pages:
type: integer
Error:
type: object
required: [code, message]
properties:
code:
type: string
description: Machine-readable error code
example: "BRAND_NOT_FOUND"
message:
type: string
description: Human-readable error description
example: "No brand found with the specified ID"
details:
type: object
additionalProperties: true
description: Additional error context
responses:
Unauthorized:
description: Authentication required or token invalid
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "UNAUTHORIZED"
message: "Invalid or expired authentication token"
NotFound:
description: Requested resource not found
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
BadRequest:
description: Invalid request parameters
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
RateLimited:
description: Rate limit exceeded
headers:
Retry-After:
schema:
type: integer
description: Seconds until rate limit resets
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
code: "RATE_LIMITED"
message: "Rate limit exceeded. Try again in 60 seconds."
Key OpenAPI Patterns Explained
Info object: The info section is the first thing both developers and AI engines read. Include a clear description, contact details, and terms of service. This metadata is indexed and used when AI systems describe your API.
Components and $ref: Reusable schema definitions in components/schemas reduce duplication and ensure consistency. When you change a schema, every reference updates automatically. This is equivalent to DRY principles in code.
Examples: Inline example values are critical for both developer experience and AI comprehension. AI engines use these to understand the shape and meaning of your data. Always include realistic examples, not placeholders like "string" or "123".
Error responses: Define error schemas as reusable responses. Consistent error handling is a strong quality signal for AI engines evaluating your API documentation.
operationId on every operation. This provides a stable, unique identifier that code generators and AI systems use to reference specific endpoints. Choose descriptive names: listBrands is better than getBrands or brands_get.
AsyncAPI for Event-Driven APIs
The AsyncAPI specification is to event-driven architectures what OpenAPI is to REST APIs. It describes message-based APIs that use protocols like WebSocket, Kafka, MQTT, AMQP, and Server-Sent Events.
Complete AsyncAPI 3.0 Example
asyncapi: "3.0.0"
info:
title: Visibility Events API
version: "1.0.0"
description: |
Real-time event stream for brand visibility changes.
Subscribe to receive notifications when visibility
metrics change, new mentions are detected, or
competitive positioning shifts.
contact:
name: Events API Support
email: events-support@example.com
license:
name: Apache 2.0
servers:
production:
host: events.example.com
protocol: wss
description: Production WebSocket endpoint
security:
- type: http
scheme: bearer
staging:
host: events-staging.example.com
protocol: wss
description: Staging WebSocket endpoint
channels:
brandMentions:
address: /brands/{brandId}/mentions
description: |
Stream of new brand mentions detected across AI engines.
Each message contains the mention context, source engine,
query that triggered it, and positional data.
parameters:
brandId:
description: Unique brand identifier
messages:
newMention:
$ref: "#/components/messages/MentionDetected"
visibilityAlerts:
address: /brands/{brandId}/alerts
description: |
Alerts for significant visibility changes. Triggered
when visibility score changes by more than 5 points
or when competitive ranking shifts.
parameters:
brandId:
description: Unique brand identifier
messages:
visibilityChange:
$ref: "#/components/messages/VisibilityAlert"
competitorUpdates:
address: /workspace/competitors
description: |
Workspace-wide competitor activity feed. Aggregates
notable changes across all monitored competitors.
messages:
competitorChange:
$ref: "#/components/messages/CompetitorUpdate"
operations:
receiveMention:
action: receive
channel:
$ref: "#/channels/brandMentions"
summary: Receive new mention notifications
description: |
Subscribe to this channel to receive real-time
notifications when your brand is mentioned in
AI-generated responses.
receiveAlert:
action: receive
channel:
$ref: "#/channels/visibilityAlerts"
summary: Receive visibility change alerts
receiveCompetitorUpdate:
action: receive
channel:
$ref: "#/channels/competitorUpdates"
summary: Receive competitor activity updates
components:
messages:
MentionDetected:
name: MentionDetected
title: New Brand Mention
contentType: application/json
payload:
type: object
required: [id, brand_id, engine, detected_at]
properties:
id:
type: string
description: Unique mention identifier
example: "mention_xyz789"
brand_id:
type: string
example: "brand_abc123"
engine:
type: string
enum: [chatgpt, claude, perplexity, google_aio]
description: AI engine where mention was detected
query:
type: string
description: User query that triggered the mention
example: "best project management tools for remote teams"
position:
type: integer
minimum: 1
description: Position in the response (1 = first mentioned)
example: 2
context:
type: string
description: Surrounding text context of the mention
example: "...tools like Asana and Acme Corp offer real-time..."
citation_type:
type: string
enum: [direct_quote, paraphrase, recommendation, comparison]
sentiment:
type: string
enum: [positive, neutral, negative]
detected_at:
type: string
format: date-time
VisibilityAlert:
name: VisibilityAlert
title: Visibility Change Alert
contentType: application/json
payload:
type: object
required: [brand_id, alert_type, severity]
properties:
brand_id:
type: string
alert_type:
type: string
enum:
- score_increase
- score_decrease
- rank_change
- new_competitor_detected
- mention_spike
severity:
type: string
enum: [info, warning, critical]
previous_value:
type: number
current_value:
type: number
description:
type: string
example: "Visibility score increased from 68.2 to 74.1 (+5.9)"
triggered_at:
type: string
format: date-time
CompetitorUpdate:
name: CompetitorUpdate
title: Competitor Activity Update
contentType: application/json
payload:
type: object
properties:
competitor_domain:
type: string
format: hostname
change_type:
type: string
enum: [visibility_change, new_content, schema_update]
summary:
type: string
detected_at:
type: string
format: date-time
When to Use AsyncAPI
Use AsyncAPI when your API involves any of these patterns:
- WebSocket connections - Bidirectional real-time communication
- Server-Sent Events (SSE) - Server-to-client streaming
- Message queues - Kafka, RabbitMQ, AWS SQS, Google Pub/Sub
- MQTT - IoT and lightweight messaging
- Webhooks - Server-to-server event notifications
If your system uses both REST endpoints and event-driven messaging, maintain both OpenAPI and AsyncAPI specifications. Many modern platforms document their REST API with OpenAPI and their event streams with AsyncAPI.
JSON Schema for Data Validation
JSON Schema is the foundation that both OpenAPI and AsyncAPI build on for data type definitions. Understanding JSON Schema independently is valuable because you can use it for configuration validation, form generation, and data documentation beyond API contexts.
Complete JSON Schema Example
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/brand-config.json",
"title": "Brand Configuration",
"description": "Configuration schema for setting up brand monitoring. Defines required fields, validation rules, and defaults for new brand entities.",
"type": "object",
"required": ["name", "domain", "monitoring"],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Display name for the brand",
"examples": ["Acme Corp", "TechStart Inc."]
},
"domain": {
"type": "string",
"format": "hostname",
"description": "Primary domain to monitor",
"examples": ["acmecorp.com"]
},
"aliases": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 20,
"uniqueItems": true,
"description": "Alternative names, abbreviations, or brand variations",
"default": [],
"examples": [["Acme", "ACME Corp", "Acme Corporation"]]
},
"monitoring": {
"type": "object",
"required": ["engines", "keywords"],
"properties": {
"engines": {
"type": "array",
"items": {
"type": "string",
"enum": ["chatgpt", "claude", "perplexity", "google_aio", "copilot"]
},
"minItems": 1,
"uniqueItems": true,
"description": "AI engines to monitor for brand mentions"
},
"keywords": {
"type": "array",
"items": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"minItems": 1,
"maxItems": 50,
"description": "Search queries to monitor"
},
"frequency": {
"type": "string",
"enum": ["hourly", "daily", "weekly"],
"default": "daily",
"description": "How often to check for new mentions"
},
"competitors": {
"type": "array",
"items": {
"type": "string",
"format": "hostname"
},
"maxItems": 10,
"default": [],
"description": "Competitor domains to track for comparison"
}
},
"additionalProperties": false
},
"notifications": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Email address for alert notifications"
},
"webhook_url": {
"type": "string",
"format": "uri",
"description": "Webhook endpoint for real-time alerts"
},
"alert_threshold": {
"type": "number",
"minimum": 1,
"maximum": 50,
"default": 5,
"description": "Minimum visibility score change to trigger alert"
}
}
}
},
"additionalProperties": false,
"examples": [
{
"name": "Acme Corp",
"domain": "acmecorp.com",
"aliases": ["Acme", "ACME"],
"monitoring": {
"engines": ["chatgpt", "claude", "perplexity"],
"keywords": ["project management software", "team collaboration tool"],
"frequency": "daily",
"competitors": ["competitor1.com", "competitor2.com"]
},
"notifications": {
"email": "alerts@acmecorp.com",
"alert_threshold": 5
}
}
]
}
Key JSON Schema features demonstrated:
$schemaand$id- Self-identifying schema with version referenceformat- Semantic validation hints (hostname, email, uri, date-time)enum- Restricts values to a predefined setdefault- Specifies default values for optional propertiesexamples- Provides realistic sample data for each fieldadditionalProperties: false- Strict mode that rejects unknown properties- Nested objects - Complex structures with their own required fields and validation rules
Documentation Tooling
These tools generate interactive, browsable documentation from your OpenAPI and AsyncAPI specifications:
| Tool | Specification | Type | Key Feature |
|---|---|---|---|
| Swagger UI | OpenAPI | Free / OSS | Interactive API explorer with "Try it" functionality |
| Redocly | OpenAPI | Freemium | Three-panel layout, SEO-friendly output, API linting |
| Stoplight | OpenAPI | Freemium | Visual API design, mock servers, style guides |
| AsyncAPI Studio | AsyncAPI | Free / OSS | Visual editor and documentation generator for AsyncAPI |
| Bump.sh | Both | Freemium | Hosted docs with change tracking and diff detection |
Best Practices for Machine-Readable API Docs
1. Write Descriptions for Machines and Humans
Every endpoint, parameter, and schema should have a description field. These descriptions are what AI engines read when summarizing your API's capabilities.
# BAD: No description
parameters:
- name: q
in: query
schema:
type: string
# GOOD: Descriptive, specific, useful
parameters:
- name: q
in: query
description: |
Full-text search query. Searches across brand name,
domain, and keyword fields. Supports quoted phrases
for exact matching. Maximum 200 characters.
schema:
type: string
maxLength: 200
example: "project management"
2. Version Your API Specification
Maintain your OpenAPI/AsyncAPI specification in version control alongside your API code. This ensures the documentation stays in sync with the implementation.
# Recommended project structure
api/
openapi.yaml # OpenAPI specification
asyncapi.yaml # AsyncAPI specification (if applicable)
schemas/
brand.json # Shared JSON Schema definitions
visibility.json
examples/
create-brand.json # Request/response examples
visibility-report.json
docs/
getting-started.md # Human-readable guides
authentication.md
rate-limits.md
3. Include Realistic Examples
AI engines use example values to understand your data model. Always provide realistic examples at both the schema level and the operation level.
# BAD: Placeholder examples
example:
id: "string"
name: "string"
score: 0
# GOOD: Realistic examples that demonstrate actual use
example:
id: "brand_abc123"
name: "Acme Corp"
score: 72.4
4. Use Tags to Organize Endpoints
Tags group related endpoints. Documentation tools use tags to create navigation sections. AI engines use tags to understand the functional areas of your API.
5. Document Error Responses Completely
Every endpoint should document its error responses, not just the success path. AI engines describing your API will include error handling information in their recommendations.
6. Keep Specifications Valid
Use linting tools to catch specification errors before publishing:
# Lint OpenAPI specification
npx @redocly/cli lint openapi.yaml
# Validate AsyncAPI specification
npx @asyncapi/cli validate asyncapi.yaml
# Validate JSON Schema
npx ajv validate -s schema.json -d data.json
API Documentation and AI Visibility
Well-structured API documentation directly affects how AI engines describe and recommend your product. When a developer asks an AI engine "What APIs are available for tracking brand visibility?", the AI draws on parsed API documentation to construct its answer.
Here is how structured API docs contribute to discoverability:
- The
infoobject provides a concise summary that AI engines can quote directly - Endpoint descriptions tell AI engines what specific capabilities your API offers
- Schema definitions show the depth and sophistication of your data model
- Examples demonstrate practical use cases that AI engines can reference
- Error handling signals production-readiness and reliability
Platforms like 42A have observed that products with comprehensive, publicly accessible API documentation tend to receive more detailed and accurate descriptions in AI-generated technical recommendations. This is because the structured nature of OpenAPI and AsyncAPI specifications gives AI engines precise, parseable data about your product's capabilities.
Frequently Asked Questions
What is the difference between OpenAPI and Swagger?
Swagger was the original name of the API specification format. In 2015, the specification was donated to the OpenAPI Initiative (part of the Linux Foundation) and renamed to OpenAPI Specification. Swagger now refers to the tooling ecosystem (Swagger UI, Swagger Editor, Swagger Codegen) built around the OpenAPI Specification. OpenAPI 3.0+ is the current standard; Swagger 2.0 is the legacy version.
When should I use AsyncAPI instead of OpenAPI?
Use AsyncAPI for event-driven APIs that use message brokers (Kafka, RabbitMQ, MQTT, WebSockets, Server-Sent Events). Use OpenAPI for synchronous REST APIs with request-response patterns. If your system uses both patterns, maintain both specifications for complete documentation coverage.
Does API documentation affect AI search visibility?
Yes. Well-structured API documentation using OpenAPI or AsyncAPI specifications is machine-readable by design. AI engines can parse these specifications to understand your product's capabilities, which influences how your product is described in AI-generated technical comparisons and recommendations.
Next Steps
Start with an OpenAPI specification for your primary API. Use a linting tool to validate it. Generate interactive documentation with Swagger UI or Redocly. If you have event-driven components, add an AsyncAPI specification for those.
Combine your API documentation with Organization schema and Product schema on your marketing site. This creates a complete picture: your marketing pages tell AI engines what your product does, and your API documentation tells them exactly how it works.
For measuring how your documentation affects AI visibility, see our tools guide for tracking and measurement platforms.