fcaai (Python)
Official Python client for the fcaai API. Standard library only (no requests/httpx), Python 3.9+. All prices in USD.
pip install fcaai
export FCAAI_API_KEY=fcaai_live_…
from fcaai import Fcaai
client = Fcaai() # reads FCAAI_API_KEY
print(client.models.get("google/nano-banana-pro", resolution="2k")["estimate"]["price_display"])
gen = client.generations.create("google/nano-banana-pro", {"prompt": "a paper plane on a wooden desk", "aspect_ratio": "16:9"})
gen.wait() # long-polls /v1/generations/{id}?wait=60
print(gen.status, gen.urls, gen.price_usd)
# Files: ≤ 50 MB in one request, bigger ones chunked (8 MB, 3 parallel, resumable with session_id=)
img = client.uploads.create("room.jpg", "image/jpeg")
video = client.uploads.create_chunked("walkthrough.mp4", mime="video/mp4", on_progress=lambda s, n: print(s * 100 // n, "%"))
clip = client.generations.create("fca/magic-v3", {"image": img["url"], "prompt": "slow dolly in", "duration": 5}, wait=600)
Audio, 3D, 4K images and templates (0.2)
# Text to speech (MP3). Voices: [v.id for v in client.models.voices("minimax/speech-2.8")] → narrator, calm, …
clip = client.audio.speech("Welcome to the studio.", voice="narrator", wait=True)
# Sound effects: duration in seconds, seamless loop
rain = client.audio.sfx("rain on a tin roof", duration=6, loop=True, wait=True)
# One object photo → GLB (takes minutes)
chair = client.model3d.from_image(img["url"], detail="detailed", surface="textured", wait=1800)
# 4K on local models (2K render + detail upscaler), up to 4 outputs
shots = client.images.create("glass villa, blue hour", model="fca/magic-pro", resolution="4k", count=2, wait=True)
for o in shots.outputs: # Output dataclass: url, kind, mime, width, height, thumb_url, card_url, poster_url
print(o.url, o.thumb_url)
# Templates
tpl = client.templates.list()[0]
print([(i.key, i.type, i.required) for i in tpl.inputs])
run = client.templates.run(tpl.id, {"photo": img["url"]}, wait=True)
Canvas: timelines, farm, community, approvals, plans, panoramas, video edits (0.3)
# Scene timeline: storyboard → cheap previews → approve → full quality → one MP4
tl = client.timelines.create([{"prompt": "Lina walks into the empty gallery at dawn", "duration": 5}],
{"model": "bytedance/seedance-2.0-fast", "imageModel": "fca/magic-pro", "aspect": "16:9"}, preview=True)
client.timelines.wait(tl["id"]); client.timelines.approve(tl["id"]); client.timelines.final(tl["id"])
client.timelines.wait(tl["id"], timeout=3600); client.timelines.cut(tl["id"])
print(client.timelines.wait(tl["id"])["cut"]["url"])
# Render farm (scenes sent from 3ds Max with the FCA plugin; FcaaiError not_enabled when the farm is off)
for j in client.farm.jobs.list(status="active"):
print(j["id"], j["status"], j["progress"])
client.farm.jobs.pause("fj_…") # the reserved amount stays on hold; paused time is not charged
client.farm.jobs.resume("fj_…")
page = client.community.list(type="flow", category="architecture", sort="popular")
res = client.approvals.list("<board-id>", status="pending")
client.approvals.decide("<board-id>", "<request-id>", "<option-id>", "changes", note="Warmer light, please.")
plan = client.plans.read(img["url"]) # billed per read, never retried
pano = client.panoramas.finish("https://…/pano.png") # free
edit = client.video_edits.create([{"url": "https://fcaai.ai/o/…/clip-1.mp4", "start": 0.5, "end": 4}], transition="fade", wait=True)
print(edit.urls[0])
Voices, multi-step templates, elements, style kits, reseller (0.4)
# Clone your own voice (free; speech is billed as usual). Consent is required.
info = client.voices.list()
me = client.voices.clone(["take1.mp3", "take2.mp3"], name="My voice", consent=True,
consent_version=info["clone"]["consent_version"])
client.audio.speech("Hello from my own voice.", voice=me["id"], model="<speech-model-with-cloned-voices>", wait=True)
styles = client.models.voice_styles(locale="en") # ready-made speaking styles → styles["param"]
# Multi-step templates (Template.is_package) run as one template run
tpl = client.templates.get("<package-slug>")
run = client.templates.run_package(tpl.id, {"photo": img["url"]}, wait=True)
print(run["status"], run["price_usd"], [o["url"] for o in run["outputs"]])
# client.templates.get_run(run_id, wait=30) · client.templates.cancel_run(run_id)
# Single-step template on another allowed model, with a style kit, filed into an Architecture Studio project
kit = client.style_kits.list()[0]
g = client.templates.run("<slug>", {"photo": img["url"]}, model=tpl.models[-1]["id"], brand_kit_id=kit["id"], project="<project-id>")
# Element library (characters, products, places, materials) → references added server-side
lina = client.elements.list(kind="character", q="lina")["data"][0]
client.generations.create("fca/magic-pro", {"prompt": "@lina reading in a cafe", "element_ids": [lina["id"]]},
brand_kit_id=kit["id"], external_user_id="customer-42")
# Reseller keys (scope reseller:manage)
acme = client.reseller.subtenants.create("Acme Studio", retail_markup=1.5)
key = client.reseller.subtenants.create_key(acme["id"], "server", mode="live") # full key shown only here
print(client.reseller.usage(from_="2026-10-01", to="2026-10-31")["totals"])
images.generate(prompt, size=…, n=…) stays OpenAI-compatible (returns a dict); passing resolution, count, aspect_ratio, images or wait makes it a native generation.
Also: generations.get/list(status=, limit=)/cancel, account.get/balance/usage(from_=, to=), uploads.create_session/get_session/put_chunk/complete_session/delete_session (low-level resumable upload), webhooks.list/create/delete/deliveries, chat.completions.create(messages) (OpenAI schema, fca/chat), images.generate(prompt, size=…).
Errors raise fcaai.FcaaiError (status, type, code, message, request_id, doc_url, retry_after, body). 429/5xx/network errors are retried (max_retries=2) honoring Retry-After. create() always sends an Idempotency-Key, so retries never double-charge.
Webhooks
from fcaai import verify_webhook_signature
ok = verify_webhook_signature(secret, request.headers["X-FCAAI-Signature"], request.get_data(), tolerance_sec=300)
Changelog
Full history in CHANGELOG.md (included in the source distribution). 0.4.0 — full /v1 parity: multi-step template runs, voice cloning + voice styles,
elements, style kits, reseller sub-tenants/keys/usage, brand_kit_id / external_user_id on generations, typed package (py.typed).
Tests
python -m pytest -q # or: python -m unittest
License: MIT © 2026 FCA Studio LLC.
Metadata
Release files for fcaai 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fcaai-0.4.0.tar.gz | 36.1 kB | Without provenance | Details for fcaai-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fcaai-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for fcaai-0.4.0-py3-none-any.whl |
Total release size: 59.9 kB
Release files / fcaai-0.4.0.tar.gz
| Download URL | fcaai-0.4.0.tar.gz |
|---|---|
| Size | 36.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b538c245d834828e0ccd235ce1073a8b798d84b39d5fd5545d4869dd85c07f36
|
|
BLAKE2b-256 checksum How to use checksums |
6d529ba631d87ca66c6703ba73fb796c42eaa12a8c9c718ec689b53c48b33cfe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / fcaai-0.4.0-py3-none-any.whl
| Download URL | fcaai-0.4.0-py3-none-any.whl |
|---|---|
| Size | 23.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
151ad3a2478e0b34c440bab083724ff87c78b6b22bba9ebde2e9af0e0c6663b7
|
|
BLAKE2b-256 checksum How to use checksums |
ed13ef82981822d1b8f249f0706d229a80050be4fcf83e2159c6f1a42f16d9b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for fcaai 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.