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.
- Reference
- REST API
- One job
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.
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.
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.
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.
Request
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.
- http://localhost:8087/v2/vif/vod/files
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''{ "files": [ { … } ], "truncated": true }
Request
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.
- video/mp4
- application/octet-stream
- http://localhost:8087/v2/vif/vod/files
- curl
- Java
- Python
- JavaScript
- video/mp4
- application/octet-stream
curl -i -X POST \
-u <username>:<password> \
'' \
-H 'Content-Type: video/mp4' \
-d string{ "file": "string", "size_bytes": 0, "modified_at": "2019-08-24T14:15:22Z" }
Request
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.
- http://localhost:8087/v2/vif/vod/files
- curl
- Java
- Python
- JavaScript
curl -i -X DELETE \
-u <username>:<password> \
''Request
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.
- http://localhost:8087/v2/vif/vod/jobs
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''One page of jobs, and the arithmetic to walk the others.
This page's jobs, newest first.
The stream group config the job was submitted with, by name; null for an inline-only job.
The configured listeners a file job cannot serve (overlay, ID3) and skipped.
True when a write failure cut the stored results short of the file's end; a resume fills the gap.
Where the job is in its lifecycle.
Why a job failed, as a class a client can act on; error carries the words.
A ceiling estimate of the requests the file takes; requests_sent may land one short of it.
The file's duration, when the container could be probed.
When the job reached a terminal state; null while it is still queued or running.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
{ "offset": 0, "limit": 0, "count": 0, "total": 0, "jobs": [ { … } ] }
Request
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.
A stream group config by its name. Its config is the middle layer, over the default config; its match rule is not consulted. Pre-v2 configuration files answer to their file name without the extension.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
Whether to keep the job's detections for GET .../results. false runs the job status-only, which needs a listener that can run offline.
Where to POST this job's state changes, overriding the VOD settings' destination. Absent inherits that destination; "" turns notifications off for this job. The configured secret is sent only to the configured destination, never to one given here — authorize a destination of this job's own by naming a secret in lifecycle_webhook_secret.
The name of a configured secret whose value goes out as the Authorization header on this job's notifications. A name nothing configures is refused at submit.
- http://localhost:8087/v2/vif/vod/jobs
- curl
- Java
- Python
- JavaScript
curl -i -X POST \
-u <username>:<password> \
'' \
-H 'Content-Type: application/json' \
-d '{
"file": "string",
"stream_group_config": "string",
"config": {
"active": true,
"detector": {
"type": "scene"
},
"listeners": {
"property1": {
"type": "overlay",
"name": "string",
"enabled": true,
"trigger": "immediate",
"min_confidence": 1,
"suppress_empty": true,
"etag": "string"
},
"property2": {
"type": "overlay",
"name": "string",
"enabled": true,
"trigger": "immediate",
"min_confidence": 1,
"suppress_empty": true,
"etag": "string"
}
},
"processing": {
"inference_fps": 0,
"window_seconds": 0,
"video_height": 0,
"grayscale": true,
"frame_source": "transcoder",
"grab_interval_seconds": 0,
"buffer_frames": 0,
"auto_throttle": true,
"catch_up": {
"enabled": true,
"max_behind_seconds": 0
},
"rollup_interval_seconds": 0,
"gpu_ids": [
0
]
},
"service": {
"url": "string",
"api_key": "string",
"model_idle_timeout_seconds": 0
},
"diagnostics": {
"save_images": true,
"timing_log_seconds": 0,
"max_logged_messages": 0
}
},
"store_results": true,
"tag": "string",
"lifecycle_webhook": "string",
"lifecycle_webhook_secret": "string",
"auto_resume": true
}'The job as it was queued (without config and effective_config; read the job for those).
The stream group config the job was submitted with, by name; null for an inline-only job.
The configured listeners a file job cannot serve (overlay, ID3) and skipped.
True when a write failure cut the stored results short of the file's end; a resume fills the gap.
Where the job is in its lifecycle.
Why a job failed, as a class a client can act on; error carries the words.
A ceiling estimate of the requests the file takes; requests_sent may land one short of it.
When the job reached a terminal state; null while it is still queued or running.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
{ "job_id": "string", "file": "string", "tag": "string", "detector_type": "scene", "stream_group_config": "string", "listener_warning": "string", "store_results": true, "results_truncated": true, "state": "pending", "error": "string", "error_cause": "response_timeout", "requests_sent": 0, "requests_total": 0, "media_time_ms": 0, "source_duration_ms": 0, "queued_at": "2019-08-24T14:15:22Z", "started_at": "2019-08-24T14:15:22Z", "ended_at": "2019-08-24T14:15:22Z", "resumes": 0, "config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } }, "effective_config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } } }
- http://localhost:8087/v2/vif/vod/jobs/{jobId}
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''The job.
The stream group config the job was submitted with, by name; null for an inline-only job.
The configured listeners a file job cannot serve (overlay, ID3) and skipped.
True when a write failure cut the stored results short of the file's end; a resume fills the gap.
Where the job is in its lifecycle.
Why a job failed, as a class a client can act on; error carries the words.
A ceiling estimate of the requests the file takes; requests_sent may land one short of it.
When the job reached a terminal state; null while it is still queued or running.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
{ "job_id": "string", "file": "string", "tag": "string", "detector_type": "scene", "stream_group_config": "string", "listener_warning": "string", "store_results": true, "results_truncated": true, "state": "pending", "error": "string", "error_cause": "response_timeout", "requests_sent": 0, "requests_total": 0, "media_time_ms": 0, "source_duration_ms": 0, "queued_at": "2019-08-24T14:15:22Z", "started_at": "2019-08-24T14:15:22Z", "ended_at": "2019-08-24T14:15:22Z", "resumes": 0, "config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } }, "effective_config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } } }
Request
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.
- http://localhost:8087/v2/vif/vod/jobs/{jobId}
- curl
- Java
- Python
- JavaScript
curl -i -X DELETE \
-u <username>:<password> \
''- http://localhost:8087/v2/vif/vod/jobs/{jobId}/cancel
- curl
- Java
- Python
- JavaScript
curl -i -X POST \
-u <username>:<password> \
''Accepted; the job as it stood when the cancel was taken.
The stream group config the job was submitted with, by name; null for an inline-only job.
The configured listeners a file job cannot serve (overlay, ID3) and skipped.
True when a write failure cut the stored results short of the file's end; a resume fills the gap.
Where the job is in its lifecycle.
Why a job failed, as a class a client can act on; error carries the words.
A ceiling estimate of the requests the file takes; requests_sent may land one short of it.
When the job reached a terminal state; null while it is still queued or running.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
{ "job_id": "string", "file": "string", "tag": "string", "detector_type": "scene", "stream_group_config": "string", "listener_warning": "string", "store_results": true, "results_truncated": true, "state": "pending", "error": "string", "error_cause": "response_timeout", "requests_sent": 0, "requests_total": 0, "media_time_ms": 0, "source_duration_ms": 0, "queued_at": "2019-08-24T14:15:22Z", "started_at": "2019-08-24T14:15:22Z", "ended_at": "2019-08-24T14:15:22Z", "resumes": 0, "config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } }, "effective_config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } } }
Request
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 settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
- http://localhost:8087/v2/vif/vod/jobs/{jobId}/resume
- curl
- Java
- Python
- JavaScript
curl -i -X POST \
-u <username>:<password> \
'' \
-H 'Content-Type: application/json' \
-d '{
"config": {
"active": true,
"detector": {
"type": "scene"
},
"listeners": {
"property1": {
"type": "overlay",
"name": "string",
"enabled": true,
"trigger": "immediate",
"min_confidence": 1,
"suppress_empty": true,
"etag": "string"
},
"property2": {
"type": "overlay",
"name": "string",
"enabled": true,
"trigger": "immediate",
"min_confidence": 1,
"suppress_empty": true,
"etag": "string"
}
},
"processing": {
"inference_fps": 0,
"window_seconds": 0,
"video_height": 0,
"grayscale": true,
"frame_source": "transcoder",
"grab_interval_seconds": 0,
"buffer_frames": 0,
"auto_throttle": true,
"catch_up": {
"enabled": true,
"max_behind_seconds": 0
},
"rollup_interval_seconds": 0,
"gpu_ids": [
0
]
},
"service": {
"url": "string",
"api_key": "string",
"model_idle_timeout_seconds": 0
},
"diagnostics": {
"save_images": true,
"timing_log_seconds": 0,
"max_logged_messages": 0
}
}
}'Accepted; the job as it was queued again.
The stream group config the job was submitted with, by name; null for an inline-only job.
The configured listeners a file job cannot serve (overlay, ID3) and skipped.
True when a write failure cut the stored results short of the file's end; a resume fills the gap.
Where the job is in its lifecycle.
Why a job failed, as a class a client can act on; error carries the words.
A ceiling estimate of the requests the file takes; requests_sent may land one short of it.
When the job reached a terminal state; null while it is still queued or running.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
The settings that make a stream analyze: which detector runs, what its listeners do with the results, how frames are processed, which service analyzes them, and diagnostics. Every document that carries one keeps it under a member literally named config — see "Model" in this API's description for how stream group configs, overrides and running streams each use one.
Except on a running stream, where every layer is already resolved, a config is sparse: an omitted member isn't a value, it inherits from the layer below. Most members merge field by field; detector replaces the whole section at once instead, and listeners merge per entry by name — see "Model" for why.
{ "job_id": "string", "file": "string", "tag": "string", "detector_type": "scene", "stream_group_config": "string", "listener_warning": "string", "store_results": true, "results_truncated": true, "state": "pending", "error": "string", "error_cause": "response_timeout", "requests_sent": 0, "requests_total": 0, "media_time_ms": 0, "source_duration_ms": 0, "queued_at": "2019-08-24T14:15:22Z", "started_at": "2019-08-24T14:15:22Z", "ended_at": "2019-08-24T14:15:22Z", "resumes": 0, "config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } }, "effective_config": { "active": true, "detector": { … }, "listeners": { … }, "processing": { … }, "service": { … }, "diagnostics": { … } } }
Request
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.
- http://localhost:8087/v2/vif/vod/jobs/{jobId}/results
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''{ "job_id": "string", "offset": 0, "limit": 0, "count": 0, "total": 0, "results": [ {} ] }
Request
The results file itself, one JSON object per line, as an attachment named <jobId>.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.
- http://localhost:8087/v2/vif/vod/jobs/{jobId}/results/file
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''Request
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).
- http://localhost:8087/v2/vif/vod/jobs/{jobId}/thumbnail
- curl
- Java
- Python
- JavaScript
curl -i -X GET \
-u <username>:<password> \
''