Lamina Labs

Documentation

Python SDK

Async-first Python SDK: generate, stream events, or use callbacks.

install
pip install lamina-sdk

Python 3.11 or newer is required. Set LAMINA_API_KEY in your environment, or pass api_key directly. The SDK handles the poll-and-download dance for you.

Quick start

python
from lamina import Simi

async with Simi(api_key="lamina_your_key") as client:
    video = await client.generate(
        "A narrated lesson about derivatives",
        duration=1,
    )
    await video.save("out.mp4")

duration is in whole minutes, 1 to 5. duration=1 is a one-minute video, not one second.

Stream events

python
async with Simi() as client:
    job = await client.submit_async(
        "Explain our refund policy",
        duration=1,
        document="policy.pdf",
    )
    async for event in client.stream_events(job):
        print(event.type)

document takes a path to a local file; the SDK uploads it and attaches it to the job for you.

Callback style

python
async with Simi() as client:
    job = await client.submit_async("A narrated lesson about derivatives")
    job.onstream(lambda event: print(event.type))
    job.oncompletion(lambda video: print(f"Ready: {video.job_id}"))
    await job.wait()

List, cancel, and play back

python
async with Simi() as client:
    jobs = await client.list_jobs(limit=10, status="complete")
    for job in jobs:
        print(job.job_id, job.status)

    await client.cancel("job_abc123")

    playback = await client.get_playback(jobs[0].job_id)
    print(playback.src, playback.src_available, playback.expires_at)

Retries and errors

Reads are retried automatically on 429 and 5xx with exponential backoff, honouring retry-after. A submit is only retried when you pass an idempotency_key, so a retry can never create a second video.

python
from lamina import Simi, SimiRateLimitError

async with Simi(max_retries=3) as client:
    try:
        job = await client.submit_async(
            "Explain our refund policy",
            idempotency_key="req-1",
        )
    except SimiRateLimitError as error:
        print(error.status, error.retry_after, error.request_id)

Every error derives from SimiError: SimiAPIError (carrying status, request_id, and retry_after), SimiRateLimitError, SimiJobError, SimiStreamError, SimiDownloadError, and SimiCancelledError.

Use async with in async code. Plain with is supported only outside a running event loop, and will tell you so if you get it wrong.