Skip to content

Python

Guide to using Soxom-generated Python SDKs.

soxom.yaml
targets:
python:
package_name: acme-sdk # PyPI package name
min_version: "3.9" # Minimum Python version
OptionDefaultDescription
package_namesdk.name (snake_case)PyPI package name
min_version"3.8"Minimum Python version
Terminal window
pip install acme-sdk
from acme_sdk import Client
# With token
client = Client(token=os.environ["ACME_API_TOKEN"])
# With options
client = Client(
token=os.environ["ACME_API_TOKEN"],
base_url="https://api.acme.com/v2", # Override base URL
timeout=30000, # Default timeout (ms)
)
# From environment (if configured)
client = Client() # Reads from ACME_API_TOKEN

Soxom generates full type hints for Python 3.9+:

from acme_sdk import Client, User, UserCreate, UserStatus
# Type hints on methods
def get_user(client: Client, user_id: str) -> User:
return client.users.get(user_id)
# Typed request objects
user: User = client.users.create(
email="john@example.com",
name="John Doe",
)
# Typed responses
users = client.users.list()
for user in users.data:
print(user.name) # str
print(user.status) # Literal["active", "inactive"]
# Enum types
status: UserStatus = "active"
from acme_sdk import PaymentMethod, CreditCard, BankAccount
def process_payment(method: PaymentMethod) -> None:
# Pattern matching (Python 3.10+)
match method:
case CreditCard():
print(f"Card: {method.card_number}")
case BankAccount():
print(f"Account: {method.account_number}")
# Or isinstance check
if isinstance(method, CreditCard):
print(method.expiry_month)
elif isinstance(method, BankAccount):
print(method.routing_number)
# Basic operations
user = client.users.get("user-123")
print(user.name)
# Create
new_user = client.users.create(
email="jane@example.com",
name="Jane Doe"
)
# List with filters
orders = client.orders.list(status="pending", limit=10)
for order in orders.data:
print(order.id)

Soxom generates async clients for Python:

from acme_sdk import AsyncClient
import asyncio
async def main():
client = AsyncClient(token=os.environ["ACME_API_TOKEN"])
# Async operations
user = await client.users.get("user-123")
# Parallel requests
user, orders = await asyncio.gather(
client.users.get("user-123"),
client.orders.list(user_id="user-123")
)
# Async iteration
async for user in client.users.list():
print(user.name)
asyncio.run(main())
# Iterate through all pages
for user in client.users.list():
print(user.name)
# With filters
for order in client.orders.list(status="pending"):
print(order.id)
# Collect all into list
all_users = list(client.users.list())
# Get first page
page = client.users.list(limit=10)
print(page.data)
# Check and get next page
if page.has_more:
next_page = page.next()
# Or use cursor directly
page2 = client.users.list(after=page.next_cursor, limit=10)
# SSE streaming
stream = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}],
stream=True
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
async for chunk in await client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}],
stream=True
):
print(chunk.choices[0].delta.content or "", end="")
from acme_sdk import (
Client,
ApiError,
AuthenticationError,
NotFoundError,
RateLimitError,
ValidationError,
TimeoutError
)
try:
user = client.users.get("user-123")
except AuthenticationError:
# 401 - Invalid or expired token
print("Please check your API token")
except NotFoundError:
# 404 - Resource not found
print("User not found")
except RateLimitError as e:
# 429 - Too many requests
print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
# 400 - Invalid request
print(f"Validation errors: {e.errors}")
except TimeoutError:
# Request timeout
print("Request timed out")
except ApiError as e:
# Other API errors
print(f"API error: {e.status} - {e.message}")
except ApiError as e:
e.status # HTTP status code
e.message # Error message
e.code # API error code
e.request_id # Request ID for debugging
e.headers # Response headers

Override settings per-request:

# Custom timeout
report = client.reports.generate(
params,
timeout=120000
)
# Disable retries
payment = client.payments.create(
data,
retries={"enabled": False}
)
# Custom headers
result = client.users.list(
headers={"X-Custom-Header": "value"}
)
# Idempotency key
order = client.orders.create(
data,
idempotency_key="unique-request-123"
)
# Use as context manager for automatic cleanup
with Client(token=token) as client:
user = client.users.get("user-123")
# Async context manager
async with AsyncClient(token=token) as client:
user = await client.users.get("user-123")
acme_sdk/
├── __init__.py # Main exports
├── client.py # Client class
├── async_client.py # Async client
├── resources/
│ ├── __init__.py
│ ├── users.py # Users resource
│ └── orders.py # Orders resource
├── types/
│ ├── __init__.py # Type exports
│ ├── user.py # User types
│ └── order.py # Order types
├── pyproject.toml
└── README.md