The Kodall Python SDK (kodall-client) is a modern, typed API client built on top of httpx. It provides ergonomic domain namespaces (client.auth, client.entities, client.fetch, client.workflows, client.storage), scoped entity helpers, connection pooling, and transparent session management.
Install kodall-client using your preferred Python package manager:
pip install kodall-client
poetry add kodall-client
uv add kodall-client
Use the client as a Python context manager or as a standalone instance:
from kodall_client import KodallClient, APIError
# Initialize client with API key
with KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="e3097afe-1528-4fdb-a816-0d3724a8f318"
) as client:
try:
# Execute a fetch query
query = """
FETCH todo (key, title, is_completed)
ORDER BY key DESC
LIMIT 5
"""
todos = client.fetch(query)
for todo in todos:
print(f"Todo #{todo['key']}: {todo['title']}")
except APIError as e:
print(f"API Error [{e.status_code}]: {e}")
The KodallClient constructor accepts the following options:
from kodall_client import KodallClient
# Stateless API Key mode
client = KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="your-api-key",
timeout=30.0,
verify_ssl=True
)
# Stateful Session Cookie mode
session_client = KodallClient(
base_url="https://docs-demo.kodall.io",
timeout=30.0
)
| Parameter | Type | Default | Description |
|---|---|---|---|
base_url | str | "https://docs-demo.kodall.io" | Target Kodall server base URL. |
api_key | str | None | None | Optional API key sent via X-API-Key header. |
timeout | float | 30.0 | HTTP request timeout in seconds. |
verify_ssl | bool | True | Whether to verify SSL/TLS certificates. |
The SDK supports both stateless API Key authentication and stateful Session Cookie authentication:
from kodall_client import KodallClient, AuthenticationError
with KodallClient(base_url="https://docs-demo.kodall.io") as client:
try:
# Login establishes session and CSRF cookies automatically
session = client.auth.login(user="root", password="password123", locale="ro")
print(f"Authenticated user: {session.userName} (ID: {session.userKey})")
print(f"Server version: {session.version}")
except AuthenticationError as e:
print(f"Login failed: {e}")
from kodall_client import KodallClient, OidcTokens
with KodallClient(base_url="https://docs-demo.kodall.io") as client:
session = client.auth.auth(OidcTokens(
access_token="eyJhbGciOi...",
refresh_token="eyJhbGciOi..." # Optional
))
# Inspect current session with roles and profiles
session_info = client.auth.session(roles=True, profiles=True)
print("Roles:", session_info.roles)
print("Profiles:", session_info.profiles)
# Switch active user profile context
active_profile = client.auth.change_user_profile("sales_admin")
print("Switched to profile:", active_profile.name)
# Manually refresh session cookie token
refreshed = client.auth.refresh()
# Logout
client.auth.logout()
For more authentication details, visit the Auth API Reference.
The SDK provides both domain service methods (client.entities.*) and ergonomic scoped helpers (client.entity("Name").*):
from kodall_client import (
KodallClient,
Entity,
ChildEntity,
ValidationError,
NotFoundError,
APIError,
)
with KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="e3097afe-1528-4fdb-a816-0d3724a8f318"
) as client:
try:
# 1. Create Entity with nested children
new_todo = Entity(
entity_name="todo",
properties={"title": "Review Python SDK", "is_completed": 0},
children={
"todo_todo_item": [
ChildEntity(entity_name="todo_item", properties={"description": "Write tests", "is_completed": 1})
]
}
)
op = client.entities.create(new_todo)
key = op.key
print(f"Created todo with key: {key}")
# 2. Retrieve Entity by Key
todo = client.entities.get("todo", key)
print(f"Retrieved: {todo.properties['title']}")
# 3. Scoped Entity Helper (Update)
client.entity("todo").update(
key=key,
properties={"title": "Review Python SDK (Completed)", "is_completed": 1}
)
# 4. Scoped Entity Helper (Delete)
client.entity("todo").delete(key)
except ValidationError as e:
# HTTP 424: Business rule validation constraint violated
print(f"Validation failure on {e.validation.propertyName}: {e.validation.detail}")
except NotFoundError as e:
print(f"Entity not found: {e}")
except APIError as e:
print(f"API Error [{e.status_code}]: {e}")
For more entity operations and payload structures, visit the Entities API Reference.
Execute declarative graph queries, parse AST structures, or inspect result column metadata:
with KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="e3097afe-1528-4fdb-a816-0d3724a8f318"
) as client:
# 1. Execute Query
query = """
FETCH todo (key, title, is_completed) {
todo_item TO id_todo (key AS item_key, description, is_completed AS item_completed)
}
FILTER AND (is_completed == 0)
ORDER BY key DESC
LIMIT 10
"""
rows = client.fetch(query)
print(f"Retrieved {len(rows)} rows")
# 2. Parse Query AST
ast = client.fetch.parse("FETCH todo (key, title)")
print("Parsed AST:", ast)
# 3. Query Metadata Inspection
metadata = client.fetch.metadata("FETCH todo (key, title)")
print("Columns:", metadata)
For more query syntax options, visit the Fetch API Reference.
Invoke server-side workflows dynamically by name and method:
with KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="e3097afe-1528-4fdb-a816-0d3724a8f318"
) as client:
response = client.workflows.execute(
workflow_name="DemoWf",
workflow_method="hello",
payload={"name": "Python Developer", "type": "default"}
)
print("Workflow response:", response)
For more workflow examples, visit the Workflow API Reference.
Upload, download, and version files with automatic multipart/form-data encoding:
with KodallClient(
base_url="https://docs-demo.kodall.io",
api_key="e3097afe-1528-4fdb-a816-0d3724a8f318"
) as client:
# 1. Upload a file from disk
items = client.storage.upload_file("report.pdf")
file_id = items[0].id
print(f"Uploaded file ID: {file_id}")
# 2. Upload raw bytes directly
byte_items = client.storage.upload_file(
("document.txt", b"Hello from Python SDK!", "text/plain")
)
# 3. Upload a new file version
client.storage.upload_file_version("report_v2.pdf", key=file_id)
# 4. Download file bytes
file_bytes = client.storage.get_file(file_id, action="download")
with open("downloaded_report.pdf", "wb") as f:
f.write(file_bytes)
For more storage operations, visit the Storage API Reference.
The SDK provides a structured exception hierarchy for precise error handling:
from kodall_client import (
KodallClient,
ValidationError,
AuthenticationError,
ForbiddenError,
NotFoundError,
APIError,
)
try:
client.entities.create(invalid_entity)
except ValidationError as e:
# HTTP 424: Business rule validation constraint violated
print("Validation Error:", e.validation.detail)
print("Failed Property:", e.validation.propertyName)
print("Triggered Event:", e.validation.eventName)
except AuthenticationError as e:
# HTTP 401: Invalid credentials or expired session
print("Authentication failed:", e)
except ForbiddenError as e:
# HTTP 403: Permission denied
print("Access forbidden:", e)
except NotFoundError as e:
# HTTP 404: Resource not found
print("Not found:", e)
except APIError as e:
# HTTP 400, 500, etc.
print(f"API Error [{e.status_code}]: {e}")