SDK
Python SDK
The official Clipia Python SDK (PyPI clipia 1.5.0) — Clipia and AsyncClipia clients, the generation queue, catalog and price estimates, webhook checks, errors.
The official Clipia Python client is published on PyPI as clipia. It's built on httpx, runs on Python 3.9+ and provides a synchronous Clipia and an asynchronous AsyncClipia with the same methods. It covers the generation queue (submit, status, result), the high-level subscribe, the model catalog with price estimates, and account data.
Package
The package and module are both called clipia, current version 1.5.0. The base URL is https://api.clipia.ai. The SDK doesn't read environment variables on its own: pass the key explicitly as api_key.
Quickstart
Install
pip install clipiaClient
import os
from clipia import Clipia
# Read the key from an environment variable; don't hard-code it
clipia = Clipia(api_key=os.environ["CLIPIA_KEY"])Besides api_key, the constructor takes base_url (https:// only), an HTTP timeout (60 seconds by default), max_retries (how many times submit retries a transient failure, default 2; 0 disables retries), retry_delay (the base pause between retries, default 0.5 seconds) and transport — a custom httpx transport for tests. Use the client as a context manager (with Clipia(...) as clipia:) or close it with clipia.close().
Generate and wait for the result
subscribe queues the job and polls its status until it finishes:
out = clipia.subscribe(
"nano-banana-2",
input={"prompt": "a neon city in the rain, cinematic lighting"},
on_queue_update=lambda s: print(s.status),
poll_interval=1.0, # default, seconds
timeout=600.0, # default, seconds
)
if out.status == "COMPLETED":
print(out.output) # links to the finished media
print(out.cost) # cost in credits
else:
print(out.error)subscribe also returns on FAILED, so check status. The client retries transient polling errors (network, 429, 5xx) on its own. If the job doesn't finish within timeout, it raises ClipiaTimeoutError; the job keeps running and you can still fetch it by request_id.
Manual queue control
job = clipia.submit(
"nano-banana-2",
input={"prompt": "..."},
webhook_url="https://example.com/clipia-webhook", # optional
)
status = clipia.status(job.request_id)
result = clipia.result(job.request_id)
# result.pending is True while the job is IN_QUEUE or IN_PROGRESSIdempotency key
The SDK generates a new Idempotency-Key for every submit call and retries transient failures — a network error, 429, 500, 502, 503, 504 — up to max_retries times with the same key, honoring Retry-After: an internal retry never creates a second job. A new submit call in your code, however, gets a new key. To make your own retry land on the same job, pass idempotency_key and reuse it on the retry — see Idempotency.
Catalog, price and account
catalog = clipia.models.list() # {"data": [...]}
model = clipia.models.get("nano-banana-2")
estimate = clipia.models.estimate("nano-banana-2", {"prompt": "a neon city"})
print(estimate.credits)
account = clipia.account.get()
# {"account_id": ..., "balance": {"credits": ...}, "usage_30d": {"requests": ..., "credits_spent": ...}}The catalog and account come back as dictionaries (TypedDict); queue and estimate responses are objects with attributes. models.list() can include LLM models without a slug — see Model catalog.
Ignored parameters
If input contains a key the model will not apply (a typo, a parameter of another model), submit and models.estimate accept the request as usual and return the key in warnings — one entry per key. When every parameter is accepted, the list is empty.
# job is the submit response from the section above
for w in job.warnings:
print(w.code, w.parameter, w.message)
# unknown_parameter aspect_ration Parameter "aspect_ration" is not recognized and was ignored. …
# The same check before you run anything: an estimate charges nothing
estimate = clipia.models.estimate("nano-banana-2", {"prompt": "..."})
print(estimate.warnings) # [] — every parameter was acceptedThe InputWarning class and the warnings attribute were added in version 1.5.0. subscribe returns the generation result, which carries no warnings: call submit or models.estimate to read them. The code values and the other rules are in Ignored parameters.
Async client
import asyncio
from clipia import AsyncClipia
async def main():
async with AsyncClipia(api_key=os.environ["CLIPIA_KEY"]) as clipia:
out = await clipia.subscribe("nano-banana-2", input={"prompt": "a cat"})
print(out.output)
asyncio.run(main())Verifying webhooks
from clipia.webhooks import verify_signature
ok = verify_signature(
secret=os.environ["CLIPIA_WEBHOOK_SECRET"],
headers=request.headers,
body=raw_body, # the raw request body, str or bytes
tolerance_seconds=300, # default
)The function returns True or False and never raises on malformed input. Each API key has its own webhook secret — see Webhooks.
Error handling
Any non-2xx response becomes a ClipiaApiError with status, code, type, message and, when the server sent Retry-After, retry_after in seconds. ClipiaTimeoutError is its subclass for an expired timeout in subscribe: status is 0, code is poll_timeout, and request_id holds the id of the job, which keeps running.
from clipia import ClipiaApiError
try:
clipia.submit("nano-banana-2", input={"prompt": "..."})
except ClipiaApiError as e:
print(e.status, e.code, e.type, e.message)Error codes are listed on the Errors page.
Sandbox
A key prefixed clipia_test_ returns a canned result instantly with no credits charged. See Sandbox.
TypeScript SDK
The official Clipia TypeScript SDK (npm clipia-ai 1.5.0) — install, generation queue, catalog and price estimates, webhook checks, errors and the clipia CLI.
Best practices
Build a reliable Clipia API integration — idempotent retries, webhooks over polling, error and 429 handling, cost estimates and storing request_id.