# VOD On-demand analysis: the video files under the Engine's content directory, and the jobs that analyze them. Unlike a running stream, a job outlives its analysis and is neither a config nor a stream. It just names the config it should use when you submit it, and keeps a record of what it actually used once it's done. ## List the files a VOD job can analyze - [GET /vod/files](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/listvodfiles.md): Every analyzable container under the Engine's content directory, as the relative paths a job names its file by, newest first. At most 500 entries are listed; truncated: true marks a listing that was cut off, and the newest files are the ones kept. A listing is not a probe: a file here can still turn out to carry no H.264 track, which the job reports when it runs. ## Upload a source file into the content directory - [POST /vod/files](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/createvodfile.md): The request body is the file itself; the target name rides the query string because names carry subdirectory slashes. The bytes are written beside the target and renamed into place, so a partial upload is never visible under an analyzable name, and the file is in the listing — and submittable — the moment this answers. Uploads never overwrite: 409 when the name is taken. 400 for no name, an absolute or escaping path, a non-analyzable extension, or a path segment a file already occupies. 413 for an upload larger than the VOD settings' max_upload_bytes. ## Remove a source file from the content directory - [DELETE /vod/files](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/deletevodfile.md): The opposite of the upload: the file ?file= names, exactly as the listing spells it, is removed. Nothing else goes with it — no job record, stored rows or thumbnail, an emptied subdirectory stays, and a symbolic link is removed as the link, never what it points at. Files are not owned by jobs. A finished job keeps its record and results without its source; a failed or cancelled job on a removed file can no longer be resumed — the resume answers 409 saying the source cannot be resolved, and automatic resume stands down. 409 while a queued or running job is using the file, naming the job: cancel it first, then delete. 404 when no such file is there. 400 for no name, an absolute or escaping path, or a non-analyzable extension — the content directory is the Engine's playback directory, and this removes only what the listing could show. ## List the jobs this Engine knows about - [GET /vod/jobs](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/listvodjobs.md): Newest first, one page at a time. The tag and state filters are applied before the page is taken, so total is what they selected and ?state=pending&limit=1 is a queue depth. A listing is a reading, not a subscription: a job can leave the state it was selected for before the answer is read. Finished jobs stay listed until the retention settings evict them or a DELETE removes them. ## Submit a file for analysis - [POST /vod/jobs](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/createvodjob.md): Queues an offline analysis of file, a path under the content directory as GET /vod/files lists it, and answers as soon as the job is queued; progress is polled from the job. The job's configuration is resolved when it is submitted, in the same layers a stream's is: default config < stream_group_config < config. stream_group_config names a stream group config (its match rule plays no part — the job uses its config); config is an inline config layered over it, or over the default config alone. At least one of the two is required; both are allowed. The layering rules are the contract's: a detector declared at a layer replaces the whole detector below it, listeners layer per entry, everything else field by field. What the job resolved to is recorded on it (effective_config on the single-job view) and a later edit of the group never touches a job already submitted. 400 for anything wrong with the body: a missing or unsupported file, an unknown stream_group_config, neither configuration member, a configuration that selects no detector or is inactive, no runnable listener together with store_results: false, an unusable lifecycle_webhook URL, a lifecycle_webhook_secret naming no configured secret. 503 when VOD is unavailable on this Engine. ## One job - [GET /vod/jobs/{jobId}](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/getvodjob.md): Includes both config (as submitted) and effective_config (as resolved and run). ## Remove a finished job - [DELETE /vod/jobs/{jobId}](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/deletevodjob.md): Removes the job's record, stored rows and thumbnail. Only a job in a terminal state can be removed: 409 for one still queued or running (cancel it first), for one that has just ended and is still writing its record (try again), and for one that was resumed while the removal waited. A removal is never reported that did not happen. ## Stop a queued or running job - [POST /vod/jobs/{jobId}/cancel](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/cancelvodjob.md): The job settles to cancelled off this request and keeps its record and stored rows; removing those is what DELETE is for. 409 for a job already in a terminal state — a cancel that raced completion says the job completed rather than pretend it stopped anything. ## Resume a failed or cancelled job - [POST /vod/jobs/{jobId}/resume](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/resumevodjob.md): The same job id runs again from where its stored results stop, appending to the same results file rather than analyzing the source afresh; resumes counts the runs. A job submitted with a stream_group_config reloads that group by name and re-layers the inline config it was submitted with — the group must still resolve to the same analysis, or the resume is refused. An inline-only job whose credentials were redacted out of its record takes them from the body: config must be the same analysis as submitted, and only its credentials are taken. A body on a group-built job is refused. 400 for a body this API cannot read. 409 for every other refusal, each saying which: a job still queued or running, a completed job with nothing to fill in, a job that kept no results, a source file that changed since the job ran, a configuration that no longer matches, credentials the record does not hold and the body did not supply, a resume point this file cannot open a window on, a job still writing its record (try again). ## The job's stored detections, one page at a time - [GET /vod/jobs/{jobId}/results](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/listvodjobresults.md): Every response the analysis service returned for the job, as the job stored it — media-time stamped and unfiltered by any listener's gating — verbatim rows, never reshaped. A job still running serves what it has answered so far. ?from_ms&to_ms narrow the page to a half-open stretch of the source. 404 when the job is unknown, when it was submitted with store_results: false, or when it has not stored a row yet; the detail says which. ## The job's detections as NDJSON - [GET /vod/jobs/{jobId}/results/file](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/getvodjobresultsfile.md): The results file itself, one JSON object per line, as an attachment named .jsonl. A job whose results were compressed at rest is served verbatim under Content-Encoding: gzip to a client that accepts it, and decompressed to one that does not; either way what arrives is the same lines. 404 as for the paged results. ## The job's frame (in progress or final) - [GET /vod/jobs/{jobId}/thumbnail](https://developer.wowza.com/docs/wowza-video-intelligence-framework/api/openapi/vod/getvodjobthumbnail.md): The job's own decoded frame — the size, scaling and encoding the detector was given — so it shows what was analyzed rather than a re-render of the source. 404 when the job is unknown or has no frame to show, which is every job on the clip path (a synthetic detector relays encoded video and never decodes a picture).