Python SDK for the Aho Verifiable Credentials API
Project description
aho_sdk Python SDK
Official Python SDK for the Aho Verifiable Credentials API.
Installation
# Basic installation (sync only)
pip install aho-sdk
# With async support
pip install aho-sdk[async]
# With validation (Pydantic models)
pip install aho-sdk[validation]
# All features
pip install aho-sdk[all]
Quick Start
import os
from aho_sdk import Issuer
# Initialize the Issuer client
issuer = Issuer(api_key=os.environ['AHO_ISSUER_API_KEY'])
# Issue a credential
credential = issuer.credentials.create(
schema_uuid='your-schema-uuid',
subject_identifier='user@example.com',
claims={
'name': 'Jane Doe',
'role': 'Engineer'
}
)
print(credential['uuid'])
Clients
The SDK provides the following clients:
| Client | Purpose | API Key Type |
|---|---|---|
Account |
Manage account settings, domains, and API keys | Account API Key |
System |
System health and status endpoints | System API Key |
Holder |
Manage holder credentials and presentations | Holder API Key |
Verifier |
Create presentation requests and verify credentials | Verifier API Key |
Issuer |
Issue and manage verifiable credentials | Issuer API Key |
Schemas |
Browse and retrieve credential schemas | Schemas API Key |
Unauthenticated |
Public endpoints (no authentication required) | None (public) |
Usage Examples
Issuing Credentials
from aho_sdk import Issuer
issuer = Issuer(api_key=os.environ['AHO_ISSUER_API_KEY'])
# List all schemas
schemas = issuer.schemas.list()
for schema in schemas:
print(schema['name'])
# Create a schema
schema = issuer.schemas.create(
name='EmployeeBadge',
claims=[
{'name': 'employee_id', 'type': 'string', 'required': True},
{'name': 'department', 'type': 'string', 'required': True},
{'name': 'hire_date', 'type': 'date', 'required': False}
]
)
# Issue a credential
credential = issuer.credentials.create(
schema_uuid=schema['uuid'],
subject_identifier='jane.doe@company.com',
claims={
'employee_id': 'EMP-12345',
'department': 'Engineering',
'hire_date': '2024-01-15'
}
)
# Revoke a credential
issuer.credentials.revoke(uuid=credential['uuid'], reason='Employee departed')
Verifying Credentials
from aho_sdk import Verifier
verifier = Verifier(api_key=os.environ['AHO_VERIFIER_API_KEY'])
# Create a presentation request
request = verifier.requests.create(
name='Employment Verification',
query_format='dcql',
credentials=[
{
'id': 'employee_badge',
'format': 'vc+sd-jwt',
'claims': [
{'path': ['employee_id']},
{'path': ['department']}
]
}
]
)
# Get the QR code for the request (supports 'png', 'svg' formats)
qr = verifier.requests.qr_code(uuid=request['uuid'], output_format='svg')
# List responses to the request
responses = verifier.responses.list(request_uuid=request['uuid'])
Managing Holder Credentials
from aho_sdk import Holder
holder = Holder(api_key=os.environ['AHO_HOLDER_API_KEY'])
# List credentials
credentials = holder.credentials.list(status='active')
# Create a presentation (selective disclosure)
presentation = holder.presentations.create(
credential_uuid='credential-uuid',
disclosed_claims=['name', 'department']
)
Account Management
from aho_sdk import Account
account = Account(api_key=os.environ['AHO_API_KEY'])
# Manage domains
domains = account.domains.list()
account.domains.verify(id=domain['id'])
# Manage signing keys
keys = account.signing_keys.list()
account.signing_keys.rotate(id=key['id'])
# Configure webhooks
account.webhooks.create(
url='https://your-app.com/webhooks/aho',
events=['credential.issued', 'credential.revoked']
)
Pagination
List methods return Page objects with built-in iteration:
# Iterate through all pages automatically
for credential in issuer.credentials.list():
print(credential['uuid'])
# Or handle pages manually
page = issuer.credentials.list(per_page=50)
while page:
for credential in page.data:
print(credential['uuid'])
page = page.next_page()
# Collect all items
all_credentials = list(issuer.credentials.list())
File Uploads
For endpoints that accept file uploads:
# Upload a file
issuer.media.upload(
file=open('document.pdf', 'rb'),
metadata={'description': 'Employee contract'}
)
# The SDK auto-detects MIME types from file extensions
# You can also pass a Path:
from pathlib import Path
issuer.media.upload(file=Path('document.pdf'))
Binary Responses
Some endpoints return binary data (images, PDFs):
# Get QR code as PNG
png_data = verifier.requests.qr_code(uuid='...', output_format='png')
with open('qr.png', 'wb') as f:
f.write(png_data)
# Get QR code as SVG
svg_data = verifier.requests.qr_code(uuid='...', output_format='svg')
with open('qr.svg', 'w') as f:
f.write(svg_data.decode('utf-8'))
Error Handling
from aho_sdk import (
Issuer,
ValidationError,
AuthenticationError,
NotFoundError,
RateLimitError,
ApiError
)
try:
issuer.credentials.create(invalid_params)
except ValidationError as e:
# 422 - Validation failed
for error in e.field_errors:
print(f"{error['field']}: {error['hint']}")
except AuthenticationError as e:
# 401 - Invalid API key
print("Check your API key")
except NotFoundError as e:
# 404 - Resource not found
print(f"Resource not found: {e.message}")
except RateLimitError as e:
# 429 - Rate limited (SDK auto-retries with exponential backoff)
print(f"Retry after {e.retry_after} seconds")
except ApiError as e:
# Other API errors
print(f"Error {e.status_code}: {e.message}")
print(f"Request ID: {e.request_id}")
Error Classes
| Error Class | HTTP Status | Description |
|---|---|---|
AuthenticationError |
401 | Invalid or missing API key |
ForbiddenError |
403 | Insufficient permissions |
NotFoundError |
404 | Resource not found |
ConflictError |
409 | Resource conflict |
ValidationError |
422 | Request validation failed |
RateLimitError |
429 | Rate limit exceeded |
ServerError |
5xx | Server-side error |
NetworkError |
- | Connection/timeout error |
ApiError |
* | Base class for all API errors |
Rate Limiting
The SDK automatically handles rate limits with exponential backoff:
- Idempotent methods (GET, DELETE, PUT): Auto-retry up to 3 times
- Non-idempotent methods (POST, PATCH): Only retry with idempotency key
# Use idempotency keys for safe retries on POST/PATCH
issuer.credentials.create(
schema_uuid='...',
claims={...},
idempotency_key='unique-request-id'
)
Configuration
import logging
# Custom configuration
issuer = Issuer(
api_key=os.environ['AHO_ISSUER_API_KEY'],
base_url='https://api.aho.com', # Custom base URL
timeout=60, # Request timeout in seconds
logger=logging.getLogger('aho') # Enable debug logging
)
Async Support
The SDK provides async versions of all clients. Install with async support:
pip install aho-sdk[async]
Then use the async clients:
import asyncio
from aho_sdk import AsyncIssuer
async def main():
# Use async context manager for automatic cleanup
async with AsyncIssuer(api_key=os.environ['AHO_ISSUER_API_KEY']) as issuer:
# All methods are async
credentials = await issuer.credentials.list()
# Async iteration through pages
async for credential in credentials:
print(credential['uuid'])
# Or await individual operations
credential = await issuer.credentials.get(uuid='...')
asyncio.run(main())
Async clients available:
AsyncAccount- Async version ofAccountAsyncSystem- Async version ofSystemAsyncHolder- Async version ofHolderAsyncVerifier- Async version ofVerifierAsyncIssuer- Async version ofIssuerAsyncSchemas- Async version ofSchemasAsyncUnauthenticated- Async version ofUnauthenticated
Requirements
- Python 3.9+
- httpx (for async support, optional)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aho_sdk-0.1.1.tar.gz.
File metadata
- Download URL: aho_sdk-0.1.1.tar.gz
- Upload date:
- Size: 44.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8500b2b77266f57964a4a465fa84a2e21b757f01958d22cb6ddfb4d2b77e664b
|
|
| MD5 |
1530814389cc05d741ee10d680908531
|
|
| BLAKE2b-256 |
ed0d3da26c5aa9cedec4bae1184c26f14d193a81772d0e69fd14d2dbf882c11c
|
File details
Details for the file aho_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: aho_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 55.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30d64b00206a65426df9e48ae8dbd729cbb903698eb7dcbea7c53022e4d946f4
|
|
| MD5 |
04e099a36985018de27d09570a2bb726
|
|
| BLAKE2b-256 |
2061a9201e4900a716a89d5839f44a5ff778cfd6ec51c2d76351d5992be682d2
|