Documentation Index
Fetch the complete documentation index at: https://docs.truthlocks.com/llms.txt
Use this file to discover all available pages before exploring further.
Requirements: Python 3.9 or later. Uses httpx for HTTP requests.
Installation
Quick Start
from truthlock import TruthlockClient, Algorithm, Verdict
client = TruthlockClient(api_key="your-api-key")
# Create an issuer
issuer = client.issuers.create(
name="My Organization",
legal_name="My Organization Inc.",
)
# Register a key
key = client.keys.register(
issuer_id=issuer.id,
kid="key-1",
alg=Algorithm.ED25519.value,
public_key_b64url="your-base64url-public-key",
)
# Mint an attestation
attestation = client.attestations.mint(
issuer_id=issuer.id,
kid="key-1",
alg=Algorithm.ED25519.value,
payload_b64url="base64url-encoded-payload",
)
print(f"Attestation: {attestation.attestation_id}")
# Verify
result = client.verify.verify_online(
attestation_id=attestation.attestation_id,
)
if result.verdict == Verdict.VALID:
print("Verified successfully")
Client Configuration
client = TruthlockClient(
api_key="your-api-key",
base_url="https://api.truthlocks.com", # default
environment="production", # or "sandbox"
timeout=30.0, # seconds
max_retries=3, # auto-retry on failures
idempotency_prefix="my-app", # prefix for auto-generated idempotency keys
)
Idempotency keys
The SDK generates an Idempotency-Key header automatically on every write operation (mint, revoke, supersede), making retries safe by default. If a request fails and is retried, the server returns the original response instead of performing the action twice.
When multiple applications share the same tenant, set idempotency_prefix to namespace the auto-generated keys and prevent collisions:
# Service A
billing_client = TruthlockClient(
api_key="tl_live_...",
idempotency_prefix="billing-svc",
)
# Service B
onboarding_client = TruthlockClient(
api_key="tl_live_...",
idempotency_prefix="onboarding-svc",
)
With these prefixes, a key generated by the billing service looks like billing-svc_<uuid>, while onboarding produces onboarding-svc_<uuid> — so concurrent requests from different services never conflict.
Idempotency keys expire after 24 hours. If you omit idempotency_prefix, keys are generated without a prefix and are still unique per request.
Retry behavior
When max_retries is set (default: 3), the SDK automatically retries failed requests using exponential backoff with jitter.
What gets retried
The SDK retries when all of the following are true:
- The HTTP status code is retryable:
408, 429, 500, 502, 503, or 504
- The retry count has not exceeded
max_retries
Responses with 400, 401, 403, 404, or 409 are not retried.
Backoff schedule
| Attempt | Base delay | With jitter (approx.) |
|---|
| 1st retry | 100 ms | 80–120 ms |
| 2nd retry | 200 ms | 160–240 ms |
| 3rd retry | 400 ms | 320–480 ms |
The delay doubles on each attempt, capped at 2 seconds. If the API returns a 429 with a Retry-After header, the SDK waits the server-specified duration instead.
Disabling retries
client = TruthlockClient(
api_key="your-api-key",
max_retries=0, # No automatic retries
)
The SDK generates idempotency keys automatically for write operations, so retries for mint and revoke calls are safe. See idempotency keys to configure a prefix for multi-service environments.
Error handling
from truthlock import TruthlockClient, TruthlockError, NotFoundError
client = TruthlockClient(api_key="your-key")
try:
att = client.attestations.get("nonexistent-id")
except NotFoundError:
print("Attestation not found")
except TruthlockError as e:
print(f"API error {e.status_code}: {e.error_code} - {e}")
Revoke an attestation
Permanently invalidate an attestation. Once revoked, any verification check returns REVOKED. This action cannot be undone — if you need to issue an updated credential instead, use supersede.
from truthlock import TruthlockClient, Verdict
client = TruthlockClient(api_key="tl_live_...")
revoked = client.attestations.revoke(
"660e8400-e29b-41d4-a716-446655440001",
reason="Certificate holder no longer employed",
)
print(f"Status: {revoked['status']}") # "REVOKED"
print(f"Revoked at: {revoked['revoked_at']}")
# Subsequent verifications reflect the revocation
check = client.verify.verify_online(
attestation_id="660e8400-e29b-41d4-a716-446655440001",
)
print(f"Verdict: {check.verdict}") # "REVOKED"
Revocation is permanent and recorded in the transparency log. You cannot undo it. Use supersede if you need to replace a credential with an updated version.
Supersede an attestation
Replace an existing attestation with an updated version. The original is marked as SUPERSEDED and linked to the new one, creating an auditable version chain.
import base64
import json
from truthlock import TruthlockClient
client = TruthlockClient(api_key="tl_live_...")
# Supersede an attestation with updated claims
updated_payload = base64.urlsafe_b64encode(
json.dumps({
"student_name": "Jane Doe",
"degree_type": "Master of Science", # Updated from Bachelor to Master
}).encode()
).decode().rstrip("=")
result = client.attestations.supersede(
attestation_id="660e8400-e29b-41d4-a716-446655440001", # Original attestation ID
payload_b64url=updated_payload,
)
print(f"Old attestation status: {result['old']['status']}") # "SUPERSEDED"
print(f"New attestation ID: {result['new']['attestation_id']}")
Both the original and new attestation remain in the transparency log. Verifiers can trace the full chain using the superseded_by_attestation_id field on the original.
Context Manager
Use the client as a context manager to ensure proper cleanup of HTTP connections.
with TruthlockClient(api_key="your-key") as client:
issuers = client.issuers.list()
for issuer in issuers:
print(f"{issuer.name} ({issuer.id})")
API Reference
Issuers
client.issuers.create(name, ...) - Create a new issuer
client.issuers.list(limit, offset) - List issuers
client.issuers.get(issuer_id) - Get issuer by ID
client.issuers.trust(issuer_id) - Trust an issuer
Attestations
client.attestations.mint(...) - Mint a new attestation
client.attestations.get(id) - Get attestation details
client.attestations.list(limit, offset) - List attestations
client.attestations.revoke(id, reason) - Revoke an attestation
client.attestations.supersede(attestation_id, payload_b64url) - Supersede an attestation
client.attestations.proof_bundle(id) - Get proof bundle
Receipts
client.receipts.mint(req) - Mint a signed receipt
client.receipts.get(receipt_id) - Get receipt by ID
client.receipts.list(filter?) - List receipts with optional filters
client.receipts.revoke(receipt_id, reason?) - Revoke a receipt
client.receipts.list_types() - List available receipt types
client.receipts.get_type(name) - Get a receipt type by name
client.receipts.get_proof_bundle(receipt_id) - Get proof bundle
client.receipts.verify(receipt_id) - Verify a receipt
client.receipts.search(**kwargs) - Search receipts
client.receipts.export(format, filters?) - Queue bulk export
client.receipts.get_export(export_id) - Get export job status
client.receipts.redact(receipt_id) - Redact receipt payload
Verify
client.verify.verify_online(attestation_id, payload_b64url) - Verify attestation online
Audit
client.audit.query(params) - Query audit events with filters
client.audit.export(data) - Start an async audit log export
Governance
client.governance.list_requests() - List governance requests
client.governance.create_request(data) - Create a governance request
client.governance.approve_request(id) - Approve a pending request
client.governance.execute_request(id) - Execute an approved request
Querying audit logs
Retrieve audit events to track API activity, monitor security events, and generate compliance reports. Filter by action, actor, resource, or time range.
from truthlock import TruthlockClient
client = TruthlockClient(api_key="tl_live_...")
# Query recent attestation events
events = client.audit.query(
action="attestation.mint",
from_date="2026-01-01T00:00:00Z",
to_date="2026-01-31T23:59:59Z",
limit=100,
)
for event in events:
print(f"[{event['timestamp']}] {event['action']} by {event['actor_id']}")
# Export audit logs for compliance
export_job = client.audit.export(
start_date="2026-01-01",
end_date="2026-01-31",
format="csv",
)
print(f"Export started: {export_job['id']} (status: {export_job['status']})")
See the audit API reference for the full list of filter parameters.
Governance workflows
Manage formal issuer actions — suspend, revoke, reinstate, and change trust tier — through a multi-party approval workflow. Create a request, collect approvals from authorized reviewers, then execute.
from truthlock import TruthlockClient
client = TruthlockClient(api_key="tl_live_...")
# Create a governance request to suspend an issuer
req = client.governance.create_request(
action="suspend",
issuer_id="issuer-uuid",
reason="Compliance review pending",
)
print(f"Request created: {req['id']} (status: {req['status']})")
# Another authorized user approves the request
client.governance.approve_request(req["id"])
# Execute the approved request
result = client.governance.execute_request(req["id"])
print(f"Executed: {result['id']} — issuer is now {result['issuer_status']}")
# List all governance requests
requests = client.governance.list_requests()
for r in requests:
print(f"[{r['status']}] {r['action']} {r['issuer_id']} — {r['reason']}")
See the governance API reference for the full request and response schemas.
Audit queries and exports
Query audit events with filters and export logs for compliance reporting. Use client.audit.query() to search events and client.audit.export() to start an asynchronous export job.
from truthlock import TruthlockClient
client = TruthlockClient(api_key="tl_live_...")
# Query recent attestation events
events = client.audit.query(
action="attestation.mint",
from_date="2026-06-01T00:00:00Z",
to_date="2026-06-30T23:59:59Z",
limit=100,
)
for evt in events["data"]:
print(f"[{evt['timestamp']}] {evt['action']} by {evt['actor_id']}")
# Start an async export for compliance
export_job = client.audit.export(
from_date="2026-01-01T00:00:00Z",
to_date="2026-06-30T23:59:59Z",
report_type="soc2", # "soc2", "gdpr", "hipaa", or omit for raw
format="json",
)
print(f"Export started: {export_job['id']} (status: {export_job['status']})")
See audit logs for the full event structure, filter parameters, and retention policies.
Receipt operations
Mint, verify, search, export, and redact cryptographically signed receipts. See the receipts guide for an overview of receipt types and the full lifecycle.
from truthlock import TruthlockClient, MintReceiptRequest
client = TruthlockClient(api_key="tl_live_...")
# Mint a payment receipt
receipt = client.receipts.mint(MintReceiptRequest(
issuer_id="your-issuer-id",
kid="ed-key-2026",
alg="Ed25519",
receipt_type="payment_receipt",
subject="customer@example.com",
payload={
"amount": 5000,
"currency": "USD",
"provider": "stripe",
"provider_reference": "ch_3Px...",
},
))
# Verify a receipt
result = client.receipts.verify(receipt.receipt_id)
print(f"Verdict: {result['verdict']}") # "VALID"
# Download a proof bundle for offline verification
bundle = client.receipts.get_proof_bundle(receipt.receipt_id)
# Search receipts
results = client.receipts.search(
q="stripe",
receipt_type="payment_receipt",
from_date="2026-01-01T00:00:00Z",
)
# Export receipts as JSON
export_job = client.receipts.export(
format="json",
filters={"receipt_type": "payment_receipt"},
)
# Poll for completion
completed = client.receipts.get_export(export_job["id"])
if completed["status"] == "complete":
print(f"Download: {completed['download_url']}")
# Redact PII from a receipt (permanent, for GDPR erasure requests)
client.receipts.redact(receipt.receipt_id)
See the receipts API reference for the full request and response schemas.