API Diff X
Git diff for API behavior.
apidiffx captures API responses, compares snapshots, detects structural changes, classifies breaking changes, and provides CI-friendly exit codes.
Install
python -m pip install -e .
Capture
apidiffx capture https://example.com/api/users --output baseline.json
Compare
apidiffx compare baseline.json current.json
JSON report:
apidiffx compare baseline.json current.json --format json
A breaking change returns exit code 1; otherwise 0.
Python
from apidiffx import compare
result = compare("baseline.json", "current.json")
print(result.has_breaking_changes)
for change in result.changes:
print(change.path, change.change_type, change.severity)
What v0.1 detects
- Added JSON fields
- Removed JSON fields
- Nested object changes
- Array element changes
- Type changes
- HTTP method and URL changes
- HTTP success-to-error status changes
- Header additions/removals
- Sensitive-data masking
- Text and JSON reports
- CI-friendly exit codes
Project direction
The long-term goal is to make API compatibility work like a Git diff:
old API behavior
↓
apidiffx
↓
new API behavior
↓
structural diff
↓
breaking-change analysis
Development
python -m pip install -e .
python -m pytest -q
License
MIT
OpenAPI / Swagger contract diff
Compare two OpenAPI documents:
apidiffx openapi old.json new.json
JSON output:
apidiffx openapi old.yaml new.yaml --format json
YAML support is optional:
python -m pip install -e ".[yaml]"
The OpenAPI diff currently detects:
- Removed endpoints
- Added endpoints
- Removed operations
- Added operations
- Removed response definitions
- Added response definitions
- Removed response properties
- Added response properties
- Required properties added/removed
- Parameter additions/removals
- Parameters becoming required
- Schema type changes
- Array item schema changes
- Selected enum/format/pattern changes
pytest integration
Install development/test dependencies:
python -m pip install -e ".[dev]"
Use the compatibility assertion directly:
from apidiffx import assert_compatible
def test_users_api(client):
response = client.get("/api/users")
assert_compatible(response, "snapshots/users.json")
For a requests.Response, apidiffx reads the request method, URL, status,
headers, and JSON/text body automatically.
You can also save a refreshed snapshot after a successful comparison:
assert_compatible(
response,
"snapshots/users.json",
snapshot_path="snapshots/users-new.json",
)
Authentication and request configuration
Real-world APIs can be captured with custom headers, Bearer tokens, API keys, query parameters, and request bodies.
Examples:
apidiffx capture https://api.example.com/users \
--header "Accept=application/json" \
--bearer-token "${API_TOKEN}" \
--output baseline.json
API key:
apidiffx capture https://api.example.com/users \
--api-key "${API_KEY}" \
--api-key-header "X-API-Key"
Query parameters:
apidiffx capture https://api.example.com/users \
--param "page=1" \
--param "limit=20"
POST JSON:
apidiffx capture https://api.example.com/users \
--method POST \
--header "Content-Type=application/json" \
--json '{"name":"John","email":"john@example.com"}'
Basic authentication:
apidiffx capture https://api.example.com/users \
--basic-user "${API_USER}" \
--basic-password "${API_PASSWORD}"
Environment variables use the ${VARIABLE} syntax. Values are resolved from
the process environment, and sensitive response fields are masked before the
snapshot is written.
Multi-endpoint configuration
Create apidiffx.yaml:
name: patient-api
base_url: https://api.example.com
headers:
Accept: application/json
auth:
type: bearer
token: ${API_TOKEN}
endpoints:
- name: users
method: GET
path: /users
- name: patient
method: GET
path: /patients/123
params:
include_history: true
- name: create_user
method: POST
path: /users
json:
name: John
email: ${TEST_EMAIL}
Install YAML support:
pip install "apidiffx[yaml]"
Then create/update all baselines:
apidiffx update
Run the complete compatibility test:
apidiffx test
apidiffx test checks every configured endpoint and exits with code 1 when a breaking response change is detected, making it suitable for CI/CD. Environment variables can be referenced with ${VAR_NAME} so credentials do not need to be committed to the configuration file.
Endpoint inventory changes
When you run apidiffx update, API Diff X also records the configured endpoint inventory in .apidiffx/manifest.json. On later apidiffx test runs it can detect contract-level inventory changes:
- Removed endpoint — breaking
- Changed method/path for an existing endpoint — breaking
- Added endpoint — non-breaking
- Renamed configuration entry with the same method/path — non-breaking; the existing response baseline is reused
This keeps endpoint changes separate from response-body diffs and avoids noisy field-level differences when an endpoint itself has moved.
CI and HTML reports
apidiffx test is CI-friendly: it exits with code 1 when configured breaking changes are detected and 2 when a baseline/configuration is missing or invalid.
Generate a standalone HTML report:
apidiffx test --report apidiffx-report.html
The report contains endpoint status, change counts, breaking changes, and detailed field-level differences. A GitHub Actions example is included at .github/workflows/apidiffx.yml.
For JSON output suitable for other CI systems:
apidiffx test --format json --report apidiffx-report.json
Metadata
Release files for apidiffx 0.1.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 | |
|---|---|---|---|
| apidiffx-0.1.0.tar.gz | 23.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apidiffx-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.0 kB
Release files / apidiffx-0.1.0.tar.gz
| Download URL | apidiffx-0.1.0.tar.gz |
|---|---|
| Size | 23.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
87ff896f1bd6275a3ec6dddf332a8c465c77eacf0aa21071ba6896c44c8030a6
|
|
BLAKE2b-256 checksum How to use checksums |
469d04fe59b9a9c55c6c63c56dd421d88fe64bcbb8f990b8978e915a9f3f5981
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.10
|
Release files / apidiffx-0.1.0-py3-none-any.whl
| Download URL | apidiffx-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6ae706052a9cf2413f8611f9fbd2f1e48c763cd51983aa90152bf31e3a65f70
|
|
BLAKE2b-256 checksum How to use checksums |
b42b665312542d8a36901e3cba1050deea06299c69525acfeafe2dbe47746035
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.10
|