Skip to main content

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)

Source distribution for fcaai 0.4.0
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)

Table of built distributions (wheels) for fcaai 0.4.0
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page