Kodall
Client SDKs

Python SDK

Get started with the modern, typed Python 3.10+ client library for the Kodall platform.

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.


Requirements

  • Python 3.10 or higher
  • httpx 0.24.0 or higher (installed automatically)

Installation

Install kodall-client using your preferred Python package manager:

BASH
pip install kodall-client

Quickstart

Use the client as a Python context manager or as a standalone instance:

PYTHON
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}")

Client Configuration

The KodallClient constructor accepts the following options:

PYTHON
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
)
ParameterTypeDefaultDescription
base_urlstr"https://docs-demo.kodall.io"Target Kodall server base URL.
api_keystr | NoneNoneOptional API key sent via X-API-Key header.
timeoutfloat30.0HTTP request timeout in seconds.
verify_sslboolTrueWhether to verify SSL/TLS certificates.

Authentication

The SDK supports both stateless API Key authentication and stateful Session Cookie authentication:

Basic Authentication (Username & Password)

PYTHON
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}")

OpenID Connect (OIDC / OAuth2)

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

Session Lifecycle & Profile Switching

PYTHON
# 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.


Entity CRUD Operations

The SDK provides both domain service methods (client.entities.*) and ergonomic scoped helpers (client.entity("Name").*):

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


Fetch Query Engine

Execute declarative graph queries, parse AST structures, or inspect result column metadata:

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


Custom Workflows

Invoke server-side workflows dynamically by name and method:

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


File Storage & Versioning

Upload, download, and version files with automatic multipart/form-data encoding:

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


Error Handling

The SDK provides a structured exception hierarchy for precise error handling:

PYTHON
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}")

Next Steps