apifacts
A verified changelog of reality for AI agents. An open registry of typed, dated facts about what third-party machine interfaces (HTTP APIs, SDK packages, CLIs) actually do today, as opposed to what their docs say.
Why
Interfaces change, docs lag, and nobody tells the agent. Every session pays tokens to rediscover the
same traps: a 200 with an empty array instead of a 429, a rate limit reported as status: 0 in the
body, an SDK release that silently dropped a field. Documentation tools answer "give me the right docs";
apifacts answers "the docs are wrong about this endpoint right now, here is the verified difference".
Install
pip install apifacts-pytest # pytest plugin: a test failing on an HTTP error prints the known facts
uvx apifacts check https://api.stripe.com/v1/charges -X GET --status 401 # CLI (and library)
Both packages are on PyPI, carry the same version and ship together from one tag (release). The plugin sends nothing until a test fails.
How a fact is verified
- One fact per YAML file in
facts/<service>/, with a kind (error_meaning,rate_limit,breaking_change, ...), the exact error signal, a one-sentence claim, dimensions (env,plan,region,account_state) and evidence. - Truth comes only from deterministic probes: declarative HTTP steps and assertions that our runner executes on a schedule. No language model is called anywhere in the verification path.
- Fixes are data, not advice: members of a closed vocabulary with typed parameters (no free text, no shell, no foreign URLs), rendered to one English sentence by us.
- A probe in another environment never refutes a fact; it adds a dimension.
Calling check()
One endpoint answers and learns at the same time: the request is the contribution. Send the target and, optionally, the error you got; receive matching facts with typed fixes and what the probes observe. If the target matches a registered template, a normalized observation is stored (no bodies, headers, query strings or raw IPs).
curl -s https://apifacts.dev/v0/check \
-H 'Content-Type: application/json' \
-d '{"target": {"method": "POST", "url": "https://api.stripe.com/v1/payment_intents"},
"error": {"status": 400, "body_excerpt": "Keys for idempotent requests can only be used with the same parameters they were first used with."}}'
The response is never empty: facts, observed, and an unknown.reason when nothing matches.
Status
The API is live at https://apifacts.dev (/v0/check, /v0/services, /openapi.json, /healthz;
facts.baillot.dev is a legacy alias). The registry covers the services and facts listed in
pages/index.md, each fact page showing how it was established. Design contracts
live in docs/specs/.
Running your own copy: the API reads facts/ and services/ once, at startup, so after a git pull
restart it; ops/deploy.sh checks out, syncs and restarts in one step.
Contributing
Calling check() is contributing. Pull requests are for humans and API producers: see
CONTRIBUTING.md. Producer signatures are always free.
License
Code: MIT. Data (facts/ and the generated fact pages): CC BY 4.0.
Metadata
Release files for apifacts 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 | Provenance | |
|---|---|---|---|---|
| apifacts-0.1.0.tar.gz | 151.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apifacts-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 458.9 kB
Release files / apifacts-0.1.0.tar.gz
| Download URL | apifacts-0.1.0.tar.gz |
|---|---|
| Size | 151.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63df68bb85696b100fb5e0271c034523aa76b16a4c522c58cf72c7fa88181a9c
|
|
BLAKE2b-256 checksum How to use checksums |
cdd702a2eb6c480639597c8f257f7d832e62d9ad460335b9a5d0be278b629774
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / apifacts-0.1.0-py3-none-any.whl
| Download URL | apifacts-0.1.0-py3-none-any.whl |
|---|---|
| Size | 307.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ae04e81545c42e298f90441d3ebf5964ccffdab539f482bff8167f8bb3c46c0
|
|
BLAKE2b-256 checksum How to use checksums |
4714e94ab12ca01cae6dff29b8ab5ecec9fa64e855e2e6f75c924835c2f478ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for apifacts 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.