Skip to main content

Installation

pip install keystoneos
Requires Python 3.10+. Dependencies: httpx (HTTP client) and pydantic (type validation).

Initialize

from keystoneos import KeystoneClient

client = KeystoneClient(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    environment="production",
)

# Use as async context manager for clean connection handling
async with client:
    settlements = await client.settlements.list()
The async client is recommended for production. The sync client wraps the async client for scripts, notebooks, and frameworks without native async support.

Configuration

OptionTypeDefaultDescription
client_idstrrequiredAuth0 M2M client ID
client_secretstrrequiredAuth0 M2M client secret
environmentstr"production""development", "staging", or "production"
base_urlstrper environmentOverride API base URL
auth_domainstrper environmentOverride Auth0 domain
audiencestrper environmentOverride Auth0 audience
timeoutfloat30.0Request timeout in seconds
retryRetryConfig3 retries, 0.5s baseRetry configuration

RetryConfig

Override retry behavior:
from keystoneos import RetryConfig

client = KeystoneClient(
    client_id="...",
    client_secret="...",
    retry=RetryConfig(
        max_retries=5,
        base_delay=1.0,
        max_delay=60.0,
        retryable_status_codes={429, 500, 502, 503, 504},
    ),
)

Resources

client.instructions   # Submit, get, list, cancel bilateral instructions
client.settlements    # Create, get, list, events, compliance decisions
client.templates      # List and get settlement templates (read-only)
client.webhooks       # CRUD + test, rotate secret, delivery logs, signature verification
client.environments   # CRUD + deactivate platform environments
client.compliance     # approve() and reject() convenience methods

Idempotency Keys

key = client.generate_idempotency_key()            # "ks-{uuid4}"
key = client.generate_idempotency_key("my-prefix")  # "my-prefix-{uuid4}"

# Safe to retry - same key returns existing resource
settlement = await client.settlements.create({
    "idempotency_key": key,
    # ...
})

Pagination

All list methods return PaginatedResponse[T] with convenience properties:
result = await client.settlements.list(limit=20)

print(result.items)       # list[Settlement]
print(result.total)       # Total count
print(result.has_more)    # True if more pages exist
print(result.next_offset) # Offset for next page

# Iterate through all pages
offset = 0
while True:
    page = await client.settlements.list(limit=50, offset=offset)
    for settlement in page.items:
        process(settlement)
    if not page.has_more:
        break
    offset = page.next_offset