Python SDK and API v1
The SDK is a small synchronous wrapper around the local API v1 server. Use it when you want a stable Python surface for automation without hand-rolling HTTP.
Start the API bridge#
nameframe api-serve --scene-manifest _local/scene_manifest.json --port 8010
The server binds to localhost. Produce the scene manifest first with nameframe
scene-unreal against an open editor, or point it at a manifest you already have.
Using the client#
from nameframe import NameFrameApiError, NameFrameClient
client = NameFrameClient("http://127.0.0.1:8010", timeout_s=10)
print(client.capabilities())
print(client.classes())
Call capabilities() first. It reports the plugin, API and schema versions and
which features are supported, so your code can adapt instead of failing on a missing
endpoint.
Scenarios#
scenario = {
"schema_version": 1,
"scenario_id": "scenario_demo",
"scenario_version": 1,
"master_seed": 123,
"scene": {"map": "Testing"},
"spawn": {}, "camera": {}, "environment": {},
"capture": {}, "annotations": {},
"output": {"root": "D:/tmp/nameframe_sdk"},
}
validation = client.validate_scenario(scenario)
if not validation["ok"]:
raise RuntimeError(validation["errors"])
client.apply_scenario(scenario)
current = client.current_scenario()
Controlled updates
Updates are protected by optimistic concurrency. You pass the config hash you believe is
current, and a stale writer gets CONFIG_CONFLICT instead of silently overwriting
newer state. Updates are dry runs by default.
# preview only, nothing changes
planned = client.update_scenario(
{"spawn": {"count": 25}},
expected_config_hash=current["configuration_hash"],
)
# persistent write: needs dry_run=False and an idempotency key
updated = client.update_scenario(
{"camera": {"fov_deg": 72}},
expected_config_hash=current["configuration_hash"],
dry_run=False,
idempotency_key="sdk-camera-update-001",
)
Retrying a request with the same key is safe: it returns the original result instead of applying the change twice. Generate one per logical operation, not per HTTP attempt.
Durable tasks#
Generation does not block. You start a task and poll it.
import time
task = client.create_generation_task(
plan,
expected_config_hash=plan["configuration_hash"],
approved=True,
idempotency_key="sdk-generation-001",
)
while task["status"] not in {"completed", "failed", "cancelled"}:
time.sleep(0.5)
task = client.task(task["task_id"])
Tasks can be cancelled, retried and resumed with cancel_task,
retry_task and resume_task. Cancelling preserves completed
frames.
Errors#
try:
client.job("missing")
except NameFrameApiError as exc:
print(exc.status, exc.code, exc.recoverable, exc.details)
recoverable tells you whether retrying could plausibly work. Use it instead of
retrying blindly on every failure.
Supported calls#
Discovery
capabilities(), scene(), classes(),
zones(), cameras()
Scenario
validate_scenario(scenario), apply_scenario(scenario),
current_scenario(),
update_scenario(patch, expected_config_hash=..., dry_run=True, idempotency_key=None),
create_scene_helper(helper, expected_config_hash=..., dry_run=True, idempotency_key=None)
Tasks and jobs
create_generation_task(plan, ...),
create_validation_task(scenario=None, idempotency_key=...),
tasks(limit=50, status=""), task(task_id),
cancel_task(task_id), retry_task(task_id),
resume_task(task_id),
create_job(target_samples=..., output_root=..., scenario=None, job_id=None),
jobs(), job(job_id), pause_job(job_id),
resume_job(job_id), cancel_job(job_id)
Preview and analytics
preview(scenario=None), get_preview(preview_id),
analytics(), search_frames(filters=None, limit=50, offset=0),
annotation_issues(run_id="", limit=100),
compare_runs(baseline_run_id, candidate_run_id, representative_limit=12),
coverage_correction_plan(matrix, limit=100, max_additional_frames=100000),
events()
API v1 endpoints#
If you would rather speak HTTP directly:
| Area | Endpoints |
|---|---|
| Discovery | GET /v1/capabilities, /v1/scene, /v1/classes, /v1/zones, /v1/cameras |
| Scenario | POST /v1/scenario/apply, /v1/scenario/validate, /v1/scenario/update; GET /v1/scenario/current |
| Scene helpers | POST /v1/scene/helpers |
| Preview | POST /v1/preview, GET /v1/preview/{id} |
| Jobs | POST /v1/jobs, GET /v1/jobs, GET /v1/jobs/{id}, POST /v1/jobs/{id}/pause|resume|cancel |
| Tasks | POST /v1/tasks/generate, /v1/tasks/validate; GET /v1/tasks, /v1/tasks/{id}; POST /v1/tasks/{id}/cancel |
| Events | GET /v1/events, a finite Server-Sent Events snapshot |
Scene helper creation only accepts NameFrame spawn, target, camera and exclusion zones and
flight paths. It never accepts arbitrary class or asset paths, and the native operation runs as
an Unreal transaction. The full contract, including schema versions and job status transitions,
is in docs/API_V1.md.