x403
The x403 protocol for Python: the objects, RFC 8785 canonical JSON, ES256 signing and verifying, the HTTP binding, a sync and an async client for any authority, and a FastAPI gate. One dependency, cryptography. Python 3.10+.
pip install x403 # objects, canonical JSON, signing, verifying
pip install "x403[client]" # plus the HTTP client (httpx)
pip install "x403[fastapi]" # plus the FastAPI gate
Ask before you execute
from x403 import X403
x403 = X403(authority="https://api.kredit.sh", api_key=os.environ["KREDIT_API_KEY"])
decision = x403.decide(
direction="inbound",
policy_id="shop-checkout-v1",
payment={"type": "payment", "amount": "189.00", "currency": "USD", "rail": "card", "executor": {"id": "shop.example"}},
actor={"agent": {"status": "asserted", "id": "did:key:z6Mk..."}},
evidence=[{"type": "kredit.passport", "ref": passport_hash, "inline": passport}],
budget_ms=150,
)
if decision["decision"] == "allow":
... # within decision["constraints"]
else:
... # decision["http_status"], decision["reasons"], decision.get("escalation")
Verify offline
result = x403.verify(decision) # keys fetched once from authority.json
assert result, result.reason
Or without a client, against keys you already hold:
from x403 import verify_decision
ok = verify_decision(decision, jwks)
FastAPI
from fastapi import Depends, FastAPI
from x403 import AsyncX403
from x403.middleware.fastapi import X403Gate, install, post_receipt
app = FastAPI()
install(app)
authority = AsyncX403("https://api.kredit.sh", api_key=os.environ["KREDIT_API_KEY"])
gate = X403Gate(
authority,
payment=lambda request: {"type": "payment", "amount": "189.00", "currency": "USD", "rail": "card", "executor": {"id": "shop.example"}},
policy_id="shop-checkout-v1",
budget_ms=150,
)
@app.post("/checkout")
async def checkout(decision: dict = Depends(gate)):
auth = await charge(decision["constraints"])
await post_receipt(authority, decision, executed=True, execution={"rail": "card", "ref": auth.id},
executor={"id": "did:web:shop.example", "kid": kid}, private_jwk=private_jwk)
return {"ok": True}
On allow the route receives the decision. On anything else the gate answers with the decision's http_status, the decision as the body and X403-Decision on the response. If the authority cannot be reached it fails closed with an executor-signed authority_timeout decision.
Sign your side
from x403 import generate_key, sign_receipt, decision_hash
pair = generate_key() # publish pair.public_jwk at /.well-known/x403/jwks.json
receipt = sign_receipt({"decision_ref": d["id"], "decision_hash": decision_hash(d), "executed": True,
"executor": {"id": "did:web:shop.example", "kid": pair.kid}}, pair.private_jwk)
Status codes
status_for(decision) implements section 6.3 of the spec. The decision already carries http_status; use the function to pin the table in your own tests.
Apache-2.0. Spec and registry: https://github.com/kreditsh/x403
Metadata
Release files for x403 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 | Actions |
|---|---|---|---|---|
| x403-0.1.0.tar.gz | 21.3 kB | Without provenance | Details for x403-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| x403-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for x403-0.1.0-py3-none-any.whl |
Total release size: 41.5 kB
Release files / x403-0.1.0.tar.gz
| Download URL | x403-0.1.0.tar.gz |
|---|---|
| Size | 21.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4de48d43fbe7b426eaed081bc2375db779c190ad008b4cbfa4cd5c657cb5cfcb
|
|
BLAKE2b-256 checksum How to use checksums |
0bf4bddf463a53b2988e7fcc4c317bbe5ed60c6c4a5ddb639d02cd897c90e593
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Release files / x403-0.1.0-py3-none-any.whl
| Download URL | x403-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6e0320fe9fec1825d02ef7948a0d566065bf9f7b68b1ad30edd7fc4395ee5b27
|
|
BLAKE2b-256 checksum How to use checksums |
e25c0b599e92cac2d366379e4b76d997d7a94826fe3a4035aafa622acb1b2848
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Security for x403 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.