Skip to content

Wowza Video Intelligence Framework API (2.0.0)

This reference documents every endpoint in the Wowza Video Intelligence Framework (VIF) REST API, including the parameters each one takes and the request and response bodies it works with. VIF adds real-time AI video analysis, such as object detection and scene recognition, to streams running on Wowza Streaming Engine, and this API is served by the Video Intelligence Controller (VIC), a module that runs alongside the Engine's own REST interface, on port 8087 by default.

Almost everything you do with this API comes down to one idea: a config, the group of settings that tells VIF how to analyze a stream (which detector to run, what to do with the results, and so on). You'll run into a config in three places, and each one uses it a little differently. A stream group config applies a config to every stream whose name matches a pattern you choose, such as cam.*. An override applies a config to one specific stream, by its exact name instead of a pattern. A running stream reports the config it's actually using right now, alongside its live connection state and performance. Wherever you see one of these documents in the reference below, look for a config member: that's where the settings live. The rest of the document, the match rule, the stream's identity, its live state, just says how that config gets used, and isn't part of the config itself.

Configs also build on each other in layers: a stream's final settings come from a default config, then a matching stream group config, then a per-stream override, then any changes made directly to the running stream. Each layer can fill in whatever the one below it left unset. The Config schema, wherever it appears in this reference, explains exactly how that merge works, including the two members, detector and listeners, that don't merge field by field like the rest.

Endpoints are grouped below by what they work with: durable configuration you save to disk, the live streams currently running, one-off video analysis jobs, connectivity checks, and framework-wide status. Each group's description explains what you'll find in it.

A few things are worth knowing before you make your first request. Every error this API returns is application/problem+json (RFC 7807), so error.title, error.status, and error.detail tell you what went wrong; the exceptions are failures the API never gets to handle, like a URL the Engine can't route or an Engine-level authentication or license failure, which come back in the Engine's own {success, code, message} format instead. Every document you can edit under /persist comes with an ETag header; send that value back as If-Match when you write, and the API answers 428 if you forget it and 412 if it's gone stale, so you never overwrite a change you haven't seen yet. PATCH requests are a JSON Merge Patch (RFC 7386), not a full replacement: send only the fields you want to change, and anything you leave out keeps its current value. Sending a field as null removes it instead, letting it inherit from whatever's underneath, except on a running stream, where null isn't accepted for config or config.active, because a running instance needs values to actually run with; use POST .../reset there if you want to discard your changes instead. The verbs you'll use are GET, POST, PATCH, and DELETE: POST creates a document (409 if one already exists by that name) or triggers an action, like resetting a stream or resuming a job; PATCH edits a document that already exists (404 if it doesn't); DELETE removes one. This API has no PUT. Wherever an endpoint isn't JSON, uploading or downloading a video file, for example, its description says so explicitly; everything else you send or receive is JSON.

Note: This is version 2 of the VIF REST API. Version 1 is deprecated, and we strongly recommend moving any integration that writes configuration to v2. Saving through v1 rewrites your configuration files in an older format: a per-stream override saved that way loses what made it an override, and comes back instead as a stream group config matched to that one stream's literal name. Reading through v1 stays safe at any time; just make sure every integration that writes configuration moves to v2, and that you don't mix the two on one installation.

Authentication

Engine REST credentials (engineBasic). Requests are additionally subject to the Engine license entitlement (402 without it) and Engine RBAC: the "basic" role is read-only, and the Engine's REST layer answers 403 to every non-GET request from such a user, with the Engine's own JSON error format: {"success":false, "code":403, "message":"You do not have permission to access this resource"}. Both are enforced only while the Engine mounts this API with authentication (server property VideoIntelligenceServer=authorized, the default); unauthorized mounts it with neither credentials nor roles.

Download OpenAPI description
Languages
Servers
{scheme}://{host}:{port}/v2/vif

Server

Framework-wide status: which VIS instances are connected, which streams are running, and which detection models are available on them. These endpoints are read-only.

