Skip to main content

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 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aho_sdk-0.1.1.tar.gz (44.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aho_sdk-0.1.1-py3-none-any.whl (55.7 kB view details)

Uploaded Python 3

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

Hashes for aho_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8500b2b77266f57964a4a465fa84a2e21b757f01958d22cb6ddfb4d2b77e664b
MD5 1530814389cc05d741ee10d680908531
BLAKE2b-256 ed0d3da26c5aa9cedec4bae1184c26f14d193a81772d0e69fd14d2dbf882c11c

See more details on using hashes here.

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

Hashes for aho_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 30d64b00206a65426df9e48ae8dbd729cbb903698eb7dcbea7c53022e4d946f4
MD5 04e099a36985018de27d09570a2bb726
BLAKE2b-256 2061a9201e4900a716a89d5839f44a5ff778cfd6ec51c2d76351d5992be682d2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page