API documentation with OpenAPI/Swagger — endpoint descriptions, request/response
66
57%
Does it follow best practices?
Impact
100%
1.06xAverage score across 3 eval scenarios
Passed
No known issues
A small internal tooling team has a lightweight Python HTTP server that collects product feedback from employees. It was written quickly using Python's standard library (http.server) without any framework, so there is no auto-generated documentation. New developers joining the team, and a third-party tool that needs to integrate with it, are blocked because there is no reference describing how to call the API.
Your job is to write clear, comprehensive API documentation for this service. The documentation should be good enough that a developer who has never seen the code can integrate against it without asking any questions.
Produce a file named API.md containing the full API reference for the service described below.
The documentation should cover every endpoint thoroughly enough to allow a developer to make correct HTTP requests without reading the source code.
The following file is provided as input. Extract it before beginning.
=============== FILE: feedback_server.py =============== #!/usr/bin/env python3 """Minimal feedback collection HTTP server (no framework)."""
import json from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import urlparse, parse_qs import uuid from datetime import datetime
FEEDBACKS = {}
class FeedbackHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urlparse(self.path)
parts = parsed.path.strip('/').split('/')
# GET /feedback - list all feedback, optional ?product=X&limit=N
if parts == ['feedback']:
qs = parse_qs(parsed.query)
product_filter = qs.get('product', [None])[0]
try:
limit = int(qs.get('limit', [50])[0])
except ValueError:
self._send(400, {"error": "limit must be an integer"})
return
items = list(FEEDBACKS.values())
if product_filter:
items = [i for i in items if i['product'] == product_filter]
self._send(200, {"items": items[:limit], "total": len(items)})
# GET /feedback/{id} - get a single feedback entry
elif len(parts) == 2 and parts[0] == 'feedback':
fid = parts[1]
entry = FEEDBACKS.get(fid)
if entry is None:
self._send(404, {"error": "Feedback entry not found"})
else:
self._send(200, entry)
# GET /health
elif parts == ['health']:
self._send(200, {"status": "ok"})
else:
self._send(404, {"error": "Not found"})
def do_POST(self):
parsed = urlparse(self.path)
parts = parsed.path.strip('/').split('/')
# POST /feedback - submit new feedback
if parts == ['feedback']:
length = int(self.headers.get('Content-Length', 0))
if length == 0:
self._send(400, {"error": "Request body is required"})
return
try:
body = json.loads(self.rfile.read(length))
except json.JSONDecodeError:
self._send(400, {"error": "Invalid JSON"})
return
product = body.get('product')
message = body.get('message')
rating = body.get('rating') # optional, integer 1-5
author_email = body.get('author_email') # optional
if not product or not message:
self._send(400, {"error": "product and message are required"})
return
if rating is not None:
if not isinstance(rating, int) or not (1 <= rating <= 5):
self._send(400, {"error": "rating must be an integer between 1 and 5"})
return
entry = {
"id": str(uuid.uuid4()),
"product": product,
"message": message,
"rating": rating,
"author_email": author_email,
"created_at": datetime.utcnow().isoformat() + "Z"
}
FEEDBACKS[entry['id']] = entry
self._send(201, entry)
# POST /feedback/{id}/resolve - mark a feedback entry as resolved
elif len(parts) == 3 and parts[0] == 'feedback' and parts[2] == 'resolve':
fid = parts[1]
entry = FEEDBACKS.get(fid)
if entry is None:
self._send(404, {"error": "Feedback entry not found"})
return
entry['resolved'] = True
entry['resolved_at'] = datetime.utcnow().isoformat() + "Z"
self._send(200, entry)
else:
self._send(404, {"error": "Not found"})
def do_DELETE(self):
parsed = urlparse(self.path)
parts = parsed.path.strip('/').split('/')
# DELETE /feedback/{id} - delete a feedback entry
if len(parts) == 2 and parts[0] == 'feedback':
fid = parts[1]
if fid not in FEEDBACKS:
self._send(404, {"error": "Feedback entry not found"})
return
del FEEDBACKS[fid]
self._send(204, None)
else:
self._send(404, {"error": "Not found"})
def _send(self, status, body):
self.send_response(status)
self.send_header('Content-Type', 'application/json')
self.end_headers()
if body is not None:
self.wfile.write(json.dumps(body).encode())
def log_message(self, fmt, *args):
pass # suppress default loggingif name == 'main': server = HTTPServer(('0.0.0.0', 8080), FeedbackHandler) print("Listening on http://0.0.0.0:8080") server.serve_forever()