RESTful API Checker
Validate RESTful best practices on your OpenAPI/Swagger specs. Generates HTML and JSON reports with actionable feedback.
Why
OpenAPI linters such as Spectral and
Redocly CLI (TypeScript) or
vacuum (Go) are rule engines you configure with a
ruleset. restful-checker is a small Python package with a fixed set of REST design checks
and a scored report: pip install it, point it at a document or URL, and open the HTML.
It reads Swagger 2.0 and OpenAPI 3.0, 3.1 and 3.2 documents in JSON or YAML.
Installation
pip install restful-checker
Requires Python 3.8+. Depends on PyYAML (YAML documents) and requests (remote documents).
Usage
# Local file
restful-checker path/to/openapi.json
# Remote URL
restful-checker https://api.example.com/openapi.yaml --open
# Generate HTML + JSON
restful-checker openapi.json --output-format both --output-folder reports
Remote documents are fetched within 60 seconds and up to 50 MB. Messages show a URL without its user, password or query string.
Options
| Option | Description | Default |
|---|---|---|
--output-format |
html, json, or both |
html |
--output-folder |
Destination folder | ./html |
--open |
Open HTML in browser | false |
-q, --quiet |
Suppress output | false |
--version |
Show version | - |
rest_report.html and rest_report.json are both written to the output folder; the
format picks which ones are announced (and json and both write the JSON with non-ASCII
text as is).
What It Checks
URL Design
| Check | Description |
|---|---|
| Versioning | A version segment (v1, v2.1, v1beta1, v2alpha) early in the path, followed by a resource |
| Resource Naming | Verbs in URIs (getUsers, get-users, addtocart), plural collections, casing, generic names |
| Resource Nesting | Patterns like /users/{id}/orders |
| Path Parameters | Consistent {param} naming across the document |
HTTP Standards
| Check | Description |
|---|---|
| HTTP Methods | GET, POST, PUT, PATCH, DELETE semantics; HEAD, OPTIONS, TRACE and QUERY are accepted |
| Status Codes | Expected codes per method (200, 201, 204, 400, 404, 409); ranges such as 2XX count for every code of their class |
| Content Types | JSON bodies (application/json, +json types, JSON Lines and JSON sequences); binary and multipart bodies are accepted (see is_binary_media_type) |
| HTTPS Enforcement | OpenAPI 3 servers of the document, its paths and operations, with variables and relative URLs; Swagger 2.0 schemes, also per operation |
Response Quality
| Check | Description |
|---|---|
| Response Examples | example or examples on the media type or its schema (also through allOf) |
| Error Format | code and message fields, or RFC 9457 problem details (application/problem+json or +xml, or two of type, title, status, detail, instance), also through allOf |
Performance
| Check | Description |
|---|---|
| Pagination | page, limit, offset, cursor, per_page, page_size, page_token (or camel case) or JSON:API page[...] on collection GETs |
| Query Filters | Filters like ?status= or JSON:API filter[...] on collection GETs, with a declared type |
Limitations and choices
-
The expected status codes are this tool's conventions and stricter than RFC 9110: PUT and PATCH are asked for 200 and 204, and a DELETE returning 200 without 204 is an error, where the RFC allows 200 or 204 for an update and 200, 202 or 204 for a deletion.
-
An OpenAPI 3 document without top-level
serversgets a warning, although the specification then defaults to/: declaring the server is the advice. -
Version segments with a minor or patch number (
v1.2) are accepted, although some style guides (Google AIP-185) expose only the major version. -
Only local references (
#/components/...) are followed. References to other files or URLs (common.yaml#/Error) are left unresolved, so whatever they hold is not checked. -
The Content Types, Response Examples and Error Format checks read OpenAPI 3
content; Swagger 2.0 bodies (consumes,produces,in: body) are not read.
Programmatic Usage
from restful_checker import analyze_api
result = analyze_api("path/to/openapi.json", output_dir="output")
print(f"HTML: {result['html_path']}")
print(f"JSON: {result['json_path']}")
print(f"Score: {result['json_report']['score']}")
analyze_api(path, output_dir="html", output_format="html") writes both reports and
returns html_path, json_path and json_report (the JSON report as a dictionary). It
raises OSError when the file cannot be read or the report written, and ValueError when
the file is not valid JSON or YAML, does not hold a mapping, has another extension, or is
nested too deeply to read.
Each check is also a function of its own, returning (messages, score): plain-text
messages starting with ✅, ⚠️ or ❌, and a score from 0.0 to 1.0.
| Function | Module (restful_checker.checks.) |
|---|---|
check_versioning |
version_checker |
check_naming |
naming_checker |
check_http_methods |
http_method_checker |
check_status_codes, covers |
status_code_checker |
check_content_type, is_json_media_type, is_binary_media_type |
content_type_checker |
check_response_examples |
response_example_checker |
check_error_format, is_structured_error |
check_error_format |
check_query_filters |
query_filter_checker |
check_pagination, is_pagination_parameter |
pagination_checker |
check_resource_nesting |
resource_nesting_checker |
check_param_consistency |
param_consistency_checker |
check_https_usage, server_kind |
https_checker |
These, analyze_api, the command and the report layouts are the stable API; other names
in the submodules stay importable for existing code but may change.
from restful_checker.checks.naming_checker import check_naming
print(check_naming("/v1/get-users"))
# (['❌ Contains verb-like segment: `get-users`'], 0.0)
Guide and changes
The GUIDE explains how documents are read, every rule of every check, the scores and the report layout.
See the CHANGELOG; 3.2.0 lists every verdict that changed since 3.1.1.
Contributing
Found a bug? Open an issue.
License
MIT
Metadata
Release files for restful-checker 3.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| restful_checker-3.2.0.tar.gz | 86.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| restful_checker-3.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 142.7 kB
Release files / restful_checker-3.2.0.tar.gz
| Download URL | restful_checker-3.2.0.tar.gz |
|---|---|
| Size | 86.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05cc23a02cb945e0259cdd7392bc0e4fa710ecf5eff29ce1ed5f515482bc8ccf
|
|
BLAKE2b-256 checksum How to use checksums |
dc17130e6db8a9e1c01ec16cac18bd2e4aa1efe2040a301f47df383b5f7239d2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|
Release files / restful_checker-3.2.0-py3-none-any.whl
| Download URL | restful_checker-3.2.0-py3-none-any.whl |
|---|---|
| Size | 55.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6514213b09820f9cf115b904fb6c9dace1989f55a8f826fdc3894df2a02fb937
|
|
BLAKE2b-256 checksum How to use checksums |
39d78353237e09369d8f9934b90ac66fde4fee4dec4d551733a46b39d78c13e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|