Python Client

Use indream-client with sync and async clients.

Install

pip install indream-client

Sync Client

from indream import IndreamClient

client = IndreamClient(
    api_key="<YOUR_API_KEY>",
    base_url="https://api.indream.ai",
    timeout=60,
    max_retries=2,
)

Search Illustrations

Search by keyword when you need a supported hand-drawn illustration name.

items = client.illustrations.search("creative")
print(items)

Create and Wait

OpenAPI enforces active export concurrency per account. If your account already has two active export tasks, exports.create returns 422 OPEN_API_EXPORT_CONCURRENCY_LIMIT_EXCEEDED.

created = client.exports.create(
    {
        "editorState": editor_state,
        "ratio": "9:16",
        "scale": 0.6,
        "fps": 30,
        "format": "mp4",
    }
)
print(created.duration_seconds, created.billed_standard_seconds)

done = client.exports.wait(created.task_id, timeout=600, poll_interval=2)
print(done.status, done.output_url)

duration_seconds is the real export duration. billed_standard_seconds is the billing unit.

Project Workflow

project = client.projects.create(
    {
        "title": "Launch draft",
        "editorState": editor_state,
    }
)

with open("hero.png", "rb") as fh:
    asset = client.uploads.upload(
        fh.read(),
        filename="hero.png",
        content_type="image/png",
        project_id=project.project_id,
    )

client.projects.sync(
    project.project_id,
    {
        "editorState": {
            **editor_state,
            "assets": {
                **editor_state.get("assets", {}),
                "hero": {
                    "type": "image",
                    "remoteUrl": asset.file_url,
                    "remoteKey": asset.file_key,
                },
            },
        }
    },
)

created_from_project = client.projects.create_export(
    project.project_id,
    {
        "ratio": "9:16",
        "scale": 0.6,
        "fps": 30,
        "format": "mp4",
    },
)

done = client.exports.wait(created_from_project.task_id, timeout=600, poll_interval=2)
print(done.project_id, done.status)

List Exports

page = client.exports.list(
    page_size=20,
    page_cursor=None,
    created_by_api_key_id=None,
)
print(len(page.items), page.next_page_cursor)
print(page.items[0].created_by_api_key_id if page.items else None)

Verify and Parse Webhook

import json

from indream import verify_export_webhook_request
from indream.types import ExportWebhookEvent

raw_body = request.get_data(as_text=True)
is_valid = verify_export_webhook_request(
    webhook_secret=WEBHOOK_SECRET,
    raw_body=raw_body,
    headers=request.headers,
    max_skew_seconds=300,  # optional
)

if not is_valid:
    raise ValueError("Invalid webhook signature")

event = ExportWebhookEvent.model_validate(json.loads(raw_body))
print(event.event_type)
print(
    event.task.task_id,
    event.task.status,
    event.task.duration_seconds,
    event.task.billed_standard_seconds,
)

event_type values are EXPORT_STARTED, EXPORT_COMPLETED, EXPORT_FAILED. event.task has the same shape as client.exports.get(task_id) result. duration_seconds is the real export duration, while billed_standard_seconds is the billing unit. verify_export_webhook_request validates both signature headers and timestamp skew window.

Validate Editor State

capabilities = client.editor.capabilities()
print([preset.id for preset in capabilities.caption_animations.in_])

result = client.editor.validate(editor_state)
if not result.valid:
    for err in result.errors:
        print(err.code, err.path, err.message)

client.editor.validate(...) and client.exports.create(...) perform local editor-state schema checks before sending the request. If the payload is invalid, the SDK raises ValidationError immediately.

Async Client

import asyncio
from indream import AsyncIndreamClient

async def main() -> None:
    client = AsyncIndreamClient(api_key="<YOUR_API_KEY>")
    created = await client.exports.create(
        {
            "editorState": editor_state,
            "ratio": "9:16",
            "scale": 0.6,
            "fps": 30,
            "format": "mp4",
        }
    )
    done = await client.exports.wait(created.task_id, timeout=600, poll_interval=2)
    print(done.status, done.output_url)
    await client.aclose()

asyncio.run(main())

Exceptions

  • AuthError: invalid credentials or forbidden scope.
  • ValidationError: schema or semantic payload issue.
  • RateLimitError: request throttled.
  • APIError: non-specialized API error.

Resources

For source code, issues, and contributions, visit our GitHub repository. Install the latest Python package from indream-client.

Last updated on

On this page