Operations

Runtime

The stream instances currently running. A GET here shows a stream's live, resolved configuration alongside its health and performance. Writes are ephemeral: they change only the running instance, are never saved to disk, and are lost if the stream or the Engine restarts. A 404 on any Runtime endpoint means the stream isn't currently running, not that it doesn't exist at all.

Operations

Persist

The durable configuration that lives on disk whether or not a stream is running: stream group configs, which apply automatically to any stream whose name matches a pattern, and per-stream overrides. Writing here saves the document, and if a running stream is governed by it, applies the change to that stream immediately. You can also write an override for a stream that isn't running yet; it takes effect as soon as the stream starts.

Operations

Edit the VOD settings

Request

A merge patch, applied to the running registry at once — a smaller max_jobs evicts, a new job_ttl_seconds reschedules retention, a new webhook or default takes effect for the next job. content_dir and jobs_dir are read at Engine start and apply at the next one. 400 for a bound violation or a lifecycle_webhook_secret naming no configured secret.

Security
engineBasic
Headers
If-Matchstringrequired

ETag of the revision this write is based on. * is not supported: quoting "any revision" defeats the concurrency check and is rejected with 412.

Bodyapplication/merge-patch+jsonrequired
max_concurrent_jobsinteger>= 1

Jobs analyzed at once; the rest queue. Default 1.

max_jobsinteger>= 1

Job records kept; the oldest finished job is evicted first. Default 25.

job_ttl_secondsinteger(int64)>= 0

How long a finished job stays before retention removes it; 0 keeps them until evicted. Default 0.

content_dirstring or null

The content directory jobs read from and uploads land in, relative to the Engine home unless absolute. Applies at the next Engine start.

jobs_dirstring or null

Where job records, results and thumbnails are stored. Applies at the next Engine start.

lifecycle_webhookstring or null

The default destination of every job's state changes; a job may override or turn it off.

lifecycle_webhook_secretstring or null

The name of the secret sent as Authorization to the default destination — and only to it.

lifecycle_webhook_headerstring or null

The header the secret's value is sent under, for receivers that expect their credential under a name of their own (X-Api-Key, for example). Absent means Authorization. Applies only to deliveries to lifecycle_webhook, like the secret: a job that brings its own destination sends its credential as Authorization unless it names a header of its own. Must be a legal header name; Content-Type and the connection-management headers are refused.

auto_resumeboolean or null

Whether a job that stops for a transient reason is resumed on its own. Default true.

max_upload_bytesinteger(int64)>= 1

The largest upload POST /vod/files accepts; beyond it, 413. Default 10 GiB.

etagstring or null

Server-assigned and ignored on a write.

curl -i -X PATCH \
  -u <username>:<password> \
  '' \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'If-Match: string' \
  -d '{
    "max_concurrent_jobs": 1,
    "max_jobs": 1,
    "job_ttl_seconds": 0,
    "content_dir": "string",
    "jobs_dir": "string",
    "lifecycle_webhook": "string",
    "lifecycle_webhook_secret": "string",
    "lifecycle_webhook_header": "string",
    "auto_resume": true,
    "max_upload_bytes": 1,
    "etag": "string"
  }'

Responses

The applied settings.

Headers
ETagstring

Opaque revision tag of the returned document.

Bodyapplication/json
max_concurrent_jobsinteger>= 1

Jobs analyzed at once; the rest queue. Default 1.

max_jobsinteger>= 1

Job records kept; the oldest finished job is evicted first. Default 25.

job_ttl_secondsinteger(int64)>= 0

How long a finished job stays before retention removes it; 0 keeps them until evicted. Default 0.

content_dirstring or null

The content directory jobs read from and uploads land in, relative to the Engine home unless absolute. Applies at the next Engine start.

jobs_dirstring or null

Where job records, results and thumbnails are stored. Applies at the next Engine start.

lifecycle_webhookstring or null

The default destination of every job's state changes; a job may override or turn it off.

lifecycle_webhook_secretstring or null

