API Documentation — OpenAPI/Swagger Guide
In this tutorial, you'll learn about API Documentation. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
API documentation written with OpenAPI 3.1 and Swagger produces interactive, machine-readable specifications that keep themselves in sync with your code through annotations and Code Generation.
What You'll Learn
You will learn how to write OpenAPI specifications, generate interactive Swagger UI docs, use annotations to keep docs in sync, and follow documentation best practices that DodaTech uses for its partner APIs.
Why API Documentation Matters
Undocumented APIs create integration friction. Every partner integration requires support calls, trial-and-error testing, and guesswork. Good documentation reduces support tickets by 60-80% and accelerates onboarding. DodaTech's Durga Antivirus Pro partner API handles 500+ integrations — each one depends on clear, accurate documentation.
Writing an OpenAPI 3.1 Spec
OpenAPI is a YAML or JSON file that describes every endpoint, parameter, request body, and response.
openapi: 3.1.0
info:
title: Durga Threat Intelligence API
version: 2.0.0
description: API for querying threat data from Durga Antivirus Pro
servers:
- url: https://api.durga.dodatech.com/v2
description: Production server
paths:
/threats:
get:
summary: List threats with optional filtering
parameters:
- name: severity
in: query
schema:
type: string
enum: [low, medium, high, critical]
description: Filter by threat severity
- name: page
in: query
schema:
type: integer
default: 1
responses:
"200":
description: Paginated threat list
content:
application/json:
schema:
$ref: "#/components/schemas/ThreatList"
"401":
description: Missing or invalid API key
Expected output when loaded in Swagger UI:
# Interactive docs at /docs
GET /threats?severity=critical&page=1
→ Try it Out shows parameter inputs and "Execute" button
→ Response section shows schema, example values, status codes
Defining Reusable Schemas
Components prevent repetition and keep your spec maintainable.
components:
schemas:
Threat:
type: object
required: [id, name, severity, detected_at]
properties:
id:
type: string
format: uuid
example: "thr_a1b2c3d4"
name:
type: string
example: "Emotet Trojan Variant"
severity:
type: string
enum: [low, medium, high, critical]
detected_at:
type: string
format: date-time
mitre_id:
type: string
description: MITRE ATT&CK technique ID
example: "T1055"
ThreatList:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/Threat"
pagination:
type: object
properties:
page:
type: integer
total:
type: integer
per_page:
type: integer
Annotations with Swagger Core (Python)
Keep docs in sync by annotating your code directly.
from flask import Flask, jsonify, request
from flask_openapi3 import OpenAPI, Info, Tag
app = Flask(__name__)
openapi = OpenAPI(app)
threat_tag = Tag(name="threats", description="Threat endpoints")
@openapi.route("/v2/threats", methods=["GET"], tags=[threat_tag])
def list_threats():
"""List threats with optional severity filter."""
severity = request.args.get("severity", "all")
threats = fetch_threats(severity=severity)
return jsonify({
"data": threats,
"count": len(threats),
"severity": severity,
})
@openapi.route("/v2/threats/<threat_id>", methods=["GET"], tags=[threat_tag])
def get_threat(threat_id):
"""Get a single threat by ID."""
threat = fetch_threat(threat_id)
if not threat:
return jsonify({"error": "Threat not found"}), 404
return jsonify(threat)
Expected output:
# Auto-generated spec at /openapi/v2.json
# Auto-generated docs at /swagger/
# Endpoints appear grouped by tag
# Request parameters and response schemas auto-documented
Interactive Documentation with Swagger UI
from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL = "/docs"
API_URL = "/openapi/v2.json"
swagger_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
"app_name": "Durga Threat API",
"tryItOutEnabled": True,
"displayRequestDuration": True,
},
)
app.register_blueprint(swagger_blueprint, url_prefix=SWAGGER_URL)
Expected output:
# Visit http://localhost:5000/docs →
# Interactive Swagger UI with:
# - All endpoints listed and collapsible
# - "Try it out" button on each endpoint
# - Request/response schema display
# - Authentication field (API key header)
flowchart LR
A["OpenAPI Spec\nYAML/JSON"] --> B["Swagger UI\nInteractive Docs"]
A --> C["Code Gen\nServer SDKs"]
A --> D["Client Gen\nTypeScript, Python"]
A --> E["Contract Testing\nDredd, Schemathesis"]
B --> F["Developer Portal"]
C --> G["Backend Implementation"]
D --> H["Partner Integrations"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#bbf7d0,stroke:#16a34a
style H fill:#fef3c7,stroke:#d97706
Common Errors
1. Spec Drift
The implementation changes but the spec does not. Use schema validation in tests that compare the spec against actual responses. Tools like openapi-core or dredd catch drift in CI.
2. Missing Error Responses
Documenting only the 200 response is a common mistake. Every endpoint should document 400, 401, 403, 404, 429, and 500 responses with their schemas.
3. No Examples
Schemas without examples force developers to guess the format. Every property should have an example value and every response should have at least one full JSON example.
4. Overly Complex Specs
A single spec file with 500+ endpoints becomes unmaintainable. Split by domain (threats, users, reports) and use $ref to compose them.
5. Forgetting Authentication Documentation
Without documenting auth requirements in the spec, developers cannot test endpoints. Use securitySchemes and security at the operation level.
Practice Questions
1. What is the difference between OpenAPI and Swagger?
OpenAPI is the specification standard. Swagger is the toolset (Swagger UI, Swagger Editor, Swagger Codegen) that implements OpenAPI.
2. How do you keep documentation in sync with code?
Use annotations in your framework (Flask OpenAPI, FastAPI, SpringDoc) that auto-generate the spec from code. Add CI checks that validate the spec against actual responses.
3. What does the $ref keyword do in OpenAPI?
It references a component schema defined elsewhere in the spec, enabling reuse without duplication.
4. Challenge: Write an OpenAPI 3.1 schema for a /scan endpoint that accepts a file upload and returns a scan result with status (clean/infected) and threat_name.
/scan:
post:
summary: Upload a file for malware scanning
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
"200":
content:
application/JSON:
schema:
type: object
properties:
status:
type: string
enum: [clean, infected]
threat_name:
type: string
Mini Project: Document a Threat API
Write an OpenAPI 3.1 spec for a simplified version of the Durga Antivirus Pro threat API with three endpoints: list threats, get threat by ID, and submit a suspicious file hash. Include schemas, examples, error responses, and API key auth. Generate Swagger UI and test it with curl.
Related Tutorials
RESTful API Design — API Gateway — OAuth 2.0
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-24.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro