Using the SDK¶
fxqclient is the object-oriented Python client over the public API. It is the
recommended way to script against fxquinox.
Install¶
Connect¶
from fxqclient import Session
fxq = Session("http://localhost:8000", api_key="...") # see Authentication
See Authentication and API keys for how to get an API key.
Read records¶
Every entity type is reachable through entity() (or as an attribute), which
returns a manager with get, filter, filter_raw and all:
# all shots in a project
shots = fxq.entity("Shot").filter(project="Demo Show").all()
# one record by id
task = fxq.entity("Task").get(task_id)
# the raw query DSL for anything filter() can't express
todo = fxq.entity("Task").filter_raw(
["and", ["status", "is", "waitingToStart"], ["project_id", "is", pid]]
).all()
for shot in shots:
print(shot.id, shot.status, shot.data)
Records are thin wrappers: shot.id, shot.entity_type, shot.status, and the
fields under shot.data.
Create and update¶
# Link fields are plain dicts: {"type": ..., "id": ...}
shot = fxq.entity("Shot").create(
code="sh0010",
project={"type": "Project", "id": pid},
)
fxq.entity("Task").create(
name="comp",
step="Compositing",
entity={"type": "Shot", "id": shot.id},
status="waitingToStart",
)
Publish¶
The publish chain is one call - it creates (or reuses) the product, allocates the next version number, and attaches representations:
result = fxq.publish(
task_id=task.id,
product="lightingMain",
product_type="render",
representations=[{"name": "exr", "files": [...]}],
inputs=[upstream_version_id], # lineage
comment="first pass",
)
See Integrations for using this from a DCC, and How it works for the model.
Lineage and dependencies¶
Trace what a version was built from, in either direction:
fxq.lineage(version_id) # the raw input/output lineage record
fxq.dependencies(version_id) # the enriched upstream dependency tree (VAL-51)
Resolve a path from the project anatomy¶
Turn a project's templated anatomy into a concrete path for an entity:
path = fxq.resolve_path(
template_key="publish",
entity_type="Task",
entity_id=task.id,
root_name="work", # which root to resolve against
extra={"product": "lightingMain", "ext": "exr"},
)
Browse loadable products and scene inventory¶
Drive a DCC loader and keep an open scene up to date:
# everything publishable into a context (latest only)
items = fxq.browse_loadable(project_id=pid, product_type="render", latest_only=True)
# given the versions loaded in a scene, which are outdated?
inv = fxq.scene_inventory([v1_id, v2_id]) # each item: current / latest / outdated
Render farm¶
Submit and track farm jobs (the farm itself updates progress via the callback):
job = fxq.submit_farm_job(task_id=task.id, version_id=ver_id, frames="1-100")
fxq.farm_jobs(status="running") # list / filter tracked jobs
fxq.update_farm_job(job["id"], status="completed", progress=100)
Multi-site sync (SiteSync)¶
Queue and process transfers of a representation between sites:
fxq.request_sync(representation_id=rep_id, target_site_id=site_id)
fxq.sync_jobs(status="queued") # list transfer jobs
fxq.process_sync_queue() # process the queue once → completed count
See Pipeline APIs for the concepts behind anatomy, the loader, the farm and SiteSync.
The full surface is in the SDK reference.