Skip to main content

Python SDK

The Python SDK provides helpers for the full pre-execution authorization flow: create a client, authorize an action, handle the three outcomes, and verify the permit before execution.

Install

pip install veritrellis

Requires Python 3.9 or later.

Quick reference

SymbolPurpose
Client(...)Initialize a scoped client
client.authorize(...)Submit an action for authorization
client.verify_permit(permit)Verify a permit JWT
client.poll_permit(request_id)Poll for a pending permit

Create a client

client.py
import os
from veritrellis import Client

client = Client(
api_key=os.environ["VERITRELLIS_API_KEY"],
workspace_id=os.environ["VERITRELLIS_WORKSPACE_ID"],
environment="sandbox", # "sandbox" | "production"
api_url="https://api.veritrellis.ai",
)

Configuration

OptionTypeRequiredDescription
api_keystrYesWorkspace API key (vt_sandbox_… or vt_prod_…)
workspace_idstrYesYour workspace ID (ws_…)
environmentstrYes"sandbox" or "production"; must match the API key
api_urlstrNoDefaults to https://api.veritrellis.ai

Authorize an action

Call this before any action that requires a permit. It contacts the Veritrellis API and returns one of three outcomes.

refund.py
result = client.authorize(
action_type="issue_refund",
resource_ref="cus_123",
payload={
"customer_id": "cus_123",
"amount": 75,
"currency": "EUR",
"reason": "customer request",
},
)

Handling the three outcomes

handle_outcomes.py
if result.decision == "allowed":
# Permit is ready — verify it before executing
claims = client.verify_permit(result.permit)
# Proceed with the action using verified claims
issue_refund(claims)

elif result.decision == "pending_approval":
# Save result.request_id and poll GET /v1/permits/:request_id
save_for_polling(result.request_id)

elif result.decision == "denied":
# Policy blocked this request — do not execute
raise RuntimeError(f"Action denied: {result.reason_code}")
Always verify the permit

Receiving a permit from authorize is not sufficient. You must call verify_permit before executing the action. Permits that fail verification must not unlock execution.

Request parameters

ParameterTypeRequiredDescription
action_typestrYesThe canonical action type (e.g. issue_refund)
resource_refstrYesIdentifier of the resource being acted on
payloaddictYesAction-specific fields; validated against shared schemas
actor_refstrNoID of the human or agent initiating the action
idempotency_keystrNoStable key for safe retries

Response shape

FieldPresent whenTypeDescription
decisionAlwaysstr"allowed", "pending_approval", or "denied"
request_idAlwaysstrUnique request identifier
permitallowed onlystrSigned ES256 permit JWT
reason_codedenied onlystrMachine-readable denial reason

Verify a permit

Verifies a permit JWT against the workspace JWKS. The client already holds the workspace ID and issuer, so it takes a single argument. Raises if the signature, issuer, audience, or expiry check fails.

verify.py
claims = client.verify_permit(result.permit)

The returned claims contains:

ClaimTypeDescription
substrRequest ID this permit is bound to
workspace_idstrWorkspace the permit was issued for
action_typestrAction type the permit authorizes
resource_refstrResource the permit is scoped to
iatintIssued-at timestamp (Unix)
expintExpiry timestamp (Unix)

Polling for a permit

When decision is pending_approval, poll until the request resolves:

poll.py
permit = client.poll_permit(result.request_id)
# Ready — verify before executing
claims = client.verify_permit(permit)

poll_permit returns the permit once approved, and raises if the request is denied or expires.


Environment variables

VariableRequiredDescription
VERITRELLIS_API_KEYYesAPI key from the admin app
VERITRELLIS_WORKSPACE_IDYesWorkspace ID from the admin app
Using .env files

Both the API key and workspace ID are available in the admin app under Settings > API keys. The sandbox and production environments have separate keys.


Source