Skip to content

5.1. Call the same API from Python

This is a companion to the CLI request and Audit chapter. Use the same Auth Site, client key and exact GET /tutorial/echo grant. The Python application calls Auth over HTTPS; it does not call the private upstream directly.

Install the released Python SDK 0.2.3 from PyPI in a trusted workload environment:

Terminal window
python3 -m venv .venv
. .venv/bin/activate
python -m pip install trustplane-auth-sdk==0.2.3

In Control → Client Vault → Keys, select the active key and exact GET route, then open Inspect command. Set the following variables from your active signing profile. For TP_AUTH_BASE_URL, combine the profile’s https scheme and Auth Site authority; for TRUSTPLANE_CLIENT_PRIVATE_KEY_FILE, use the persistent private-key file created in chapter 4. Do not paste its contents into Control or a shell command.

Terminal window
export TRUSTPLANE_CLIENT_PRIVATE_KEY_FILE='./client-private-key'
export TP_AUTH_BASE_URL='https://<Auth Site authority>'
export TP_ISSUER='<issuer>'
export TP_KID='<kid>'
export TP_SUBJECT='<subject>'
export TP_TRUST_DOMAIN='<trust domain>'
export TP_AUDIENCE='<audience>'
export TP_ROUTE_ID='<route ID>'

Replace every angle-bracket value before running this complete Python request:

Terminal window
python - <<'PY'
import os
from pathlib import Path
from urllib.request import HTTPRedirectHandler, build_opener
from trustplane_auth import ProtectedClient, SigningProfile, private_key_from_base64url
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, *args, **kwargs):
return None
profile = SigningProfile.from_control({
"state": "active",
"key_origin": "manual",
"request_base_url": os.environ["TP_AUTH_BASE_URL"],
"kid": os.environ["TP_KID"],
"subject": os.environ["TP_SUBJECT"],
"trust_domain": os.environ["TP_TRUST_DOMAIN"],
"issuer": os.environ["TP_ISSUER"],
"route_id": os.environ["TP_ROUTE_ID"],
"canonical_route_id": os.environ["TP_ROUTE_ID"],
"route_match_type": "Exact",
"route_path": "/tutorial/echo",
"method": "GET",
"audience": os.environ["TP_AUDIENCE"],
})
key_text = Path(os.environ["TRUSTPLANE_CLIENT_PRIVATE_KEY_FILE"]).read_text().strip()
private_key = private_key_from_base64url(key_text)
client = ProtectedClient(profile, private_key)
prepared = client.prepare(
"GET", "/tutorial/echo", headers={"Content-Type": "application/json"}
)
with build_opener(NoRedirect()).open(prepared.request, timeout=20) as response:
print("HTTP", response.status)
print(response.read(200).decode("utf-8").strip())
print("Audit correlation JTI:", prepared.passport.jti)
PY

The Content-Type header is intentional even though this GET has no body: this tutorial Auth Site covers content-type and the SDK-generated x-trustplane-nonce in its request transcript. A request that omits the covered header is denied before the upstream is reached. For your own route, use the covered header set from its active profile; do not copy this header set blindly to a different site. The SDK generates the passport, nonce, body digest and proof. The standard-library transport above refuses redirects, so it does not forward TrustPlane credentials to a changed destination.

Open this walkthrough on YouTube

Expect HTTP 200 and the private sample echo response. In Control → Audit, scope to this site and the request time, open the allowed GET /tutorial/echo event, and compare only the printed short-lived JTI with Raw evidence → Sanitized raw evidence. Confirm the caller, exact route, Allowed — verified, target version and upstream HTTP 200. The JTI is an audit identifier, not a bearer token; do not print or record the passport or proof headers. If a request fails, inspect the Audit reason and the active profile’s covered headers before retrying. A 403 transcript_build_failed can mean a required covered header was omitted.

The isolated 14 October 2026 SDK verification using the released 0.2.3 wheel returned HTTP 200; its JTI matched the allowed, verified Audit event for the same caller, route and upstream response. No customer system was involved.

Next: Change access and troubleshoot.