Skip to main content

Python SDK Reference

The optropic Python SDK provides a type-safe, idempotent interface for interacting with the Optropic API.

Installationโ€‹

Install the SDK via pip:

pip install optropic

Quick Startโ€‹

from optropic import Optropic

client = Optropic(api_key="optr_live_...")

# Access resources
assets = client.assets.list_all()
keys = client.keys.retrieve(key_id="key_123")

Client Initializationโ€‹

Basic Usageโ€‹

from optropic import Optropic

client = Optropic(api_key="optr_live_abc123xyz")

With Custom Configurationโ€‹

from optropic import Optropic

client = Optropic(
api_key="optr_live_abc123xyz",
sandbox=False,
base_url="https://api.optropic.com",
timeout=30,
debug=True
)

Configuration Optionsโ€‹

Parametersโ€‹

ParameterTypeDefaultDescription
api_keystrRequiredYour API key (format: optr_live_* or optr_sandbox_*)
sandboxboolFalseWhether to use sandbox environment
base_urlstrhttps://api.optropic.comCustom API endpoint
timeoutint30Request timeout in seconds
headersdict{}Additional headers to include in all requests
debugboolFalseEnable debug logging

Retry Configurationโ€‹

client = Optropic(
api_key="optr_live_...",
retry_config={
"max_retries": 3,
"base_delay": 1.0, # seconds
"max_delay": 30.0 # seconds
}
)

Default retry config:

  • max_retries: 3
  • base_delay: 1.0 second
  • max_delay: 30.0 seconds

Available Resourcesโ€‹

The client provides access to the following resources as properties:

client.assets          # Asset management
client.keys # Key operations
client.keysets # Keyset management
client.audit # Audit logs
client.compliance # Compliance operations
client.schemas # Schema management
client.webhooks # Webhook configuration
client.documents # Document operations
client.provenance # Provenance tracking
client.m2m # Machine-to-machine interactions

Example: Accessing Resourcesโ€‹

# List all assets
assets = client.assets.list_all()

# Retrieve a specific key
key = client.keys.retrieve(key_id="key_123")

# Create a new keyset
keyset = client.keysets.create({
"name": "Production Keys",
"description": "Keys for production environment"
})

# Get audit logs
logs = client.audit.list_all(limit=100)

Retry Behaviorโ€‹

The SDK implements automatic retry logic with exponential backoff and jitter to handle transient failures.

Retry Strategyโ€‹

  • Formula: min(base_delay * 2^attempt, max_delay) + (delay * 0.5 * random())
  • Retried Status Codes: 429, 500, 502, 503, 504
  • Default Max Retries: 3

Example: Custom Retry Configurationโ€‹

client = Optropic(
api_key="optr_live_...",
retry_config={
"max_retries": 5,
"base_delay": 0.5,
"max_delay": 60.0
}
)

The backoff calculation includes randomized jitter to prevent thundering herd problems when multiple clients retry simultaneously.

Idempotencyโ€‹

The SDK automatically generates a unique Idempotency-Key header (UUID v4) for all POST, PUT, and PATCH requests. This ensures that retried requests are safely idempotent.

# This request is automatically idempotent
keyset = client.keysets.create({
"name": "My Keyset"
})

# If the network fails and is retried, the same keyset will not be created twice

Note: The Idempotency-Key is included in all state-changing requests automatically. No manual configuration is required.

Auto-Paginationโ€‹

List operations automatically support pagination through the list_all() method, which returns an iterator.

# Iterate through all assets (handles pagination automatically)
for asset in client.assets.list_all():
print(asset["id"], asset["name"])

# Collect all results into a list
all_assets = list(client.assets.list_all())

# Access with custom parameters
for key in client.keys.list_all(limit=50, offset=0):
print(key)

Method Signature:

Iterator[Dict] list_all(
limit: int = 100,
offset: int = 0,
**kwargs
) -> Iterator[Dict]

Rate Limitingโ€‹

Access rate limit information via the rate_limit property:

from optropic import RateLimitInfo

# Get current rate limit info
info: RateLimitInfo = client.rate_limit