The name of the secret sent as Authorization to the default destination — and only to it.

lifecycle_webhook_headerstring or null

The header the secret's value is sent under, for receivers that expect their credential under a name of their own (X-Api-Key, for example). Absent means Authorization. Applies only to deliveries to lifecycle_webhook, like the secret: a job that brings its own destination sends its credential as Authorization unless it names a header of its own. Must be a legal header name; Content-Type and the connection-management headers are refused.

auto_resumeboolean or null

Whether a job that stops for a transient reason is resumed on its own. Default true.

max_upload_bytesinteger(int64)>= 1

The largest upload POST /vod/files accepts; beyond it, 413. Default 10 GiB.

etagstring or null

Server-assigned and ignored on a write.

Response
application/json
{ "max_concurrent_jobs": 1, "max_jobs": 1, "job_ttl_seconds": 0, "content_dir": "string", "jobs_dir": "string", "lifecycle_webhook": "string", "lifecycle_webhook_secret": "string", "lifecycle_webhook_header": "string", "auto_resume": true, "max_upload_bytes": 1, "etag": "string" }

The names of the configured secrets

Request

The global named credentials, by name only — a value never leaves the Engine. One flat namespace every credential consumer references: a config's *_secret members (service key, VLM/SVD endpoint keys, the SVD TLS client key), the VOD settings' lifecycle_webhook_secret, and a job submit's. Stored in conf.modules/vif/secrets.json; a document still at the pre-move conf.modules/vif/vod/secrets.json is read from there and relocated by the first PATCH.

Security
engineBasic
curl -i -X GET \
  -u <username>:<password> \
  ''

Responses

The secret names.

Headers
ETagstring

Opaque revision tag of the returned document.

Bodyapplication/json
namesArray of strings

The configured secret names, sorted alphabetically ignoring letter case.

etagstring or null

Server-assigned and ignored on a write.

Response
application/json
{ "names": [ "string" ], "etag": "string" }

Set, rotate or remove secrets

Request

A merge patch over values: a string sets or rotates the named secret, null removes it, a name not mentioned is kept. The revision covers the values, so a rotation changes the ETag even though the answer shows names only — and a rotation is never guarded: it applies to the next connect or delivery with no config write. A removal is guarded: 400 while anything still references the name — the VOD settings' lifecycle_webhook_secret, or any config document's *_secret member, in either stored syntax. The detail lists every use of every name the patch removes, one per line, so one round of repointing clears them all. A name the patch adds uses only letters, digits, ., _ and -, starts with a letter or digit, is at most 128 characters, and must not differ from another name only by letter case (400). Names that already exist are not checked, so they still rotate and remove.

Security
engineBasic
Headers
If-Matchstringrequired

ETag of the revision this write is based on. * is not supported: quoting "any revision" defeats the concurrency check and is rejected with 412.

Bodyapplication/merge-patch+jsonrequired
namesArray of strings

The configured secret names, sorted alphabetically ignoring letter case.

valuesobjectwrite-only

The merge patch — a string sets or rotates, null removes, an absent name is kept. A new name matches ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ and is unique ignoring letter case.

etagstring or null

Server-assigned and ignored on a write.

curl -i -X PATCH \
  -u <username>:<password> \
  '' \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'If-Match: string' \
  -d '{
    "names": [
      "string"
    ],
    "values": {
      "property1": "string",
      "property2": "string"
    },
    "etag": "string"
  }'

Responses

The names after the patch.

Headers
ETagstring

Opaque revision tag of the returned document.

Bodyapplication/json
namesArray of strings

The configured secret names, sorted alphabetically ignoring letter case.

etagstring or null

Server-assigned and ignored on a write.

Response
application/json
{ "names": [ "string" ], "etag": "string" }

Probes

Connectivity checks for external endpoints, such as the vision-language model a detector calls out to. Use these before you save a configuration, to confirm VIF can actually reach the endpoint you're pointing it at.

Operations

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.

Operations