Runs And Status
Start workflow or analysis runs, poll the unified status, and read kind-specific detail.
This guide shows you how to start a run, poll it to a terminal state, validate its semantic result, and read its kind-specific output.
Every run has a required kind: workflow or analysis. Both kinds use the same top-level status vocabulary:
queued -> processing -> completed | failed | canceledKind-specific detail lives in workflow or analysis. The top-level status is the terminal-state decision point for polling. It tells you when the run stops. It does not tell you whether the run produced a checked answer. A completed analysis run can still be uncertain or have partial coverage.
Start A Workflow Run
curl --fail-with-body -X POST "$BASE_URL/api/v1alpha1/runs" \
-H "Authorization: Bearer $DEEPFRAME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: workflow-run-01" \
-d '{
"kind": "workflow",
"workflow_id": "wf_0190b5d4-7e1f-7a2b-9c3d-1234567890ab",
"source_snapshot": {"source_ids":["vid_0190b5d4-7e1f-7a2b-9c3d-1234567890ab"]},
"execute_now": true
}'The 202 response confirms acceptance. It does not confirm completion. A workflow run produces findings, and its kind detail records the workflow id and source snapshot.
Start An Analysis Run
Use stored profile_id and report_template_id references, with optional profile_version and report_template_version, as described in Analysis. Inline profile and report-template bodies are rejected on POST /api/v1alpha1/runs. The request also sends formats and the admitted execution_profile_ref.
Poll A Run
curl --fail-with-body "$BASE_URL/api/v1alpha1/runs/$RUN_ID" \
-H "Authorization: Bearer $DEEPFRAME_API_KEY"type ResultState = 'found' | 'not_found' | 'uncertain' | 'not_checked' | 'error';
type Run = {
kind: 'workflow' | 'analysis';
status: 'queued' | 'processing' | 'completed' | 'failed' | 'canceled';
analysis?: {
result_state?: ResultState;
reason_code?: string;
};
};
const terminal = new Set(['completed', 'failed', 'canceled']);
async function waitForRun(run_id: string): Promise<Run> {
while (true) {
const response = await fetch(`${baseUrl}/api/v1alpha1/runs/${run_id}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
if (!response.ok) throw new Error(`run read failed: ${response.status}`);
const run = await response.json() as Run;
if (terminal.has(run.status)) return run;
await new Promise((resolve) => setTimeout(resolve, 2_000));
}
}
const run = await waitForRun(RUN_ID);
if (run.status !== 'completed') throw new Error(`run did not complete: ${run.status}`);
if (run.kind === 'analysis' && run.analysis?.result_state !== 'found') {
throw new Error(
`run is not a successful checked result: ${run.analysis?.reason_code ?? 'result state is not found'}`,
);
}Read analysis.sub_state for progress within processing on an analysis run. A workflow run reports no finer progress than status, because its internal steps are not part of the public contract. Do not infer a terminal state from a missing field.
After a terminal response, inspect analysis.result_state and analysis.reason_code before you use analysis answers. status: completed means that execution stopped. It is not semantic success. For an evidence-backed positive result, require analysis.result_state: found. uncertain, not_checked, and error are not success states. not_found is a valid checked negative, but it is not a positive pass. Inspect each answer's result_state, coverage, limitations, and evidence before you use its values.
A completed analysis run can still contain no checked answers. This happens when required evidence is unavailable or incomplete, or when the analysis budget ends before an answer is checked; a long enough video can exhaust the budget. In this case, the run can be completed while its analysis.result_state is not_checked, and one or more answers can also have result_state: not_checked. Read the reason_code and limitations before you decide what to do. Completed plus uncertain or partial is not success.
Validate Answer Semantics
Read the full answer projection before creating or using a report. The expand[] values below include event-level evidence and the answer payload that carries detailed coverage and limitations:
ANSWERS="$(curl --fail-with-body --get "$BASE_URL/api/v1alpha1/runs/$RUN_ID/answers" \
-H "Authorization: Bearer $DEEPFRAME_API_KEY" \
--data-urlencode "expand[]=events" \
--data-urlencode "expand[]=events.evidence")"
if ! jq -e '
(.data | length > 0)
and all(.data[];
.result_state == "found"
and .coverage.state == "complete"
and ((.answer_payload.coverage.gaps // []) | length == 0)
and ((.answer_payload.limitations // []) | length == 0)
and (.evidence_count > 0)
)
' <<<"$ANSWERS" >/dev/null; then
echo "The run is not a clean, complete, evidence-backed result." >&2
exit 1
fiThis is a strict full-scope gate. Review any non-empty limitations instead of hiding them. Any coverage state other than complete, or any non-empty coverage.gaps, is partial or limited and is not a successful full-video result. For timeline answers, also inspect every answer_payload.events[] item and its required attributes. Each claim used by the report must have a result_state and a timestamped, reviewable evidence reference. A non-zero aggregate evidence_count is not enough.
Result States
Answer-level semantic results use four result states. The run-level analysis.result_state also permits error when execution fails before a trustworthy result is available. The presentation table below applies to answer-level states; it rephrases them but never reclassifies them:
| Machine state | English presentation |
|---|---|
found / present | No status line; the content itself |
not_found | "Not observed in this video" plus checked-evidence counts |
uncertain | "Could not be verified" plus the primary reason in plain words and a pointer to the JSON artifact for machine codes |
not_checked | "Not analyzed" plus the reason |
| Limitations | A "Notes on this analysis" list in plain language; machine codes stay in JSON |
The JSON answers, reports, and manifests keep the machine state, reason code, and limitation code. Use the plain-language presentation for readers, and use the JSON artifact when code-level detail is needed.
Reason Codes
A reason_code explains a result_state. These are the public reason-code values.
| Code | Meaning | Caller action |
|---|---|---|
manifest_unavailable | Required evidence information was not available. | Retry after the source becomes available. If it repeats, contact support. |
tenant_context_invalid | The request did not include a valid workspace context. | Check the API key and workspace access, then retry. |
not_applicable | The request does not apply to the selected video. | Do not retry unless the request or video changes. |
no_required_evidence | The request has no required evidence, so no evidence check ran. | Treat the result as not checked. Change the request if you need an evidence-backed result. |
requirements_satisfied | All required evidence conditions were satisfied. | No retry is needed. Read the result and its evidence. |
required_evidence_backfill | The run needed more evidence before it could check the answer. | Wait for the terminal result. Retry with a source that has the missing evidence if it remains not checked. |
backfill_capability_unavailable | The missing required evidence could not be obtained. | Use a source with the required evidence, then retry. |
backfill_not_authorized | The request was not allowed to obtain missing evidence. | Check API key permissions and workspace access, then retry. |
budget_exhausted | The analysis budget ended before the answer was checked. A video that is long enough can cause this. | Treat the answer as not checked. Reduce the video scope or request fewer answers, then retry. |
execution_failed | Execution failed while producing the result. | Treat the answer as not checked. If it repeats, contact support. |
required_evidence_not_extracted | Required evidence for the answer was unavailable. | Use a source with the required evidence, then retry. |
optional_evidence_unavailable | Optional evidence was unavailable. Required evidence may still support an answer. | Use the answer with its limitation, or select a source with the optional evidence and retry. |
coverage_state_invalid | The API could not determine valid evidence coverage. | Retry. If it repeats, contact support. |
present | The required evidence was present. | No retry is needed. Read the result and its evidence. |
index_profile_incomplete | The selected video does not contain all evidence types needed for the request. | Select a source with the needed evidence or change the request. |
conflicting_evidence | The available evidence supports conflicting results. | Treat the answer as uncertain and review its evidence. |
capability_not_implemented | The requested answer type is not available. | Choose an available answer type or contact support. |
Treat a reason code you do not recognize as non-fatal: read result_state and limitations and proceed accordingly.
Cancel A Run
curl --fail-with-body -X POST "$BASE_URL/api/v1alpha1/runs/$RUN_ID/cancel" \
-H "Authorization: Bearer $DEEPFRAME_API_KEY" \
-H "Idempotency-Key: run-cancel-01"Cancellation is asynchronous. Poll the run until its top-level status is canceled.
Read The Result
- Workflow run:
GET /api/v1alpha1/findings?run_id={run_id}withVIEW_INSIGHTS. - Analysis run:
GET /api/v1alpha1/runs/{run_id}/answerswithVIEW_INSIGHTS. - Presentation: read the automatically rendered artifacts after completion. Use
POST /api/v1alpha1/runs/{run_id}/reportsonly to explicitly re-render a different presentation, then list and retrieve its persisted artifacts with the analysis guide.
For an analysis run, inspect result_state, reason_code, and limitations before you use answer values. A not_checked answer is not a successful result.
List operations use the {data, next_cursor, has_more} envelope. See Conventions.