print(f"Limit: {info.limit}")
print(f"Remaining: {info.remaining}")
print(f"Reset At: {info.reset_at}")

RateLimitInfo Dataclass:

@dataclass
class RateLimitInfo:
limit: int # Total requests allowed in the window
remaining: int # Requests remaining in the current window
reset_at: datetime # When the rate limit resets

The rate limit info is updated from response headers after each API call.

Debug Loggingโ€‹

Enable detailed logging to troubleshoot API interactions:

import logging

# Enable debug logging for the SDK
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("optropic")
logger.setLevel(logging.DEBUG)

client = Optropic(api_key="optr_live_...", debug=True)

Important: API keys and sensitive data are automatically redacted from logs using regex patterns. Keys matching the pattern optr_[a-z]+_.* are masked.

Example Log Outputโ€‹

DEBUG:optropic:Sending POST request to /keys
DEBUG:optropic:Request headers: {'Authorization': 'Bearer optr_live_[REDACTED]', ...}
DEBUG:optropic:Response status: 200
DEBUG:optropic:Response body: {...}

Versionโ€‹

Check the installed SDK version:

from optropic import __version__

print(__version__) # Output: 2.3.0

Error Handlingโ€‹

Exception Hierarchyโ€‹

OptropicError (base)
โ”œโ”€โ”€ AuthenticationError
โ”œโ”€โ”€ AuthorizationError
โ”œโ”€โ”€ RateLimitError
โ”œโ”€โ”€ ValidationError
โ”œโ”€โ”€ NotFoundError
โ”œโ”€โ”€ ConflictError
โ”œโ”€โ”€ UnprocessableEntityError
โ””โ”€โ”€ InternalServerError

Usage Examplesโ€‹

from optropic import (
Optropic,
OptropicError,
AuthenticationError,
RateLimitError,
ValidationError,
NotFoundError
)

client = Optropic(api_key="optr_live_...")

try:
key = client.keys.retrieve(key_id="key_123")
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Reset at: {e.reset_at}")
except NotFoundError:
print("Key not found")
except ValidationError as e:
print(f"Validation error: {e.details}")
except OptropicError as e:
print(f"API error: {e.message}")

Error Detailsโ€‹

try:
client.keysets.create({"name": ""})
except ValidationError as e:
print(e.message) # Human-readable error message
print(e.status_code) # HTTP status code (400)
print(e.details) # Additional error details (dict)

API Pathsโ€‹

All API paths in the SDK omit the /v1/ prefix, which is added automatically by the client.

# These are equivalent:
# Manual: GET https://api.optropic.com/v1/keys/key_123
# SDK: client.keys.retrieve(key_id="key_123")

# Manual: POST https://api.optropic.com/v1/keysets
# SDK: client.keysets.create({...})

# Manual: GET https://api.optropic.com/v1/assets?limit=50
# SDK: client.assets.list_all(limit=50)

Complete Exampleโ€‹

from optropic import Optropic, RateLimitError
import logging

# Setup logging
logging.basicConfig(level=logging.INFO)

# Initialize client
client = Optropic(
api_key="optr_live_example123",
sandbox=False,
timeout=30,
debug=False,
retry_config={
"max_retries": 3,
"base_delay": 1.0,
"max_delay": 30.0
}
)

try:
# Create a new keyset
keyset = client.keysets.create({
"name": "Production Keys",
"description": "Keys for production environment"
})
print(f"Created keyset: {keyset['id']}")

# List all keys (with auto-pagination)
key_count = 0
for key in client.keys.list_all(limit=100):
key_count += 1
print(f" - {key['id']}: {key.get('name', 'Unnamed')}")

print(f"Total keys: {key_count}")

# Check rate limit
rate_info = client.rate_limit
print(f"Rate limit: {rate_info.remaining}/{rate_info.limit}")

except RateLimitError as e:
print(f"Rate limited until {e.reset_at}")
except Exception as e:
print(f"Error: {e}")

Next Stepsโ€‹

  • Explore specific resource documentation for detailed API operations
  • Review authentication and security best practices
  • Set up webhooks for event-driven workflows
  • Check the compliance and audit modules for regulatory requirements