A client library for generating images through the flix-imagen API
Project description
Imagen SDK
A proprietary client library for generating images through the flix-imagen API.
Authorized Flixstock users only. A signed runtime license file is required before the SDK can be used.
Python compatibility
- Supported: Python 3.9 through 3.14 (CPython and PyPy)
- Wheel: one universal
py3-none-anywheel works across all supported versions - Floor: Python 3.9 (required by the
cryptographydependency)
Test locally across versions (requires tox and multiple Python installs):
pip install -e ".[dev]"
tox
CI runs the test suite on Python 3.9–3.13 via bitbucket-pipelines.yml.
Installation
pip install imagen-sdk
Runtime license file
Before creating a client, obtain an RSA-signed license file from Flixstock. The SDK verifies signatures using a public key bundled in the package; the private key never ships with the SDK.
The SDK checks for a license in this order:
license_pathargument toImagenClientIMAGEN_SDK_LICENSEenvironment variable./imagen-sdk.licenseor./license.jsonin the working directory~/.config/imagen-sdk/license.json
Example license format: see license.example.json.
Allowed email domains: @flixstock.com, @imageedit.ai.
Key setup (Flixstock admins, one-time)
Generate an RSA key pair. The public key is committed to the repo; the private key stays local.
pip install cryptography
python scripts/generate_keys.py
- Public key:
src/imagen_sdk/keys/license_public.pem(bundled in the wheel) - Private key:
keys/license_private.pem(gitignored — store securely)
Issue a license (Flixstock admins)
python scripts/issue_license.py \
--licensee "Jane Doe" \
--email "jane.doe@flixstock.com" \
--output imagen-sdk.license
Optional: --private-key /path/to/license_private.pem or set IMAGEN_SDK_PRIVATE_KEY.
Usage
Full user guide: see USAGE.md for the complete instruction set —
all generation modes, accepted parameters, and per-model allowed values (aspect
ratios, resolutions, output formats, image counts).
The SDK is a production workflow layer over the flix-imagen HTTP API. It handles
validation, model-agnostic parameter normalization, job creation, polling,
output downloads, batch orchestration with manifests/resume, typed errors, and
idempotency. See requirements.md for the full design and
what the backend currently supports.
Client setup
from imagen_sdk import ImagenClient
client = ImagenClient(
api_key="pk-your-project-key", # or "uk-..." user key
base_url="https://api-fliximagen.flixstock.com",
# license_path="/path/to/imagen-sdk.license", # or via IMAGEN_SDK_LICENSE
max_concurrency=10,
timeout=60,
poll_interval=2,
max_poll_interval=15,
log_level="INFO",
)
A signed runtime license is still required (see below). Authentication to the
API uses the X-API-Key header. With a uk- user key, pass project_name=...
to generate(...) or set it on the client.
Single generation
result = client.generate(
model="nano_banana_2", # stable SDK alias from provider_registry.json
prompt="Female model wearing a black blazer and white trousers",
input_image="https://cdn.example.com/inputs/blazer.jpg", # hosted HTTPS URL
output_path="./outputs/blazer.png",
parameters={
"aspect_ratio": "3:4",
"image_count": 1,
"resolution": "2K",
"output_format": "png",
},
)
print(result.job_id, result.status)
print(result.outputs[0].saved_to)
Models are referenced by stable aliases (ImagenClient.available_models()):
nano_banana_2, nano_banana_pro, nano_banana_2_edit,
nano_banana_pro_edit, gpt_image_2_edit, gpt_4o. You can also pass a raw model:
generate(model="fal:fal-ai/flux/dev", ...) or
generate(model="gemini-3.1-flash-image-preview", provider="vertex", ...).
Batch generation with manifest + resume
batch = client.generate_many(
requests=[
{
"request_id": "sku_001",
"model": "nano_banana_2",
"prompt": "Model wearing SKU 001",
"input_image": "https://cdn.example.com/inputs/sku_001.jpg",
"output_path": "./outputs/sku_001.png",
"parameters": {"aspect_ratio": "3:4", "output_format": "png"},
},
],
concurrency=10,
save_manifest="./outputs/manifest.json",
continue_on_error=True,
)
print(batch.total, batch.succeeded, batch.failed)
# Resume an interrupted batch (skips already-succeeded items):
client.resume_batch("./outputs/manifest.json", requests)
Async client
import asyncio
from imagen_sdk import AsyncImagenClient
async def main():
async with AsyncImagenClient(api_key="pk-...") as client:
results = await client.generate_many(
[
{"model": "nano_banana_2", "prompt": "red dress",
"input_image": "https://cdn/1.jpg", "output_path": "./out/1.png"},
{"model": "nano_banana_2", "prompt": "blue dress",
"input_image": "https://cdn/2.jpg", "output_path": "./out/2.png"},
],
concurrency=10,
)
print(results.succeeded)
asyncio.run(main())
Dry run
preview = client.generate(
model="nano_banana_2",
prompt="denim jacket",
input_image="https://cdn/in.jpg",
parameters={"aspect_ratio": "3:4", "image_count": 4},
dry_run=True,
)
print(preview.normalized_payload) # provider input_fields, no job created
print(preview.uploads_required)
Low-level API
dto = client.create_job(model="nano_banana_2", prompt="...",
input_image="https://cdn/in.jpg")
status = client.wait_for_job(dto["id"])
client.download_outputs(status["output_urls"], job_id=dto["id"],
output_dir="./outputs/")
Errors
from imagen_sdk import JobFailedError, ValidationError, RateLimitError
try:
client.generate(model="nano_banana_2", prompt="...")
except ValidationError as exc: # caught locally before any API call
print(exc.details)
except JobFailedError as exc:
print(exc.job_id, exc.error_code, exc.retryable)
All errors derive from SDKError and carry code, status_code, job_id,
request_id, and retryable.
Output overwrite policy
generate(..., on_existing=...) accepts error (default), overwrite,
rename (writes out_1.webp, out_2.webp, ...), or skip.
Local file uploads
Local files (input_image="./in.jpg", Path(...), etc.) are uploaded
automatically to S3/CDN via the Flixstudio Pegasus presign service — the
same flow the web UI uses:
POST https://api-pegasus.flixstudio.io/api/v1/util/s3PutPreSignedUrlwith{"key", "bucketName", "mimeType"}→{"url": "<signed PUT URL>"}PUTthe bytes to the signed URL- The public URL
https://fxgati.flixstock.com/<key>is passed into the job
result = client.generate(
model="nano_banana_2",
prompt="red dress",
input_image="./inputs/front.jpg", # local file -> uploaded automatically
output_path="./outputs/front.png",
)
# Or upload manually:
up = client.upload_file("./inputs/front.jpg")
print(up.cdn_url)
Configurable on the client: enable_uploads (default True),
pegasus_presign_url, upload_bucket (fxgati), cdn_host
(fxgati.flixstock.com), upload_key_prefix (Flix_ImageGen), and
pegasus_token (sent as Authorization: Bearer if the service requires it).
Set enable_uploads=False to force hosted-URL-only inputs.
Backend limitations (current flix-imagen state)
- Cancellation, webhooks, and server-side idempotency are not yet available.
cancel_job()raisesNotSupportedError; the SDK still sends anIdempotency-Keyheader so it works the moment the backend adds support.
Legacy construction
from imagen_sdk import ImagenClient, LicenseError
try:
client = ImagenClient(api_key="pk-...", license_path="/path/to/imagen-sdk.license")
except LicenseError as exc:
print(exc)
Or set the environment variable:
export IMAGEN_SDK_LICENSE=/path/to/imagen-sdk.license
Development
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS/Linux
pip install -e ".[dev]"
python scripts/generate_keys.py # if keys do not exist yet
python scripts/issue_license.py --licensee "Dev User" --email "dev@flixstock.com"
pytest
Publishing to PyPI
CI/CD (Bitbucket Pipelines)
Releases are published automatically when you push a version tag.
- Bump
versioninpyproject.tomland__version__insrc/imagen_sdk/__init__.py. - Commit and push.
- Create and push a matching tag:
git tag v0.0.2
git push origin v0.0.2
The v* tag pipeline runs tests, verifies the tag matches the package version, builds, and uploads to PyPI.
Manual TestPyPI publish: Pipelines → Run pipeline → publish-testpypi.
Bitbucket repository variables
Add these under Repository settings → Pipelines → Repository variables:
| Variable | Secured | Value |
|---|---|---|
TWINE_USERNAME |
No | __token__ |
TWINE_PASSWORD |
Yes | Production PyPI API token (full value, including pypi- prefix) |
TESTPYPI_TWINE_PASSWORD |
Yes | TestPyPI API token (only needed for the publish-testpypi custom pipeline) |
Create tokens at:
- Production: pypi.org/manage/account/#api-tokens
- Test: test.pypi.org/manage/account/#api-tokens
Scope tokens to the imagen-sdk project when possible.
Manual publish
Follow the Python Packaging User Guide.
1. Install build tools
pip install --upgrade pip build twine
2. Bump the version
Update version in pyproject.toml and __version__ in src/imagen_sdk/__init__.py. PyPI does not allow re-uploading the same version.
3. Build distribution archives
# Windows PowerShell
Remove-Item -Recurse -Force dist, build -ErrorAction SilentlyContinue
python -m build
This produces in dist/:
imagen_sdk-<version>.tar.gz— source distributionimagen_sdk-<version>-py3-none-any.whl— wheel
4. Test on TestPyPI (recommended)
- Register at test.pypi.org and verify your email.
- Create an API token at test.pypi.org/manage/account/#api-tokens.
- Upload:
python -m twine upload --repository testpypi dist/*
When prompted:
- Username:
__token__ - Password: your API token (including the
pypi-prefix)
- Verify install:
pip install --index-url https://test.pypi.org/simple/ --no-deps imagen-sdk
- Check:
https://test.pypi.org/project/imagen-sdk/
5. Publish to PyPI
- Register at pypi.org (separate from TestPyPI).
- Confirm
imagen-sdkis available on pypi.org. - Create a production API token at pypi.org/manage/account/#api-tokens.
- Upload:
python -m twine upload dist/*
- Install from PyPI:
pip install imagen-sdk
Optional: store credentials in .pypirc
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-...
Never commit .pypirc or API tokens to version control.
License
Proprietary — see LICENSE. Unauthorized use, copying, or distribution is prohibited.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file imagen_sdk-0.1.1.tar.gz.
File metadata
- Download URL: imagen_sdk-0.1.1.tar.gz
- Upload date:
- Size: 49.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62a2cec49040ab816a64007ad705d00c6dca43e48ef71c20e1fbab5b7c5785f7
|
|
| MD5 |
b5d365f30a919e395484c8b8ec7252d7
|
|
| BLAKE2b-256 |
49e13997ff88a6c617135d31f4338b4dd30afc69ede51bc7d49838262c23e309
|
File details
Details for the file imagen_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: imagen_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 50.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3117f6ae0b82becf1e7daaa6f9320dd3eef26c2fd559d7a15dbfe9ecf0f28a2
|
|
| MD5 |
721d05a21b68b28e557953e85aff5c7b
|
|
| BLAKE2b-256 |
6debb589efdcf2ae9c645e0bc392fec8e18aaf8b5e7874bbcdf91102f56db459
|