This output represents the successful execution of Step 2: gemini → generate_code for the "API Documentation Generator" workflow.
The goal of this step is to generate professional, well-structured, and comprehensive API documentation. To achieve this, we are providing a Python-based API Documentation Generator script that takes an OpenAPI Specification (OAS) as input and produces human-readable documentation in Markdown format. This Markdown output can then be easily converted to HTML, PDF, or integrated into various documentation platforms.
The generated code is designed to be clean, well-commented, and production-ready, focusing on modularity and ease of use.
This section provides the Python code for an API Documentation Generator, a Jinja2 template for rendering the documentation, and an example OpenAPI Specification file.
The provided Python script (api_doc_generator.py) serves as the core of your API documentation solution. It performs the following key functions:
To use the generator, you will need the following files:
.
├── api_doc_generator.py # The main Python script
├── templates/
│ └── api_doc_template.md.j2 # Jinja2 template for Markdown output
└── examples/
└── example_openapi_spec.yaml # An example OpenAPI 3.0 specification
This document outlines a detailed study plan designed to equip individuals with the knowledge and practical skills required to generate professional, comprehensive API documentation. This plan covers foundational concepts, industry best practices, essential tools, and advanced techniques, culminating in the ability to produce high-quality documentation that enhances developer experience and API adoption.
The primary goal of this study plan is to transform a learner into a proficient API documentation specialist. By the end of this program, you will be able to design, write, and maintain clear, accurate, and user-friendly API documentation, encompassing endpoint descriptions, request/response examples, authentication guides, and SDK usage examples, meeting professional standards.
Upon successful completion of this study plan, you will be able to:
This 6-week schedule provides a structured approach to learning, with each week building upon the previous one.
* Introduction to APIs: REST, GraphQL, gRPC basics.
* The role and importance of API documentation.
* Principles of good technical writing for developers.
* Audience analysis: Identifying different user personas (developers, business analysts, QA).
* Planning documentation structure and information architecture.
* Introduction to API documentation standards (e.g., OpenAPI/Swagger, RAML, API Blueprint).
* Read articles on API design principles and technical writing.
* Analyze exemplary API documentation (e.g., Stripe, Twilio, GitHub).
* Outline a documentation plan for a hypothetical simple API.
* Deep dive into OpenAPI Specification (OAS) structure (YAML/JSON).
* Defining paths, operations (GET, POST, PUT, DELETE).
* Describing parameters (path, query, header, cookie).
* Defining request bodies and response objects using schemas.
* Introduction to Swagger UI and Swagger Editor for visualization and editing.
* Complete an online tutorial for OAS.
* Use Swagger Editor to create a basic OpenAPI definition for a simple CRUD API.
* Generate and explore the documentation using Swagger UI.
* Documenting authentication methods: API Keys, Basic Auth, OAuth 2.0 (Authorization Code, Client Credentials), JWT.
* Defining security schemes in OAS.
* Handling complex data types and reusable components ($ref).
* Documenting error responses and common error patterns.
* API versioning strategies and how to document them.
* Introduction to webhooks documentation.
* Extend the previous week's OpenAPI definition to include authentication.
* Add detailed error responses for common scenarios (e.g., 401, 403, 404, 500).
* Experiment with defining reusable schemas.
* Crafting effective request and response examples (JSON, XML).
* Generating code snippets for various languages (cURL, Python, JavaScript, Ruby, Java).
* Best practices for documenting SDKs: installation, initialization, common usage patterns, example code.
* Introduction to API clients like Postman for testing and generating documentation.
* Exploring documentation generation tools (e.g., Stoplight Studio, ReadMe.io).
* For your API definition, create realistic request and response examples for several endpoints.
* Use Postman or similar tools to generate code snippets for different languages.
* Research how popular SDKs (e.g., Stripe, Twilio) are documented.
* Documentation as Code (Docs-as-Code) principles.
* Integrating documentation into CI/CD pipelines (e.g., linting OAS, auto-publishing).
* Generating documentation directly from code annotations/comments.
* Tools for static site generation (e.g., Docusaurus, Sphinx, MkDocs) for custom documentation portals.
* Strategies for feedback loops, updates, and deprecation.
* Internationalization and localization considerations for API docs.
* Experiment with a static site generator to host your API documentation.
* Explore tools that generate OAS from code (e.g., Springdoc-openapi for Java, drf-spectacular for Django REST Framework).
* Set up a simple CI pipeline to validate your OpenAPI definition.
* Consolidate all learned concepts into a complete documentation solution.
* Review and refine personal documentation style and process.
* Explore advanced topics: GraphQL schema documentation, gRPC Protobuf documentation.
* Capstone Project: Choose a public API (or a mock API) and create its complete, professional documentation from scratch, including:
* An OpenAPI definition.
* Clear endpoint descriptions, parameters, requests, and responses.
* Authentication guide.
* Detailed examples and code snippets.
* SDK usage examples (if applicable).
* A hosted documentation portal (e.g., using a static site generator or a dedicated platform).
* Peer review (if possible) of your capstone project.
* Reflect on challenges and successes during the learning journey.
This section lists essential resources to support your learning journey.
* OpenAPI Specification: [https://swagger.io/specification/](https://swagger.io/specification/)
* Swagger UI/Editor: [https://swagger.io/tools/swagger-ui/](https://swagger.io/tools/swagger-ui/) & [https://swagger.io/tools/swagger-editor/](https://swagger.io/tools/swagger-editor/)
* Udemy/Coursera/Pluralsight: Search for "API Documentation," "Technical Writing for Developers," "OpenAPI/Swagger."
* Postman Learning Center: [https://learning.postman.com/](https://learning.postman.com/) (Excellent for practical API usage and documentation)
* "Docs for Developers: An Engineer's and Agile Team's Guide to Technical Documentation" by Jared Batholomew
* "The Product is Docs" by Christopher Gales & Mike Jang
* "Modern Technical Writing: An Introduction to Software Documentation" by Andrew Etter
* API Design & Documentation:
* Stoplight Studio: [https://stoplight.io/](https://stoplight.io/) (Visual API design and documentation)
* ReadMe.io: [https://readme.io/](https://readme.io/) (Developer hub platform)
* Postman: [https://www.postman.com/](https://www.postman.com/) (API development environment, also generates docs)
* Static Site Generators (for custom portals):
* Docusaurus: [https://docusaurus.io/](https://docusaurus.io/) (React-based, great for docs)
* MkDocs: [https://www.mkdocs.org/](https://www.mkdocs.org/) (Python-based, simple Markdown)
* Sphinx: [https://www.sphinx-doc.org/](https://www.sphinx-doc.org/) (Python-based, powerful for complex docs)
* API Handyman: [https://apihandyman.io/](https://apihandyman.io/) (API design and documentation insights)
* Various Tech Blogs: Search for "API documentation best practices," "documenting REST APIs," "OpenAPI tutorial."
* Stripe API Docs: [https://stripe.com/docs/api](https://stripe.com/docs/api)
* Twilio API Docs: [https://www.twilio.com/docs/api](https://www.twilio.com/docs/api)
* GitHub API Docs: [https://docs.github.com/en/rest](https://docs.github.com/en/rest)
Achieving these milestones will mark significant progress and demonstrate mastery of the learning objectives.
Regular assessment ensures that learning is on track and objectives are being met.
python
import os
import yaml
import json
from jinja2 import Environment, FileSystemLoader, select_autoescape
from collections import defaultdict
TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), 'templates')
DEFAULT_TEMPLATE = 'api_doc_template.md.j2'
def load_openapi_spec(file_path):
"""
Loads an OpenAPI Specification from a given file path.
Supports both YAML and JSON formats.
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"OpenAPI spec file not found: {file_path}")
with open(file_path, 'r', encoding='utf-8') as f:
if file_path.endswith(('.yaml', '.yml')):
return yaml.safe_load(f)
elif file_path.endswith('.json'):
return json.load(f)
else:
raise ValueError("Unsupported file format. Please provide a .yaml, .yml, or .json file.")
def _get_schema_example(schema_ref, components):
"""
Recursively resolves schema references and generates a simple example.
Note: This is a basic example generator and might not cover all complex schema types.
"""
if isinstance(schema_ref, dict):
if '$ref' in schema_ref:
ref_path = schema_ref['$ref'].split('/')
component_name = ref_path[-1]
if 'schemas' in components and component_name in components['schemas']:
return _get_schema_example(components['schemas'][component_name], components)
elif 'properties' in schema_ref:
example = {}
for prop, prop_schema in schema_ref['properties'].items():
if 'example' in prop_schema:
example[prop] = prop_schema['example']
elif 'type' in prop_schema:
if prop_schema['type'] == 'string':
example[prop] = prop_schema.get('default', 'string_value')
elif prop_schema['type'] == 'integer':
example[prop] = prop_schema.get('default', 123)
elif prop_schema['type'] == 'boolean':
example[prop] = prop_schema.get('default', True)
elif prop_schema['type'] == 'array':
example[prop] = [_get_schema_example(prop_schema.get('items', {}), components)]
elif prop_schema['type'] == 'object':
example[prop] = _get_schema_example(prop_schema, components)
else:
example[prop] = "..." # Fallback for unknown types
return example
elif 'example' in schema_ref:
return schema_ref['example']
return None
def _generate_sdk_example(method, path, operation, auth_schemes, components):
"""
Generates SDK usage examples (cURL, Python, JavaScript) for a given operation.
"""
base_url = "https://api.example.com" # Placeholder, consider making this configurable
full_path = path
path_params = {}
query_params = {}
header_params = {}
request_body = None
security_headers = {}
security_query_params = {}
# Extract parameters
for param in operation.get('parameters', []):
param_name = param['name']
param_example = param.get('example', f"{{{param_name}}}") # Use example if available, else placeholder
if param['in'] == 'path':
path_params[param_name] = param_example
full_path = full_path.replace(f"{{{param_name}}}", str(param_example))
elif param['in'] == 'query':
query_params[param_name] = param_example
elif param['in'] == 'header':
header_params[param_name] = param_example
# Handle request body
if 'requestBody' in operation:
content = operation['requestBody'].get('content', {})
for media_type, media_schema in content.items():
if media_type.startswith('application/json'):
schema_ref = media_schema.get('schema')
request_body = json.dumps(_get_schema_example(schema_ref, components), indent=2)
break
# Handle authentication
for sec_req in operation.get('security', []):
for scheme_name, scopes in sec_req.items():
if scheme_name in auth_schemes:
scheme_def = auth_schemes[scheme_name]
if scheme_def['type'] == 'apiKey':
if scheme_def['in'] == 'header':
security_headers[scheme_def['name']] = "YOUR_API_KEY"
elif scheme_def['in'] == 'query':
security_query_params[scheme_def['name']] = "YOUR_API_KEY"
elif scheme_def['type'] == 'http' and scheme_def.get('scheme') == 'bearer':
security_headers['Authorization'] = "Bearer YOUR_ACCESS_TOKEN"
# Add other authentication types (OAuth2, OpenID Connect) as needed
# Build query string
query_string_parts = []
for q_name, q_val in query_params.items():
query_string_parts.append(f"{q_name}={q_val}")
for sq_name, sq_val in security_query_params.items():
query_string_parts.append(f"{sq_name}={sq_val}")
query_string = "?" + "&".join(query_string_parts) if query_string_parts else ""
# cURL Example
curl_headers = " ".join([f"-H '{k}: {v}'" for k, v in header_params.items()] +
[f"-H '{k}: {v}'" for k, v in security_headers.items()])
curl_data = f"-d '{request_body}'" if request_body else ""
curl_example = (
f"curl -X {method.upper()} "
f"{curl_headers} "
f"{curl_data} "
f"'{base_url}{full_path}{query_string}'"
).strip()
# Python Requests Example
python_headers = {header_params, security_headers}
python_params = {query_params, security_query_params}
python_example = f"""
import requests
import json
base_url = "{base_url}"
endpoint = "{full_path}"
headers = {json.dumps(python_headers, indent=4)}
params = {json.dumps(python_params, indent=4)}
"""
if request_body:
python_example += f"""
data = {request_body} # or json.dumps(your_payload) if not already a string
response = requests.{method}(f"{{base_url}}{{endpoint}}", headers=headers, params=params, json=data)
"""
else:
python_example += f"""
response = requests.{method}(f"{{base_url}}{{endpoint}}", headers=headers, params=params)
"""
python_example += """
print(response.status_code)
print(response.json())
"""
# JavaScript Fetch Example
js_headers = {header_params, security_headers}
js_body = f"body: JSON.stringify({request_body})," if request_body else ""
js_example = f"""
const base_url = "{base_url}";
const endpoint = "{full_path}";
const params = new URLSearchParams({json.dumps(python_params)});
const headers = {json.dumps(js_headers, indent=4)};
fetch(${{base_url}}{{endpoint}}?${{params.toString()}}, {{
method: '{method.upper()}',
headers: headers,
{js_body}
}})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
"""
return {
'curl': curl_example,
'python': python_example.strip(),
'javascript': js_example.strip()
}
def generate_documentation_data(openapi_spec):
"""
Processes the OpenAPI spec and extracts all necessary data for documentation.
"""
info = openapi_spec.get('info', {})
paths = openapi_spec.get('paths', {})
components = openapi_spec.get('components', {})
security_schemes = components.get('securitySchemes', {})
doc_data = {
'title': info.get('title', 'API Documentation'),
'version': info.get('version', '1.0.0'),
'description': info.get('description', 'Comprehensive API documentation.'),
'servers': openapi_spec.get('servers', []),
'contact': info.get('contact', {}),
'license': info.get('license', {}),
'security_schemes': [],
'endpoints': []
}
# Process Security Schemes
for name, scheme in security_schemes.items():
doc_data['security_schemes'].append({
'name': name,
'type': scheme.get('type'),
'description': scheme.get('description'),
'in': scheme.get('in'),
'scheme': scheme.get('
As the final step in the "API Documentation Generator" workflow, we present a comprehensive, detailed, and professionally structured API documentation output. This deliverable serves as a robust template, filled with illustrative examples, that you can directly adapt and populate with your specific API details.
Welcome to the documentation for the Product Management API. This API provides a suite of powerful endpoints designed to help you programmatically manage your product catalog, inventory, and related data. Whether you're building an e-commerce platform, an internal inventory system, or integrating with third-party services, our API offers the flexibility and reliability you need.
This documentation will guide you through the process of authenticating, making requests, understanding responses, and integrating our API into your applications using various tools and SDKs.
To begin using the Product Management API, you will need to:
All requests to the Product Management API must be authenticated. We primarily use API Key-based authentication for secure access.
Your API Key uniquely identifies your application and grants it access to our services.
Authorization header of every request, prefixed with Bearer.Example HTTP Header:
Authorization: Bearer YOUR_API_KEY
Security Best Practices:
All API requests should be made to the following base URL:
https://api.yourdomain.com/v1
The API uses standard HTTP status codes to indicate the success or failure of an API request. In case of an error, the API will return a JSON object containing details about the error.
| Status Code | Meaning | Description |
| :---------- | :-------------------------------------- | :------------------------------------------------------------------------------------------------------ |
| 200 OK | Success | The request was successful. |
| 201 Created | Resource Created | A new resource was successfully created. |
| 204 No Content | No Content to Return | The request was successful, but there is no content to return (e.g., successful deletion). |
| 400 Bad Request | Invalid Request | The request was malformed or invalid. Check your parameters. |
| 401 Unauthorized | Authentication Required or Failed | No valid API Key provided, or the API Key is invalid. |
| 403 Forbidden | Access Denied | You do not have permission to access the requested resource. |
| 404 Not Found | Resource Not Found | The requested resource could not be found. |
| 405 Method Not Allowed | Method Not Allowed | The HTTP method used is not supported for the requested resource. |
| 429 Too Many Requests | Rate Limit Exceeded | You have sent too many requests in a given amount of time. See Rate Limiting section. |
| 500 Internal Server Error | Server Error | An unexpected error occurred on the server. Please try again later. |
{
"error": {
"code": "resource_not_found",
"message": "The product with ID 'prod_xyz123' could not be found.",
"details": [
{
"field": "productId",
"description": "Ensure the product ID is valid and exists."
}
]
}
}
To ensure fair usage and system stability, the Product Management API enforces rate limits on requests.
100 requests per minute per API Key.429 Too Many Requests HTTP status code. * X-RateLimit-Limit: The maximum number of requests you can make in the current window.
* X-RateLimit-Remaining: The number of requests remaining in the current window.
* X-RateLimit-Reset: The timestamp (in UTC epoch seconds) when the current rate limit window resets.
Example Response Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1678886400
This section details all available endpoints in the Product Management API.
Retrieve a list of all products, with optional filtering and pagination.
GET/productsParameters:
| Name | Type | Location | Description | Required | Default |
| :-------- | :------- | :------- | :------------------------------------------------- | :------- | :-------- |
| limit | integer | Query | Maximum number of products to return. | No | 10 |
| offset | integer | Query | Number of products to skip before starting. | No | 0 |
| category | string | Query | Filter products by category name. | No | |
| status | string | Query | Filter products by status (e.g., active, draft). | No | active |
Request Example (cURL):
curl -X GET \
'https://api.yourdomain.com/v1/products?limit=5&category=Electronics' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Response Example (200 OK):
{
"data": [
{
"id": "prod_abc123",
"name": "Wireless Bluetooth Headphones",
"sku": "WH-BT-001",
"description": "High-fidelity wireless headphones with noise cancellation.",
"price": 99.99,
"currency": "USD",
"stock": 150,
"category": "Electronics",
"status": "active",
"createdAt": "2023-01-15T10:00:00Z",
"updatedAt": "2023-01-15T10:00:00Z"
},
{
"id": "prod_def456",
"name": "Smartwatch Series 5",
"sku": "SW-S5-001",
"description": "Advanced smartwatch with health tracking features.",
"price": 249.99,
"currency": "USD",
"stock": 75,
"category": "Wearables",
"status": "active",
"createdAt": "2023-02-01T11:30:00Z",
"updatedAt": "2023-02-01T11:30:00Z"
}
],
"meta": {
"total": 200,
"limit": 5,
"offset": 0,
"hasMore": true
}
}
SDK Usage Example (Python):
import your_api_sdk
client = your_api_sdk.Client(api_key="YOUR_API_KEY")
try:
products = client.products.list(limit=5, category="Electronics")
for product in products.data:
print(f"Product ID: {product.id}, Name: {product.name}, Price: {product.price}")
except your_api_sdk.ApiException as e:
print(f"Error fetching products: {e}")
SDK Usage Example (Node.js):
const { ProductManagementAPI } = require('your-api-sdk');
const client = new ProductManagementAPI('YOUR_API_KEY');
async function getProducts() {
try {
const products = await client.products.list({ limit: 5, category: 'Electronics' });
products.data.forEach(product => {
console.log(`Product ID: ${product.id}, Name: ${product.name}, Price: ${product.price}`);
});
} catch (error) {
console.error('Error fetching products:', error.message);
}
}
getProducts();
Retrieve detailed information for a single product using its unique ID.
GET/products/{productId}Parameters:
| Name | Type | Location | Description | Required |
| :---------- | :------- | :------- | :--------------------------- | :------- |
| productId | string | Path | The unique identifier of the product. | Yes |
Request Example (cURL):
curl -X GET \
'https://api.yourdomain.com/v1/products/prod_abc123' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Response Example (200 OK):
{
"id": "prod_abc123",
"name": "Wireless Bluetooth Headphones",
"sku": "WH-BT-001",
"description": "High-fidelity wireless headphones with noise cancellation.",
"price": 99.99,
"currency": "USD",
"stock": 150,
"category": "Electronics",
"status": "active",
"createdAt": "2023-01-15T10:00:00Z",
"updatedAt": "2023-01-15T10:00:00Z",
"tags": ["audio", "wireless", "bluetooth"],
"specifications": {
"color": "Black",
"batteryLife": "20 hours",
"weight": "250g"
}
}
Response Example (404 Not Found):
{
"error": {
"code": "resource_not_found",
"message": "The product with ID 'prod_xyz999' could not be found.",
"details": []
}
}
SDK Usage Example (Python):
import your_api_sdk
client = your_api_sdk.Client(api_key="YOUR_API_KEY")
product_id = "prod_abc123"
try:
product = client.products.get(product_id=product_id)
print(f"Found Product: {product.name} (SKU: {product.sku})")
except your_api_sdk.ApiException as e:
print(f"Error fetching product {product_id}: {e}")
SDK Usage Example (Node.js):
const { ProductManagementAPI } = require('your-api-sdk');
const client = new ProductManagementAPI('YOUR_API_KEY');
async function getProduct(productId) {
try {
const product = await client.products.get(productId);
console.log(`Found Product: ${product.name} (SKU: ${product.sku})`);
} catch (error) {
console.error(`Error fetching product ${productId}:`, error.message);
}
}
getProduct('prod_abc123');
Add a new product to your catalog.
POST/productsRequest Body:
| Name | Type | Description | Required |
| :------------ | :-------- | :-------------------------------------------------- | :------- |
| name | string | The name of the product. | Yes |
| sku | string | Stock Keeping Unit (must be unique). | Yes |
| description | string | A detailed description of the product. | No |
| price | number | The price of the product. | Yes |
| currency | string | The currency code (e.g., USD, EUR). | Yes |
| stock | integer | Initial stock quantity. | Yes |
| category | string | The category the product belongs to. | No |
| status | string | The product's status (active, draft, archived). | No |
| tags | array | List of keywords for the product. | No |
Request Example (cURL):
curl -X POST \
'https://api.yourdomain.com/v1/products' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: