VerdifaxClient
The synchronous Python client. Wraps an
httpx.Client with a connection pool, applies
client-side validation before every call, and translates HTTP errors
into a clean exception hierarchy.
Import
from verdifax import VerdifaxClient
Constructor
VerdifaxClient(
base_url: str | None = None,
api_key: str | None = None,
timeout: float = 30.0,
transport: httpx.BaseTransport | None = None,
)
| Argument | Default | Notes |
|---|---|---|
base_url | $VERDIFAX_API_URL or https://api.verdifax.com | Trailing slashes are stripped |
api_key | $VERDIFAX_API_KEY | Sent as X-Verdifax-Key header |
timeout | 30.0 seconds | Applied to every request |
transport | None | Inject a custom transport for tests (e.g. httpx.MockTransport) |
Methods
client.health() -> dict
client.attest(payload, program_id, route_id, registry_record_hash,
attested_context=None, reproducibility_context=None,
ai_output_text=None) -> AttestationReceipt
client.verify_run(run_id) -> VerifyResponse
client.verify(...) # raises UnsupportedOperationError since 0.6.0, see client.verify_run()
client.execute(payload, program_id, route_id, registry_record_hash) -> ExecutionManifest
client.close() -> None
verify_run() asks the server to re-derive a recorded run's manifest hash and compare it with the recorded seal; see client.verify_run().
execute() is a lower-level alternative to attest() that returns just the ExecutionManifest without the receipt envelope.
Context manager
with VerdifaxClient(api_key="vfx_...") as client:
receipt = client.attest(...)
# connection pool closed automatically
Environment variables
| Variable | Effect |
|---|---|
VERDIFAX_API_URL | Default base URL |
VERDIFAX_API_KEY | Default API key |
Explicit constructor arguments override env vars.
Connection reuse
For high-throughput servers, instantiate one VerdifaxClient at startup and reuse. Don't construct a new client per request, that re-creates the connection pool and triggers extra TCP handshakes.
Return types and exception handling
client.attest() returns an AttestationReceipt on success. When the orchestrator refuses or halts a run (a policy deny, a per-run budget halt, a cumulative budget halt, or any other stage failure), it answers HTTP 422 with an error_stage field, and the SDK raises StageError. Any other non-success response raises APIError, and a network failure raises ConnectionError:
from verdifax import VerdifaxClient, StageError, APIError
client = VerdifaxClient()
try:
receipt = client.attest(payload="...", program_id="...", ...)
print(receipt.manifest_hash) # OK run
except StageError as e:
print(f"Stage {e.stage} refused or halted the run: {e.message}")
print(e.response_body) # the orchestrator's full response, including any sealed receipt
except APIError as e:
print(f"HTTP {e.status_code}: {e.message}")
StageError is a subclass of APIError, so catch it first. Both carry status_code, message, and response_body; StageError adds stage, the name of the pipeline stage that refused the run.
client.execute() takes the same arguments as attest() and returns only the ExecutionManifest from the receipt.
