Skip to main content

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 of Account
  • AsyncSystem - Async version of System
  • AsyncHolder - Async version of Holder
  • AsyncVerifier - Async version of Verifier
  • AsyncIssuer - Async version of Issuer
  • AsyncSchemas - Async version of Schemas
  • AsyncUnauthenticated - Async version of Unauthenticated

Requirements

  • Python 3.9+
  • httpx (for async support, optional)

License

MIT

Release files for aho-sdk 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aho-sdk 0.1.2
File Size Uploaded
aho_sdk-0.1.2.tar.gz 45.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aho-sdk 0.1.2
File Interpreter ABI Platform
aho_sdk-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 102.0 kB

Release files / aho_sdk-0.1.2.tar.gz

Download URL aho_sdk-0.1.2.tar.gz
Size 45.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cde2f4a350285d75e75b612e3ba1be0a0c554540b56615eed8d0a7dc287e6347
BLAKE2b-256 checksum
How to use checksums
282343d942b7018f5a2894008b826287cd8ffc6e3c9fc7d9c12506f59741d3ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / aho_sdk-0.1.2-py3-none-any.whl

Download URL aho_sdk-0.1.2-py3-none-any.whl
Size 56.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8dc0523d57f207daef0c330a14a25dd96f51047bdaa5d856af2cf8840995d109
BLAKE2b-256 checksum
How to use checksums
8fda129626e3718a9cc09f701d8e2af63488342cb779e58d0c1c9394acde17de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page