Handoff and insight generation runs on a worker, not inline. Any generation endpoint returns 202 Accepted with a jobId instead of the artifact. You poll the job until it reaches a terminal state.
The jobId is the job's own id (a UUID), not the handoff or insight id. The artifact id arrives as result_id in the job response once it completes – along with the full artifact under result.
A job moves through these statuses:
pending -> processing -> completed
-> failed
pending– enqueued, not yet picked up.processing– the worker is generating.completed– done;result_idpoints at the handoff or insight.failed– generation failed;erroranderror_codeexplain why.
Poll GET /jobs/{jobId} every couple of seconds with a sane timeout. Stop on completed or failed.
async function waitForJob(jobId, apiKey, { intervalMs = 2000, timeoutMs = 120000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`https://www.flowrelay.it/api/v1/jobs/${jobId}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { job, result } = await res.json();
if (job.status === "completed") return result;
if (job.status === "failed") throw new Error(job.error ?? "Generation failed");
await new Promise((r) => setTimeout(r, intervalMs));
}
throw new Error("Timed out waiting for job");
}import time
import requests
def wait_for_job(job_id, api_key, interval=2, timeout=120):
deadline = time.time() + timeout
headers = {"Authorization": f"Bearer {api_key}"}
while time.time() < deadline:
resp = requests.get(
f"https://www.flowrelay.it/api/v1/jobs/{job_id}", headers=headers
)
payload = resp.json()
job = payload["job"]
if job["status"] == "completed":
return payload["result"]
if job["status"] == "failed":
raise RuntimeError(job.get("error") or "Generation failed")
time.sleep(interval)
raise TimeoutError("Timed out waiting for job")Project handoffs and architecture insights can take tens of seconds because they build context and run larger models. Use a timeout of 120 seconds and a poll interval of 2 seconds. Do not poll faster than once per second – it only burns your rate limit.
When status is completed, the job response embeds the artifact under result. result_kind tells you whether it is a handoff or an insight, and result_id is the row id you can fetch again later via the list endpoints.
See Errors for what a failed job's error_code means.