NAV Navbar
shell python javascript

API Documentation

#
# The shell examples on this page require the `jq` utility, which can be
# downloaded from: https://stedolan.github.io/jq
#

Welcome to the Voxel51 Platform API Documentation!

The Platform API is the underlying interface through which you can interact with the video understanding algorithms deployed on the Voxel51 Platform. The API exposes mechanisms that you can use to manage all aspects of your platform account, including uploading and managing data resources, running analytics on data, monitoring the status of jobs, downloading the outputs of jobs, and more.

The Platform API is a RESTful API that is accessible via standard HTTP requests. In addition, we provide client libraries for the API in Python and JavaScript (Node.js). The Python client library can be downloaded from https://github.com/voxel51/api-py, and the JavaScript client library can be downloaded from https://github.com/voxel51/api-js.

The left panel of this page describes the API routes and their associated parameters, and the right panel shows example code and responses for each route. Use the tabs in the upper right to toggle the example code between the supported languages.

See the Analytics documentation for developer documentation on each publicly available analytic on the platform.

See the Applications documentation for information about managing an application deployed on top of the Voxel51 Platform.

Authentication

Example Token Activation

# Path to your API token downloaded from the Platform Console
VOXEL51_API_TOKEN="/path/to/your/api-token.json"

# Extract the private key for use in the headers of your HTTP requests
TOKEN=$(jq -r '.access_token.private_key' ${VOXEL51_API_TOKEN})
#
# OPTION 1: Temporarily activate a token for use with the Python client
#   library by setting the `VOXEL51_API_TOKEN` environment variable
#

# Path to API token downloaded from the Platform Console
# export VOXEL51_API_TOKEN="/path/to/your/api-token.json"  # in a shell

#
# OPTION 2: Permanently activate a token. Your token is copied to
#  `~/.voxel51/` and will be automatically used by subsequent client library
#  sessions
#

from voxel51.users.auth import activate_token

# Path to your API token downloaded from the Platform Console
token_path = "/path/to/your/api-token.json"

activate_token(token_path)
/*
 * OPTION 1: Temporarily activate a token for use with the JavaScript client
 *   library by setting the `VOXEL51_API_TOKEN` environment variable
 */

// Path to API token downloaded from the Platform Console
// export VOXEL51_API_TOKEN="/path/to/your/api-token.json"  // in a shell

/*
 * OPTION 2: Permanently activate a token. Your token is copied to
 *   `~/.voxel51/` and will be automatically used by subsequent client library
 *   sessions
 */

let voxel51 = require('.');

let tokenPath = '/path/to/your/api-token.json';

voxel51.users.auth.activateToken(tokenPath);

To use the API, you must first create an account at https://console.voxel51.com and create an API token at https://console.voxel51.com/account/tokens. Each API request you make must be authenticated by a valid API token.

Analytics

The Voxel51 Platform is a scalable compute cluster that allows users to process their video (or other) data through state-of-the-art video understanding algorithms. Algorithms are deployed to the platform as analytics, which are concrete processing modules that take video (or other) data as input and output metadata (e.g., object detections, image classifications, etc.) in a predefined format.

The platform contains a suite of publicly available analytics that are available to all users. In addition, users can upload custom analytics to the platform for private use.

New versions of analytics are continually published to the platform. By default, your jobs will use the latest version of an analytic, but you can specify a particular analytic version to run if desired.

See the Analytics Documentation for developer documentation on each public analytic provided on the platform.

The following table describes the meaning of the fields returned by analytics-related API requests:

Name Type Description
name String the name of the analytic
id String the ID of the analytic
version String the version of the analytic
upload_date String the date the analytic was posted
description String a short description of the analytic
scope String the permissions scope of the analytic
supports_cpu Boolean whether the analytic supports CPU execution
supports_gpu Boolean whether the analytic supports GPU execution
pending Boolean whether the analytic is pending upload completion (True) or ready to use (False)

List analytics

Example Request

curl https://api.voxel51.com/v1/analytics/list \
  -H "Authorization: Bearer ${TOKEN}"

# all versions
curl https://api.voxel51.com/v1/analytics/list?all_versions=true \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
analytics = api.list_analytics()

# all versions
analytics = api.list_analytics(all_versions=True)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.listAnalytics().then(function(analytics) {
  // Use analytics
});

// all versions
api.listAnalytics(true).then(function(analytics) {
  // Use analytics
});

Example Response

HTTP/1.1 200 OK
{
  "analytics": [
    {
      "id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
      "name": "vehicle-sense",
      "version": "0.2.0",
      "scope": "public"
    },
    ...
  ]
}
# analytics
[
    {
        "id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
        "name": "vehicle-sense",
        "version": "0.2.0",
        "scope": "public"
    },
    ...
]
// analytics
[
  {
    id: 'f6774bcf-3543-4c6d-953c-1b6d3a16a4bf',
    name: 'vehicle-sense',
    version: '0.2.0',
    scope: 'public'
  },
  ...
]

Returns a list of the available analytics, including publicly available analytics (scope=public) and custom analytics (scope=user) that you have uploaded.

Parameters

The supported query parameters are:

Name Syntax Description
all_versions all_versions=true/false whether to return all versions of each analytic or only the latest version. The default is false

Download documentation

Example Request

curl https://api.voxel51.com/v1/analytics/:analyticId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

# ID of the analytic
analytic_id = "XXXXXXXX"

api = API()
doc = api.get_analytic_doc(analytic_id)
let voxel51 = require('.');

// ID of the analytic
let analyticId = 'XXXXXXXX';

let api = new voxel51.users.api.API();
api.getAnalyticDoc(analyticId).then(function(doc) {
  // Use doc
});

Example Response

HTTP/1.1 200 OK
{
  "info": {
    "name": "<analytic-name>",
    "version": "<analytic-version>",
    "supports_cpu": <true/false>,
    "supports_gpu": <true/false>,
    "description": "<analytic-description>"
  },
  "inputs": [
    {
      "name": "<input-name>",
      "type": "<input-type>",
      "description": "<input-description>",
      "required": <true/false>
    },
    ...
  ],
  "outputs": [
    {
      "name": "<output-name>",
      "type": "<output-type>",
      "description": "<output-description>",
      "filename": "<output-filename>",
      "post_as_data": <true/false>,
      "schema": <output-schema>
    },
    ...
  ],
  "parameters": [
    {
      "name": "<param-name>",
      "type": "<param-type>",
      "description": "<param-description>",
      "required": <true/false>,
      "default": <default-value>
    },
    ...
  ],
  "zip_outputs": <true/false>
}
# doc
{
    "info": {
        "name": "<analytic-name>",
        "version": "<analytic-version>",
        "supports_cpu": <True/False>,
        "supports_gpu": <True/False>,
        "description": "<analytic-description>"
    },
    "inputs": [
        {
            "name": "<input-name>",
            "type": "<input-type>",
            "description": "<input-description>",
            "required": <True/False>
        },
        ...
    ],
    "outputs": [
        {
            "name": "<output-name>",
            "type": "<output-type>",
            "description": "<output-description>",
            "filename": "<output-filename>",
            "post_as_data": <True/False>,
            "schema": <output-schema>
        },
        ...
    ],
    "parameters": [
        {
            "name": "<param-name>",
            "type": "<param-type>",
            "description": "<param-description>",
            "required": <True/False>,
            "default": <default-value>
        },
        ...
    ],
    "zip_outputs": <true/false>
}
// doc
{
  info: {
    name: '<analytic-name>',
    version: '<analytic-version>',
    supports_cpu: <true/false>,
    supports_gpu: <true/false>,
    description: '<analytic-description>'
  },
  inputs: [
    {
      name: '<input-name>',
      type: '<input-type>',
      description: '<input-description>',
      required: <true/false>
    },
    ...
  ],
  outputs: [
    {
      name: '<output-name>',
      type: '<output-type>',
      description: '<output-description>',
      filename: '<output-filename>',
      post_as_data: <true/false>,
      schema: <output-schema>
    },
    ...
  ],
  parameters: [
    {
      name: '<param-name>',
      type: '<param-type>',
      description: '<param-description>',
      required: <true/false>,
      default: <default-value>
    },
    ...
  ],
  zip_outputs: <true/false>
}

Downloads documentation for the specified analytic, including a description of the analytic's functionality, the inputs and parameters required to construct a job request, and the outputs generated by the analytic.

Parameters

Name Type Description
:analyticId String the ID of the analytic

Response Fields

Name Type Description
info String the ID of the analytic
      name String the name of the analytic
      version String the version of the analytic
      supports_cpu Boolean whether the analytic supports CPU execution
      supports_gpu Boolean whether the analytic supports GPU execution
      description String a short description of the analytic
inputs Array an array of objects describing the inputs of the analytic
      name String the name of the input
      type String the type of the input
      description String a short description of the input
      required Boolean whether the input is required for the analytic to execute
outputs Array an array of objects describing the outputs of the analytic
      name String the name of the output
      type String the type of the output
      description String a short description of the output
      filename String the name of the output within the generated output zip
      post_as_data Boolean whether the output will be posted as data to the platform on the user's behalf (True) or included in the job output download (False)
      schema Object an analytic-dependent schema describing the schema of the output. Analytics that generate metadata files describing videos will typically provide schemas in VideoLabels format. This field may be null if no schema is available
parameters Array an array of objects describing the parameters of the analytic
      name String the name of the parameter
      type String the type of the parameter
      description String a short description of the parameter
      required Boolean whether the parameter is required for the analytic to execute
      default type the default value for the parameter (optional parameters only)
zip_outputs Boolean whether the outputs will be downloaded in a zip file (True) or directly as a file of the type specified by the output's filename field (False). this will always be true if the analytic generates two or more outputs that are not posted as data

Query analytics

Example Request

curl https://api.voxel51.com/v1/analytics?fields=id,name,version&sort=upload_date:asc \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API
from voxel51.users.query import AnalyticsQuery

api = API()

analytics_query = (AnalyticsQuery()
    .add_fields(["id", "name", "version"])
    .sort_by("upload_date"))

analytics = api.query_analytics(analytics_query)
let voxel51 = require('.');

let api = new voxel51.users.api.API();

let analyticsQuery = (new voxel51.users.query.AnalyticsQuery()
    .addFields(['id', 'name', 'version'])
    .sortBy('name'))

api.queryAnalytics(analyticsQuery).then(function(analytics) {
  // Use analytics
});

Example Response

HTTP/1.1 200 OK
{
  "analytics": [
    {
      "id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
      "name": "vehicle-sense",
      "version": "0.2"
    },
    ...
  ],
  "total": 42
}
# analytics
{
    "analytics": [
        {
            "id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
            "name": "vehicle-sense",
            "version": "0.2"
        },
        ...
    ],
    "total": 42
}
// analytics
{
  analytics: [
    {
      id: 'f6774bcf-3543-4c6d-953c-1b6d3a16a4bf',
      name: 'vehicle-sense',
      version: '0.2'
    },
    ...
  ],
  total: 42
}

Generic analytic query route that provides full customization of the analytic records returned by the query. Supported customization options include:

Parameters

The supported query parameters are:

Name Syntax Description
fields fields=<field_name1>,<field_name2>... a comma-separated list of field names to include in the returned records
search search=<field_name>:<search_string1>,... a comma-separated list of field + search string pairs by which to filter the returned records
sort sort=<field_name>:<asc/desc> a field to sort by and the desired direction (ascending or descending)
limit limit=<#> a limit on the number of records to return
offset offset=<#> an offset to the start of the returned records
all_versions all_versions=<true/false> whether to include all versions of each analytic or just the latest version of each

The fields key allows you to specify the fields that are included in the returned records. To specify the fields to include, use the syntax: fields:<field_name1>,<field_name2>.... Any supported fields for analytics can be included in this list.

The search key allows you to restrict results to those whose field(s) contain the specified string(s). To search on one or more fields, use the syntax: search=<field_name>:<search_string>,....

The sort key allows you to sort the returned records by a desired field in either ascending (asc) or descending (desc) order. To sort by a given field, use the syntax: sort=<field_name>:<asc/desc>.

The limit key allows you to set an upper bound on the number of records that your query returns. To set a returned record limit, use the syntax: limit=<#>.

The offset key allows you to offset the starting point of the returned records. For example, an offset of 10 will return records 11, 12, etc. To set a returned record offset, use the syntax: offset=<#>.

The all_versions key allows you to specify whether to return all versions of each analytic in your query or just the latest version of each. Use this key with the syntax: all_versions=<true/false>.

Upload analytic

Example Request

curl https://api.voxel51.com/v1/analytics \
  -H "Authorization: Bearer ${TOKEN}" \
  -F "file=@${ANALYTIC_JSON_PATH}"
from voxel51.users.api import API

# Local path to the analytic JSON file
upload_analytic_path = "/path/to/analytic.json"

api = API()
metadata = api.upload_analytic(upload_analytic_path)
let voxel51 = require('.');

# Local path to the analytic JSON file
let uploadAnalyticPath = '/path/to/analytic.json';

let api = new voxel51.users.api.API();
api.uploadAnalytic(uploadAnalyticPath).then(function(metadata) {
  // Use metadata
});

Example Response

HTTP/1.1 201 Created
{
  "analytic": {
    "id": "fb6ff03b-cd83-4439-81ac-c4c84c291b38",
    "name": "my-custom-analytic",
    "version": "0.1.0",
    "scope": "private",
    "description": "A custom analytic",
    "supports_cpu": true,
    "supports_gpu": true
  }
}
# metadata
{
    "id": "fb6ff03b-cd83-4439-81ac-c4c84c291b38",
    "name": "my-custom-analytic",
    "version": "0.1.0",
    "scope": "private",
    "description": "A custom analytic",
    "supports_cpu": True,
    "supports_gpu": True
}
// metadata
{
  id: 'fb6ff03b-cd83-4439-81ac-c4c84c291b38',
  name: 'my-custom-analytic',
  version: '0.1.0',
  scope: 'private',
  description: 'A custom analytic',
  supports_cpu: true,
  supports_gpu: true
}

Uploads an analytic JSON that describes a custom private analytic that you plan to deploy to the platform. The analytic JSON should follow the schema described in this route. The analytic will be in a pending state until the necessary Docker images are uploaded via this route.

See the Platform SDK Documentation for more information about deploying your custom analytic in a Docker image that is compatible with the Voxel51 Platform.

Parameters

Name Type Description
file String the path to the analytic JSON to upload

Upload Docker image

Example Request

curl https://api.voxel51.com/v1/analytics/:analyticId/images?type=cpu \
  -H "Authorization: Bearer ${TOKEN} \
  -F "file=@${DOCKER_IMAGE_TAR_FILEPATH}"
from voxel51.users.api import API

# Local path to a tar.gz of your image
upload_image_tar_path = "/path/to/image.tar.gz"

image_type = "gpu"  # "cpu" or "gpu"

api = API()
api.upload_analytic_image(analytic_id, upload_image_tar_path, image_type)
let voxel51 = require('.');

// Local path to a tar.gz of your image
let uploadImageTarPath = '/path/to/image.tar.gz';

let imageType = 'gpu';  // 'cpu' or 'gpu'

let api = new voxel51.users.api.API();
api.uploadAnalyticImage(analyticId, uploadImageTarPath, imageType);

Example Response

HTTP/1.1 202 Accepted
{}
# N/A
// N/A

Uploads a Docker image for a newly-published analytic, which must have first been registered via the upload analytic route. The type parameter must be providied to indicate whether the image you are uploading supports CPU or GPU-based exeuction. See the Platform SDK Documentation for more information about supporting execution environments in your images.

Docker images must be uploaded to the platform as tarfiles. For more information about building your Docker image and saving it as a tarfile, see the Platform SDK's Quickstart Guide.

After you have successfully uploaded images for the execution environment(s) that your analytic declares, your analytic is ready to use!

Parameters

Name Type Description
:analyticId String the ID of the analytic
file String the path to the Docker image tarfile to upload
type String the execution type of the image ("cpu" or "gpu")

Delete analytic

Example Request

curl -X DELETE https://api.voxel51.com/v1/analytics/:analyticId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
api.delete_analytic(analytic_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.deleteAnalytic(analyticId);

Example Response

HTTP/1.1 204 No Content
{}
# N/A
// N/A

Deletes the analytic with the given ID.

Parameters

Name Type Description
:analyticId String the ID of the analytic

Data

Data can be uploaded to the Voxel51 Platform at any time.

Data uploads are independent from jobs. Indeed, a single data can be passed to as many jobs as you like. Data can be uploaded either via the Platform Console or via the API.

Each data uploaded to the platform has a default lifespan, and all data storage during this default lifespan is free. When the lifespan of data expires, it is automatically deleted. The time-to-live (TTL) of data can be viewed and modified via the console or via the API.

Data can be downloaded or deleted from the platform at any time. Note that download data incurs a small fee based on the bandwidth used. These fees are tracked and reported in your billing statements.

The following table describes the meaning of the fields returned by data-related API requests:

Field Type Description
id String the ID of the data
name String the filename of the data
encoding String the encoding scheme of the data
type String the MIME type of the data
size Number the size of the data file, in bytes
upload_date String the date the data was uploaded
expiration_date String the expiration date of the data

Upload data

Example Request

curl https://api.voxel51.com/v1/data \
  -H "Authorization: Bearer ${TOKEN}" \
  -F "file=@${FILEPATH}" \
  -F "data_ttl:YYYY-MM-DDThh:mm:ss.sssZ"
from voxel51.users.api import API

# Local path to the data
upload_data_path = "/path/to/video.mp4"

api = API()
metadata = api.upload_data(upload_data_path)
let voxel51 = require('.');

// Local path to the data
let uploadDataPath = '/path/to/video.mp4';

let api = new voxel51.users.api.API();
api.uploadData(uploadDataPath).then(function(metadata) {
  // Use metadata
});

Uploads the specified data file to cloud storage. Each uploaded data is assigned a unique ID number that can be used to reference the data when constructing job requests, manipulating data storage, and more.

The optional field data_ttl can be supplied to set the data's time-to-live. This field must be expressed as an ISO 8601 date string.

Example Response

HTTP/1.1 201 Created
{
  "data": {
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743
  }
}
# metadata
{
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743
}
// metadata
{
  id: '473bbd78-aada-4790-b539-ca90125056cd',
  name: 'video.mp4',
  type: 'video/mp4',
  size: 784743
}

Parameters

Name Type Description
file String the path to the data file
data_ttl String the desired TTL for the data. If not provided, the default TTL is used

Post data as URL

Example Request

curl https://api.voxel51.com/v1/data/url \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"signed_url": "<signed-url>"}' \
  -d '{"filename": "<filename>}' \
  -d '{"mimetype": "<mimetype>"}' \
  -d '{"size": <size-bytes>}' \
  -d '{"data_ttl": "YYYY-MM-DDThh:mm:ss.sssZ"}'
from voxel51.users.api import API

# Info about the data to post
url = "https://storage.googleapis.com/XXXXX"  # a GET-accessible URL
filename = "video.mp4"
mime_type = "video/mp4"
size = 784743  # in bytes

api = API()
metadata = api.post_data_as_url(url, filename, mime_type, size)
let voxel51 = require('.');

// Info about the data to post
let url = 'https://storage.googleapis.com/XXXXX';  // a GET-accessible URL
let filename = 'video.mp4';
let mimeType = 'video/mp4';
let size = 784743;  // in bytes

let api = new voxel51.users.api.API();
api.postDataAsURL(url, filename, mimeType, size).then(function(metadata) {
  // Use metadata
});

Posts the specified data to cloud storage. The data is not accessed nor uploaded at posting time. Instead, the provided URL and metadata are stored as a reference to the file. The URL must be accessible via an HTTP GET request so that the platform can access the data when requested.

Each uploaded data is assigned a unique ID number that can be used to reference the data when constructing job requests, manipulating data storage, and more.

The optional field data_ttl can be supplied to set the data's time-to-live. This field must be expressed as an ISO 8601 date string.

Example Response

HTTP/1.1 201 Created
{
  "data": {
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743
  }
}
# metadata
{
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743
}
// metadata
{
  id: '473bbd78-aada-4790-b539-ca90125056cd',
  name: 'video.mp4',
  type: 'video/mp4',
  size: 784743
}

Parameters

Name Type Description
signed_url String the URL (typically a signed URL) of the data. Must be publicly accessible via a GET request
filename String the filename of the data
mimetype String the MIME type of the data
size Number the size of the data file, in bytes
encoding String an optional encoding scheme of the data
data_ttl String the desired TTL for the data. If not provided, the default TTL is used

Get data details

Example Request

curl https://api.voxel51.com/v1/data/:dataId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
metadata = api.get_data_details(data_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getDataDetails(dataId).then(function(metadata) {
  // Use metadata
});

Example Response

HTTP/1.1 200 OK
{
  "data": {
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743,
    "upload_date": "2018-11-30T01:12:28.000Z",
    "expiration_date": "2018-12-03T01:12:29.000Z"
  }
}
# metadata
{
    "id": "473bbd78-aada-4790-b539-ca90125056cd",
    "name": "video.mp4",
    "type": "video/mp4",
    "size": 784743,
    "upload_date": "2018-11-30T01:12:28.000Z",
    "expiration_date": "2018-12-03T01:12:29.000Z"
}
// metadata
{
  id: '473bbd78-aada-4790-b539-ca90125056cd',
  name: 'video.mp4',
  type: 'video/mp4',
  size: 784743,
  upload_date: '2018-11-30T01:12:28.000Z',
  expiration_date: '2018-12-03T01:12:29.000Z'
}

Gets information about the data with the given ID.

Parameters

Name Type Description
:dataId String the ID of the data

List data

Example Request

curl https://api.voxel51.com/v1/data/list \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
data = api.list_data()
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.listData().then(function(data) {
  // Use data
});

Example Response

HTTP/1.1 200 OK
{
  "data": [
    {
      "id": "473bbd78-aada-4790-b539-ca90125056cd",
      "name": "video.mp4"
    },
    ...
  ]
}
# data
[
    {
        "id": "473bbd78-aada-4790-b539-ca90125056cd",
        "name": "video.mp4"
    },
    ...
]
// data
[
  {
    id: '473bbd78-aada-4790-b539-ca90125056cd',
    name: 'video.mp4'
  },
  ...
]

Returns a list of all data currently stored in the cloud.

Query data

Example Request

curl https://api.voxel51.com/v1/data?fields=id,name,upload_date&sort=upload_date:desc \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API
from voxel51.users.query import DataQuery

api = API()

data_query = (DataQuery()
    .add_fields(["id", "name", "upload_date"])
    .sort_by("upload_date", descending=True))

results = api.query_data(data_query)
let voxel51 = require('.');

let api = new voxel51.users.api.API();

let dataQuery = (new voxel51.users.query.DataQuery()
    .addFields(['id', 'name', 'upload_date'])
    .sortBy('upload_date', descending=true))

api.queryData(dataQuery).then(function(results) {
  // Use results
});

Example Response

HTTP/1.1 200 OK
{
  "data": [
    {
      "id": "473bbd78-aada-4790-b539-ca90125056cd",
      "name": "video.mp4",
      "upload_date": "2018-11-30T01:12:28.000Z"
    },
    ...
  ],
  "total": 42
}
# results
{
    "data": [
        {
            "id": "473bbd78-aada-4790-b539-ca90125056cd",
            "name": "video.mp4",
            "upload_date": "2018-11-30T01:12:28.000Z"
        },
        ...
    ],
    "total": 42
}
// results
{
  data: [
    {
      id: '473bbd78-aada-4790-b539-ca90125056cd',
      name: 'video.mp4',
      upload_date: '2018-11-30T01:12:28.000Z'
    },
    ...
  ],
  total: 42
}

Generic data query route that provides full customization of the data records returned by the query. Supported customization options include:

Parameters

The supported query parameters are:

Name Syntax Description
fields fields=<field_name1>,<field_name2>... a comma-separated list of field names to include in the returned records
search search=<field_name>:<search_string1>,... a comma-separated list of field + search string pairs by which to filter the returned records
sort sort=<field_name>:<asc/desc> a field to sort by and the desired direction (ascending or descending)
limit limit=<#> a limit on the number of the returned records
offset offset=<#> an offset to the start of the returned records

The fields key allows you to specify the fields that are included in the returned records. To specify the fields to include, use the syntax: fields:<field_name1>,<field_name2>.... Any supported fields for data can be included in this list.

The search key allows you to restrict results to those whose field(s) contain the specified string(s). To search on one or more fields, use the syntax: search=<field_name>:<search_string>,....

The sort key allows you to sort the returned records by a desired field in either ascending (asc) or descending (desc) order. To sort by a given field, use the syntax: sort=<field_name>:<asc/desc>.

The limit key allows you to set an upper bound on the number of records that your query returns. To set a returned record limit, use the syntax: limit=<#>.

The offset key allows you to offset the starting point of the returned records. For example, an offset of 10 will return records 11, 12, etc. To set a returned record offset, use the syntax: offset=<#>.

Update TTL

Example Request

curl -X PUT https://api.voxel51.com/v1/data/:dataId/ttl \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"days": <days>}'
from voxel51.users.api import API

api = API()
api.update_data_ttl(data_id, days)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.updateDataTTL(dataId, days);

Example Response

HTTP/1.1 200 OK
{}
# N/A
// N/A

Updates the expiration date of the data by the specified number of days. To decrease the lifespan of the data, provide a negative number.

Parameters

Name Type Description
:dataId String the ID of the data
days Number the number of days by which to extend the lifespan of the data. When a negative number of days is provided, the lifespan of the data is decreased

Delete data

Example Request

curl -X DELETE https://api.voxel51.com/v1/data/:dataId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
api.delete_data(data_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.deleteData(dataId);

Example Response

HTTP/1.1 204 No Content
{}
# N/A
// N/A

Deletes the data with the given ID from cloud storage. If the data time-to-live was extended and the time of deletion is past the original, default time-to-live, a small storage fee is incurred.

Parameters

Name Type Description
:dataId String the ID of the data

Download data

Example Request

curl https://api.voxel51.com/v1/data/:dataId/download \
  -H "Authorization: Bearer ${TOKEN}" \
  -O "${JOB_OUTPUT}"
from voxel51.users.api import API

# Local path to which to download the data
output_path = "..."

api = API()
api.download_data(data_id, output_path=output_path)
let voxel51 = require('.');

// Local path to which to download the data
let outputPath = '...';

let api = new voxel51.users.api.API();
api.downloadData(dataId, outputPath);

Example Response

HTTP/1.1 200 OK
{}
# N/A
// N/A

Downloads the data with the given ID from cloud storage.

Parameters

Name Type Description
:dataId String the ID of the data
OUTPUT_PATH String the output path to write the data

Get download URL

Example Request

curl https://api.voxel51.com/v1/data/:dataId/download-url \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
url = api.get_data_download_url(data_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getDataDownloadURL(dataId).then(function(url) {
  // Use url
});

Example Response

HTTP/1.1 200 OK
{
  "url": "<url>"
}
# url
"<url>"
// url
'<url>'

Gets a signed download URL for the data with the given ID.

Parameters

Name Type Description
:dataId String the ID of the data

Jobs

To run an analytic on data uploaded to the Voxel51 Platform, you must create a job.

Jobs can be created either via the Platform Console or the API. Jobs can be created and saved for later execution, or they can be configured to be executed immediately upon creation.

A job can be in the following states:

State Description
READY the job has been created and is ready for execution
QUEUED the job has been queued and is awaiting resources to become available in your account's quota in order to be scheduled for execution
SCHEDULED the job has been scheduled for execution in the cloud but has not yet started
RUNNING the job is currently running in the cloud
COMPLETE the job has finished and was successful
FAILED the job failed during execution

Once a job has progressed to the RUNNING state, a status file is populated that tracks the job's status. This status file can be accessed at any time via the Platform Console or via the download job status API route.

Once a job is COMPLETE, its output can be downloaded via the console or the provided download job output API route.

A job may FAIL for one of the following reasons:

Failure Type Description
USER the job failed due to a problem with the user-provided data or job parameters; the user must address the issue before reprocessing the data
ANALYTIC the job failed and the analytic has self-reported that it is to blame; typically the analytic must be repaired by the developer before users can process more data
PLATFORM the job failed due to an internal platform error; it is safe to retry the job
NONE no failure occured

If a job fails, the failiure type is accessible via the failure_type field of the job metadata. A USER failure may occur, for example, if a user uploads invalid data (e.g., a corrupted video or a non-video or otherwise unsupported type for the given analytic). In such cases, the user must address the issue before rerunning the job. An ANALYTIC failure occurs when an analytic self-reports that it is to blame for the failure of a job. In such cases, the analytic will likely be taken down for maintenance and users should wait for the issue to be resolved before rerunning the analytic. A PLATFORM failure is reported when the platform encounters an internal error. In such cases, it is safe to retry the job. If platform errors persist, the job cluster may be temporarily deactivated until the issue is resolved.

A complete history of the jobs that you have executed on the platform is maintained at all times. However, jobs can be archived and unarchived, which allows you to better organize your job history. These actions are reversible.

The following table describes the meaning of the fields returned by job-related API requests:

Field Type Description
id String the ID of the job
name String the name of the job
state String the state of the job
archived Boolean the archival status of the job
auto_start Boolean the auto-start setting for the job
compute_mode String the compute mode of the job
upload_date String the upload date of the job
analytic_id String the analytic id of the job
start_date String the start date of the job
queued_time Number the number of milliseconds the job was queued
execution_time Number the number of milliseconds required for the job to execute
completion_date String the date the job completed
fail_date String the date the job failed
failure_type String the type of job failure (if any)

Upload job request

Example Request

# Create job request
echo '{
  "analytic": "<analytic>",
  "version": null,
  "compute_mode": "BEST",
  "inputs": {
    "<input>": {"data-id": "<data-id>"}
  },
  "parameters": {
    ...
  }
}' > "${JOB_REQUEST}"

# Upload job request
curl https://api.voxel51.com/v1/jobs \
  -H "Authorization: Bearer ${TOKEN}" \
  -F "file=@${JOB_REQUEST}" \
  -F "job_name=${JOB_NAME}" \
  -F "auto_start=true/false" \
  -F "job_ttl=YYYY-MM-DDThh:mm:ss.sssZ"
from voxel51.users.api import API
from voxel51.users.jobs import JobRequest, JobComputeMode

#
# Details of the analytic to run
#
# analytic: the name of the analytic
# version: an optional version of the analytic to use. By default, the latest
#     version is used
# compute_mode: the compute mode to use. By default, the best available
#     execution mode is used (typically, GPU)
#
analytic = "<analytic>"
version = None
compute_mode = JobComputeMode.BEST

job_request = JobRequest(analytic, version=version, compute_mode=compute_mode)
job_request.set_input("<input>", data_id="<data-id>")
job_request.set_parameter("<param1>", val1)
job_request.set_parameter("<param2>", val2)

api = API()
metadata = api.upload_job_request(job_request, "<job-name>", auto_start=True)
let voxel51 = require('.');

/*
 * Details of the analytic to run
 *
 * analytic: the name of the analytic
 * version: an optional version of the analytic to use. By default, the latest
 *   version is used
 * computeMode: the compute mode to use. By default, the best available
 *   execution mode is used (typically, GPU)
 */
let analytic = '<analytic>';
let version = undefined;
let computeMode = voxel51.users.jobs.JobComputeMode.BEST;

let jobRequest = new voxel51.users.jobs.JobRequest(
  analytic, version, computeMode);
let inputPath = voxel51.users.jobs.RemoteDataPath.fromDataId('<data-id>');
jobRequest.setInput('<input>', inputPath);
jobRequest.setParameter('<param1>', val1);
jobRequest.setParameter('<param2>', val2);

let api = new voxel51.users.api.API();
api.uploadJobRequest(jobRequest, '<job-name>', true).then(
  function(metadata) {
    // Use metadata
  }
);

Example Response

HTTP/1.1 201 Created
{
  "job": {
    "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
    "name": "vehicle-sense-test",
    "compute_mode": "GPU",
    "auto_start": true
  }
}
# metadata
{
    "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
    "name": "vehicle-sense-test",
    "compute_mode": "GPU",
    "auto_start": True
}
// metadata
{
  id: 'bddf1acb-fde4-45c3-b127-22278bb5b982',
  name: 'vehicle-sense-test',
  compute_mode: 'GPU',
  auto_start: true
}

Uploads a new job request.

Job requests instruct the platform to run an analytic on some data. Each job request specifies the analytic to run, and they can also optionally specify the version of the analytic to run and configure whether CPU or GPU resources are used to execute the job by specifying the compute_mode. By default, the latest version of the analytic is used, and the best available compute type supported by the given analytic version is used. The input(s) of the job request specify the data-id of the data to process, and parameter values can be set as necessary to configure the analytic.

The optional field auto_start can be used to specify whether the job should be automatically started after it is uploaded, and the optional field job_ttl can be supplied to set the job's time-to-live. This field must be expressed as an ISO 8601 date string.

The following table describes the possible compute_mode settings for jobs:

Compute Mode Description
CPU run the job using only CPU resources
GPU run the job using GPU resources
BEST use the best available resources to execute the job; in particular, if the specified version of the analytic supports GPU execution, it will be used. This is the default behavior

Parameters

Name Type Description
file String the path to a job request JSON file to upload
job_name String a name for the job
auto_start Boolean whether to automatically start the job upon creation. The default is false
job_ttl String the desired TTL for the job output. If not provided, the default TTL is used

Get job details

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
metadata = api.get_job_details(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getJobDetails(jobId).then(function(metadata) {
  // Use metadata
});

Example Response

HTTP/1.1 200 OK
{
  "job": {
    "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
    "name": "vehicle-sense-test",
    "auto_start": true,
    "compute_mode": "GPU",
    "state": "READY",
    "analytic_id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
    "upload_date": "2018-11-30T14:36:09.000Z",
    "archived": false
  }
}
# metadata
{
    "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
    "name": "vehicle-sense-test",
    "auto_start": True,
    "compute_mode": "GPU",
    "state": "READY",
    "analytic_id": "f6774bcf-3543-4c6d-953c-1b6d3a16a4bf",
    "upload_date": "2018-11-30T14:36:09.000Z",
    "archived": False
}
// metadata
{
  id: 'bddf1acb-fde4-45c3-b127-22278bb5b982',
  name: 'vehicle-sense-test',
  auto_start: true,
  compute_mode: 'GPU',
  state: 'READY',
  analytic_id: 'f6774bcf-3543-4c6d-953c-1b6d3a16a4bf',
  upload_date: '2018-11-30T14:36:09.000Z',
  archived: false
}

Gets details about the job with the given ID.

Parameters

Name Type Description
:jobId String the ID of the job

List jobs

Example Request

curl https://api.voxel51.com/v1/jobs/list \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
jobs = api.list_jobs()
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.listJobs().then(function(jobs) {
  // Use jobs
});

Example Response

HTTP/1.1 200 OK
{
  "jobs": [
    {
      "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
      "name": "vehicle-sense-test",
      "state": "READY"
    },
    ...
  ]
}
# jobs
[
    {
        "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
        "name": "vehicle-sense-test",
        "state": "READY"
    },
    ...
]
// jobs
[
  {
    id: 'bddf1acb-fde4-45c3-b127-22278bb5b982',
    name: 'vehicle-sense-test',
    state: 'READY'
  },
  ...
]

Returns a list of all unarchived jobs uploaded to the platform.

Start job

Example Request

curl -X PUT https://api.voxel51.com/v1/jobs/:jobId/start \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

# ID of the job
job_id = "XXXXXXXX"

api = API()
api.start_job(job_id)
let voxel51 = require('.');

// ID of the job
let jobId = 'XXXXXXXX';

let api = new voxel51.users.api.API();
api.startJob(jobId);

Example Response

HTTP/1.1 200 OK
{
  "state": "<state>"
}
# N/A
// N/A

Starts the job with the given ID.

Parameters

Name Type Description
:jobId String the ID of the job

Query jobs

Example Request

curl https://api.voxel51.com/v1/jobs?fields=id,name,state&sort=name:asc \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API
from voxel51.users.query import JobsQuery

api = API()

jobs_query = (JobsQuery()
    .add_fields(["id", "name", "state"])
    .sort_by("name"))

results = api.query_jobs(jobs_query)
let voxel51 = require('.');

let api = new voxel51.users.api.API();

let jobsQuery = (new voxel51.query.JobsQuery()
  .addFields(['id', 'name', 'state'])
  .sortBy('name'))

api.queryJobs(jobsQuery).then(function(results) {
  // Use results
});

Example Response

HTTP/1.1 200 OK
{
  "jobs": [
    {
      "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
      "name": "vehicle-sense-test",
      "state": "READY"
    },
    ...
  ],
  "total": 42
}
# results
{
    "jobs": [
        {
            "id": "bddf1acb-fde4-45c3-b127-22278bb5b982",
            "name": "vehicle-sense-test",
            "state": "READY"
        },
        ...
    ],
    "total": 42
}
// results
{
  jobs: [
    {
      id: 'bddf1acb-fde4-45c3-b127-22278bb5b982',
      name: 'vehicle-sense-test',
      state: 'READY'
    },
    ...
  ],
  total: 42
}

Generic jobs query route that provides full customization of the job records returned by the query. Supported customization options include:

Parameters

The supported query parameters are:

Name Syntax Description
fields fields=<field_name1>,<field_name2>... A comma-separated list of field names to include in the returned records
search search=<field_name>:<search_string1>,... A comma-separated list of field + search string pairs by which to filter the returned records
sort sort=<field_name>:<asc/desc> A field to sort by and the desired direction (ascending or descending)
limit limit=<#> A limit on the number of records to return
offset offset=<#> an offset to the start of the returned records

The fields key allows you to specify the fields that are included in the returned records. To specify the fields to include, use the syntax: fields:<field_name1>,<field_name2>.... Any supported fields for jobs can be included in this list.

The search key allows you to restrict results to those whose field(s) contain the specified string(s). To search on one or more fields, use the syntax: search=<field_name>:<search_string>,....

The sort key allows you to sort the returned records by a desired field in either ascending (asc) or descending (desc) order. To sort by a given field, use the syntax: sort=<field_name>:<asc/desc>.

The limit key allows you to set an upper bound on the number of records that your query returns. To set a returned record limit, use the syntax: limit=<#>.

The offset key allows you to offset the starting point of the returned records. For example, an offset of 10 will return records 11, 12, etc. To set a returned record offset, use the syntax: offset=<#>.

Archive job

Example Request

curl -X PUT https://api.voxel51.com/v1/jobs/:jobId/archive \
  -H "Authorization: Bearer ${TOKEN}
from voxel51.users.api import API

api = API()
api.archive_job(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.archiveJob(jobId);

Example Response

HTTP/1.1 204 No Content
{}
# N/A
// N/A

Archives specified job. This prevents the job from being displayed in subsequent list/query requests, providing some organizational control over jobs. This action can be undone at any time.

Parameters

Name Type Description
:jobId String the ID of the job

Unarchive job

Example Request

curl -X PUT https://api.voxel51.com/v1/jobs/:jobId/unarchive \
  -H "Authorization: Bearer ${TOKEN}
from voxel51.users.api import API

api = API()
api.unarchive_job(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.unarchiveJob(jobId);

Example Response

HTTP/1.1 204 No Content
{}
# N/A
// N/A

Unarchives specified job. This re-enables the job for display in subsequent list/query requests.

Parameters

Name Type Description
:jobId String the ID of the job

Update TTL

Example Request

curl -X PUT https://api.voxel51.com/v1/jobs/:jobId/ttl \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"days": <days>}'
from voxel51.users.api import API

api = API()
api.update_job_ttl(job_id, days)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.updateJobTTL(jobId, days);

Example Response

HTTP/1.1 200 OK
{}
# N/A
// N/A

Updates the expiration date of the job by the specified number of days. To decrease the lifespan of the job, provide a negative number.

Parameters

Name Type Description
:jobId String the ID of the job
days Number the number of days by which to extend the lifespan of the job. When a negative number of days is provided, the lifespan of the job is decreased

Delete job

Example Request

curl -X DELETE https://api.voxel51.com/v1/jobs/:jobId \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
api.delete_job(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.deleteJob(jobId);

Example Response

HTTP/1.1 204 No Content
{}
# N/A
// N/A

Deletes the specified job. The job must not have been started.

Parameters

Name Type Description
:jobId String the ID of the job

Download job output

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/output \
  -H "Authorization: Bearer ${TOKEN}" \
  -O "${JOB_OUTPUT}"
from voxel51.users.api import API

# Local path to which to download the output
job_output_path = "/path/to/output.ext"

api = API()
api.wait_until_job_completes(job_id)
api.download_job_output(job_id, job_output_path)
let voxel51 = require('.');

// Local path to which to download the output
let jobOutputPath = '/path/to/output.ext';

let api = new voxel51.users.api.API();
api.waitUntilJobCompletes(jobId).then(function() {
  api.downloadJobOutput(jobId, jobOutputPath).then(function() {
    console.log('Download complete');
  });
});

Example Response

HTTP/1.1 200 OK
{}
# N/A
// N/A

Wait until a job is complete and download its output. The client library examples demonstrate how to write/use a function that waits until the job is marked as COMPLETE and initiates the output download at that time. The bash example does not support this waiting functionality.

Parameters

Name Type Description
:jobId String the ID of the job

Get output download URL

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/output-url \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
url = api.get_job_output_download_url(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getJobOutputDownloadURL(jobId).then(function(url) {
  // Use url
});

Example Response

HTTP/1.1 200 OK
{
  "url": "<url>"
}
# url
"<url>"
// url
'<url>'

Gets a signed URL for downloading the output of the job with the given ID.

Parameters

Name Type Description
:jobId String the ID of the job

Download job request

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/specs \
  -H "Authorization: Bearer ${TOKEN}" \
  -O "${JOB_REQUEST}"
from voxel51.users.api import API

api = API()
job_request = api.get_job_request(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getJobRequest(jobId).then(function(jobRequest) {
  // Use jobRequest
});

Example Response

HTTP/1.1 200 OK
{
  "analytic": "<name>",
  "version": "<version>",
  "inputs": {
    "<input-name>": {
      "data-id": "<data-id>"
    },
    ...
  },
  "parameters": {
    "<param-name>": <param-value>,
    ...
  }
}
# a voxel51.users.jobs.JobRequest instance
// a voxel51.users.jobs.JobRequest instance

Downloads the initial job request JSON for the job with the given ID. This file is a representation of the user-created specification for the given job.

Parameters

Name Type Description
:jobId String the ID of the job

Download job status

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/status \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
status = api.get_job_status(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getJobStatus(jobId).then(function(status) {
  // Use status
});

Example Response

HTTP/1.1 200 OK
{
  "name": "vehicle-sense",
  "state": "COMPLETE",
  "failure_type": "NONE",
  "start_time": "2018-12-06 19:05:58",
  "fail_time": null,
  "complete_time": "2018-12-06 19:05:59",
  "messages": [
    {
      "message": "vehicle-sense loaded",
      "time": "2018-12-06 19:05:57"
    },
    {
      "message": "Inputs and parameters downloaded",
      "time": "2018-12-06 19:05:58"
    },
    {
      "message": "Job request parsed",
      "time": "2018-12-06 19:05:58"
    },
    {
      "message": "Pipeline started",
      "time": "2018-12-06 19:05:58"
    },
    {
      "message": "Outputs published",
      "time": "2018-12-06 19:05:59"
    },
    {
      "message": "Task complete",
      "time": "2018-12-06 19:05:59"
    }
  ]
}
# status
{
    "name": "vehicle-sense",
    "state": "COMPLETE",
    "failure_type": "NONE",
    "start_time": "2018-12-06 19:05:58",
    "fail_time": None,
    "complete_time": "2018-12-06 19:05:59",
    "messages": [
        {
            "message": "vehicle-sense loaded",
            "time": "2018-12-06 19:05:57"
        },
        {
            "message": "Inputs and parameters downloaded",
            "time": "2018-12-06 19:05:58"
        },
        {
            "message": "Job request parsed",
            "time": "2018-12-06 19:05:58"
        },
        {
            "message": "Pipeline started",
            "time": "2018-12-06 19:05:58"
        },
        {
            "message": "Outputs published",
            "time": "2018-12-06 19:05:59"
        },
        {
            "message": "Task complete",
            "time": "2018-12-06 19:05:59"
        }
    ]
}
// status
{
  name: 'vehicle-sense',
  state: 'COMPLETE',
  failure_type: 'NONE',
  start_time: '2018-12-06 19:05:58',
  fail_time: null,
  complete_time: '2018-12-06 19:05:59',
  messages: [
    {
      message: 'vehicle-sense loaded',
      time: '2018-12-06 19:05:57'
    },
    {
      message: 'Inputs and parameters downloaded',
      time: '2018-12-06 19:05:58'
    },
    {
      message: 'Job request parsed',
      time: '2018-12-06 19:05:58'
    },
    {
      message: 'Pipeline started',
      time: '2018-12-06 19:05:58'
    },
    {
      message: 'Outputs published',
      time: '2018-12-06 19:05:59'
    },
    {
      message: 'Task complete',
      time: '2018-12-06 19:05:59'
    }
  ]
}

Downloads the latest status JSON file for the job with the given ID.

Parameters

Name Type Description
:jobId String the ID of the job

Download job logfile

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/log \
  -H "Authorization: Bearer ${TOKEN}" \
  -O "${JOB_LOGFILE_PATH}"
from voxel51.users.api import API

# Local path to which to download the logfile
job_logfile_path = "/path/to/logfile.log"

api = API()
api.download_job_logfile(job_id, job_logfile_path)
let voxel51 = require('.');

// Local path to which to download the logfile
let jobLogfilePath = '/path/to/logfile.log';

let api = new voxel51.users.api.API();
api.downloadJobOutput(jobId, jobLogfilePath).then(function() {
  console.log('Download complete');
});

Example Response

HTTP/1.1 200 OK
{}
# N/A
// N/A

Downloads a job's logfile.

Parameters

Name Type Description
:jobId String the ID of the job

Get logfile download URL

Example Request

curl https://api.voxel51.com/v1/jobs/:jobId/log-url \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
url = api.get_job_logfile_download_url(job_id)
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getJobLogfileDownloadURL(jobId).then(function(url) {
  // Use url
});

Example Response

HTTP/1.1 200 OK
{
  "url": "<url>"
}
# url
"<url>"
// url
'<url>'

Gets a signed URL for downloading the logfile of the job with the given ID.

Parameters

Name Type Description
:jobId String the ID of the job

Types

The Voxel51 Platform API provides a strict typing system that establishes a contract for what data can be provided to the inputs and parameters of analytics and what data structures to expect when downloading the outputs of an analytic.

All analytics have types that are defined in the type system of the ETA Library. In particular, each type corresponds to a class in the eta.core.types module.

The Voxel51 Platform supports all common media formats for images an video. The majority of other types are represented as JSON, which is the primary data format used by the platform.

Builtins

Analytic parameters can either be data types from the previous section, in which case they refer to files that must be downloaded, or they can simply be values specified using a builtin type, in which case they are parsed and used directly. Since the Platform API uses JSON syntax to transfer data, each builtin parameters is represented as a valid JSON data type or a composite JSON object.

The following table enumerates the builtin data types that may be declared for the parameters of analytics. It also lists the corresponding data types that should be used when working with the Python and JavaScript client libraries.

Type Python Type JavaScript Type Description
String str string a string
Number int or float number a numeric value
Object dict object an object with string keys and unspecified value types
Array list Array an array of values of any type
Boolean bool boolean a boolean value
Null None null a null or undefined value
StringArray list of strs Array of strings an array of strings
ObjectArray list of dicts Array of objects an array of objects

File

An abstract data type representing a file in any format. This type is represented in ETA by the eta.core.types.File class.

TextFile

A plain text file in any common format. This type is represented in ETA by the eta.core.types.TextFile class.

Image

An abstract data type representing an image in any format supported by the platform. This type is represented in ETA by the eta.core.types.Image class.

Current supported image types include ImageFile.

ImageFile

An image file in any common image format (.png, .jpg, .gif, .tiff, .bmp). This type is represented in ETA by the eta.core.types.ImageFile class.

Video

An abstract data type representing a single video in any format supported by the platform. This type is represented in ETA by the eta.core.types.Video class.

Current supported video types include VideoFile and ImageSequence.

VideoFile

A video represented as a single encoded video file in any common video format (.mp4, .mpg, .mpeg, .avi, .mov, .wmv, .flv, .mkv, .m4v). This type is represented in ETA by the eta.core.types.VideoFile class.

ImageSequence

A video represented as a sequence of images with a single numeric string format parameter. For example, frames-%05.jpg. This type is represented in ETA by the eta.core.types.ImageSequence class.

VideoMetadata

Example VideoMetadata JSON

{
    "frame_size": [1920, 1080],
    "frame_rate": 30.0,
    "total_frame_count": 1800,
    "duration": 60.0,
    "size_bytes": 114320940,
    "encoding_str": "avc1"
}

A JSON file that contains metadata about a video. This type is represented in ETA by the eta.core.types.VideoMetadata class, and instances of this type can be read/generated using the eta.core.video.VideoMetadata class.

Attribute

The base type of all types that describe attributes of entities in images or video. This type is represented in ETA by the eta.core.types.Attribute class, and all attributes implemented in ETA are subclasses of the eta.core.data.Attribute class.

Attributes can be one of three types: categorical, numeric, or boolean. All attributes have a name, a value, and an optional confidence in [0, 1] associated with them.

Current supported attribute types include CategoricalAttribute, NumericAttribute, and BooleanAttribute.

AttributeSchema

The base type of all types that describe the possible values or range of values that attributes can take. This type is represented in ETA by the eta.core.types.AttributeSchema class, and all attributes implemented in ETA are subclasses of the eta.core.data.AttributeSchema class.

Each of the concrete attribute types have corresponding schema types: CategoricalAttributeSchema, NumericAttributeSchema, and BooleanAttributeSchema.

CategoricalAttribute

Example CategoricalAttribute JSON

{
    "type": "eta.core.data.CategoricalAttribute",
    "name": "scene",
    "value": "intersection",
    "confidence": 0.92
}

Categorical attributes take values within a fixed set of possible values. They are represented in ETA by the eta.core.types.CategoricalAttribute class, and instances of this type can be read/generated using the eta.core.data.CategoricalAttribute class.

CategoricalAttributeSchema

Example CategoricalAttributeSchema JSON

{
    "type": "eta.core.data.CategoricalAttribute",
    "name": "scene",
    "categories": ["intersection", "bridge", "overpass", "on ramp", "off ramp"]
}

Categorical attribute schemas define the set of possible values that a particular categorical attribute can take. They are represented in ETA by the eta.core.types.CategoricalAttributeSchema class, and instances of this type can be read/generated using the eta.core.data.CategoricalAttributeSchema class.

NumericAttribute

Example NumericAttribute JSON

{
    "type": "eta.core.data.NumericAttribute",
    "name": "vehicle_count",
    "value": 5,
    "confidence": 0.95
}

Numeric attributes take numeric values within a certain range and can be either integer or floating point. They are represented in ETA by the eta.core.types.NumericAttribute class, and instances of this type can be read/generated using the eta.core.data.NumericAttribute class.

NumericAttributeSchema

Example NumericAttributeSchema JSON

{
    "type": "eta.core.data.NumericAttribute",
    "name": "vehicle_count",
    "range": [0, 100]
}

Numeric attribute schemas define the range of possible values that a particular numeric attribute can take. They are represented in ETA by the eta.core.types.NumericAttributeSchema class, and instances of this type can be read/generated using the eta.core.data.NumericAttributeSchema class.

BooleanAttribute

Example BooleanAttribute JSON

{
    "type": "eta.core.data.BooleanAttribute",
    "name": "is_daytime",
    "value": true,
    "confidence": 0.98
}

Boolean attributes take values of true and false. They are represented in ETA by the eta.core.types.BooleanAttribute class, and instances of this type can be read/generated using the eta.core.data.BooleanAttribute class.

BooleanAttributeSchema

Example BooleanAttributeSchema JSON

{
    "type": "eta.core.data.BooleanAttribute",
    "name": "is_daytime"
}

Boolean attribute schemas simply define that the attribute of the given name is boolean, which implies that it will take values True and False. They are represented in ETA by the eta.core.types.BooleanAttributeSchema class, and instances of this type can be read/generated using the eta.core.data.BooleanAttributeSchema class.

Attributes

Example Attributes JSON

{
    "attrs": [
        {
            "type": "eta.core.data.CategoricalAttribute",
            "name": "scene",
            "value": "intersection",
            "confidence": 0.92
        },
        {
            "type": "eta.core.data.NumericAttribute",
            "name": "vehicle_count",
            "value": 5,
            "confidence": 0.95
        },
        {
            "type": "eta.core.data.BooleanAttribute",
            "name": "is_daytime",
            "value": true,
            "confidence": 0.98
        }
    ]
}

A JSON file containing a collection of attributes of an entity in an image or video. This type is represented in ETA by the eta.core.types.Attributes class, and instances of this type can be read/generated using the eta.core.data.AttributeContainer class.

Attributes files simply contain an unordered list of Attribute instances of any subtype. The JSON to the right shows an example of an Attributes instance containing attributes of each type.

AttributesSchema

Example AttributesSchema JSON

{
    "schema": {
        "scene": {
            "type": "eta.core.data.CategoricalAttribute",
            "name": "scene",
            "categories": ["intersection", "bridge", "overpass", "on ramp", "off ramp"]
        },
        "vehicle_count": {
            "type": "eta.core.data.NumericAttribute",
            "name": "vehicle_count",
            "range": [0, 100]
        },
        "is_daytime": {
            "type": "eta.core.data.BooleanAttribute",
            "name": "is_daytime"
        }
    }
}

A JSON file containing a collection of schemas that describe the possible values or range of values that a collection of attributes can take. This type is represented in ETA by the eta.core.types.AttributesSchema class, and instances of this type can be read/generated using the eta.core.data.AttributeContainerSchema class.

AttributesSchema files contain a map of attribute names to AttributeSchema instances of any subtype. The JSON to the right shows an example of an AttributesSchema instance describing attributes of each type.

BoundingBox

Example BoundingBox JSON

{
    "bottom_right": {
        "y": 0.5722222222222222,
        "x": 0.09765625
    },
    "top_left": {
        "y": 0.4708333333333333,
        "x": 0.0
    }
}

A rectangle that describes the location of an object in a frame. This type is represented in ETA by the eta.core.types.BoundingBox class, and instances of this type can be read/generated using the eta.core.geometry.BoundingBox class.

Bounding boxes are defined by their bottom-right and upper-left (x, y) coordinates in the frame. Relative values are used, so each coordinate lies in [0, 1], where [0, 0] corresponds to the upper left corner of the frame and [1, 1] corresponds to the bottom right. Representing bounding boxes in relative coordinates allows them to be correctly rendered on resized versions of an image without recording the original resolution.

DetectedObject

Example DetectedObject JSON

{
    "label": "vehicle",
    "frame_number": 1183,
    "index": 63,
    "confidence": 0.95,
    "bounding_box": {
        "bottom_right": {
            "y": 0.5722222222222222,
            "x": 0.09765625
        },
        "top_left": {
            "y": 0.4708333333333333,
            "x": 0.0
        }
    },
    "attrs": {
        "attrs": [
            {
                "type": "eta.core.data.CategoricalAttribute",
                "name": "make",
                "value": "Audi",
                "confidence": 0.92
            }
        ]
    }
}

A JSON file describing an object detected in an image or video. This type is represented in ETA by the eta.core.types.DetectedObject class, and instances of this class can be read/generated using the eta.core.objects.DetectedObject class.

DetectedObject instances have the following fields:

DetectedObjects

Example DetectedObjects JSON

{
    "objects": [
        {
            "label": "vehicle",
            "frame_number": 1183,
            "index": 63,
            "confidence": 0.95,
            "bounding_box": {
                "bottom_right": {
                    "y": 0.5722222222222222,
                    "x": 0.09765625
                },
                "top_left": {
                    "y": 0.4708333333333333,
                    "x": 0.0
                }
            },
            "attrs": {
                "attrs": [
                    {
                        "type": "eta.core.data.CategoricalAttribute",
                        "name": "make",
                        "value": "Audi",
                        "confidence": 0.92
                    }
                ]
            }
        }
    ]
}

A JSON file describing a collection of objects detected in images or videos. This type is represented in ETA by the eta.core.types.DetectedObjects class, and instances of this type can be read/generated using the eta.core.objects.DetectedObjectContainer class.

DetectedObjects files contain an unordered list of DetectedObject instances. The JSON to the right shows an example DetectedObjects instance containing a single object.

See DetectedObject for more information about the schema of a detected object instance.

ImageLabels

Example ImageLabels JSON

{
    "filename": "road.png",
    "attrs": {
        "attrs": [
            {
                "type": "eta.core.data.CategoricalAttribute",
                "name": "vehicle_density",
                "value": "light"
            }
        ]
    },
    "objects": {
        "objects": [
            {
                "label": "vehicle",
                "confidence": 0.95,
                "bounding_box": {
                    "bottom_right": {
                        "y": 0.5722222222222222,
                        "x": 0.09765625
                    },
                    "top_left": {
                        "y": 0.4708333333333333,
                        "x": 0.0
                    }
                },
                "attrs": {
                    "attrs": [
                        {
                            "type": "eta.core.data.CategoricalAttribute",
                            "name": "make",
                            "value": "Audi",
                            "confidence": 0.92
                        }
                    ]
                }
            }
        ]
    }
}

A JSON file describing the rich semantic metdata in an image. This type is represented in ETA by the eta.core.types.ImageLabels class, and instances of this class can be read/generated using the eta.core.image.ImageLabels class.

ImageLabels instances have a top-level filename field that contains the filename of the image, an attrs field that contains an Attributes instance containing image-level attributes, and an objects field that stores a DetectedObjects instance describing the objects that were detected in the image.

For example, the JSON to the right shows an ImageLabels instance describing an image with one image-level attribute and one object.

ImageSetLabels

Example ImageSetLabels JSON

{
    "images": [
        {
            "filename": "road1.png",
            "attrs": {
                "attrs": [
                    {
                        "type": "eta.core.data.CategoricalAttribute",
                        "name": "vehicle_density",
                        "value": "light"
                    }
                ]
            },
            "objects": {
                "objects": [
                    {
                        "label": "vehicle",
                        "confidence": 0.95,
                        "bounding_box": {
                            "bottom_right": {
                                "y": 0.5722222222222222,
                                "x": 0.09765625
                            },
                            "top_left": {
                                "y": 0.4708333333333333,
                                "x": 0.0
                            }
                        },
                        "attrs": {
                            "attrs": [
                                {
                                    "type": "eta.core.data.CategoricalAttribute",
                                    "name": "make",
                                    "value": "Audi",
                                    "confidence": 0.92
                                }
                            ]
                        }
                    }
                ]
            }
        },
        {
            "filename": "road2.png",
            "attrs": {
                "attrs": [
                    {
                        "type": "eta.core.data.CategoricalAttribute",
                        "name": "vehicle_density",
                        "value": "none"
                    }
                ]
            },
            "objects": {
                "objects": []
            }
        }
    ]
}

A JSON file describing the rich semantic metdata in a collection of images. This type is represented in ETA by the eta.core.types.ImageSetLabels class, and instances of this class can be read/generated using the eta.core.image.ImageSetLabels class.

ImageSetLabels instances have a top-level images field that contains a list of ImageLabels instance describing the metadata in each image.

For example, the JSON to the right shows an ImageSetLabels instance describing two images, one of which contains an object.

ImageLabelsSchema

Example ImageLabelsSchema JSON

{
    "attrs": {
        "schema": {
            "scene": {
                "type": "eta.core.data.CategoricalAttribute",
                "name": "scene",
                "categories": ["intersection", "bridge", "overpass", "on ramp", "off ramp"]
            },
            "vehicle_count": {
                "type": "eta.core.data.NumericAttribute",
                "name": "vehicle_count",
                "range": [0, 100]
            },
            "is_daytime": {
                "type": "eta.core.data.BooleanAttribute",
                "name": "is_daytime"
            }
        }
    },
    "objects": {
        "car": {
            "schema": {
                "make": {
                    "type": "eta.core.data.CategoricalAttribute",
                    "name": "make",
                    "categories": ["Ford", "Chevrolet", "Honda", "Toyota", "Nissan"]
                }
            }
        },
        "person": {
            "schema": {
                "pose": {
                    "type": "eta.core.data.CategoricalAttribute",
                    "name": "pose",
                    "categories": ["walk", "stand", "run", "sit", "lie_flat", "jump", "crawl"]
                }
            }
        }
    }
}

A JSON file describing the taxonomy of image-level and object-level attributes that may be generated when processing image(s). This type is represented in ETA by the eta.core.types.ImageLabelsSchema class, and instances of this type can be read/generated using the eta.core.image.ImageLabelsSchema class.

ImageLabelsSchema files have an attrs field that contains an AttributesSchema that describes the schema of each image-level attributes that may be generated. They also contain an objects field that maps the set of object labels that may be detected to AttributesSchema instances that describe each of the object-level attributes that may be generated for each object.

The JSON to the right shows an example of an ImageLabelsSchema instance describing the schema of a hypothetical image-based analytic.

VideoLabels

Example VideoLabels JSON

{
    "filename": "road.mp4",
    "attrs": {
        "attrs": [
            {
                "type": "eta.core.data.BooleanAttribute",
                "name": "is_daytime",
                "value": true
            }
        ]
    },
    "frames": {
        "1": {
            "frame_number": 1,
            "attrs": {
                "attrs": [
                    {
                        "type": "eta.core.data.CategoricalAttribute",
                        "name": "vehicle_density",
                        "value": "light"
                    }
                ]
            },
            "objects": {
                "objects": [
                    {
                        "label": "vehicle",
                        "frame_number": 1,
                        "index": 1,
                        "confidence": 0.95,
                        "bounding_box": {
                            "bottom_right": {
                                "y": 0.5722222222222222,
                                "x": 0.09765625
                            },
                            "top_left": {
                                "y": 0.4708333333333333,
                                "x": 0.0
                            }
                        },
                        "attrs": {
                            "attrs": [
                                {
                                    "type": "eta.core.data.CategoricalAttribute",
                                    "name": "make",
                                    "value": "Audi",
                                    "confidence": 0.92
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
}

A JSON file describing the rich semantic metdata in a video. This type is represented in ETA by the eta.core.types.VideoLabels class, and instances of this class can be read/generated using the eta.core.video.VideoLabels class.

VideoLabels instances have a top-level filename field that contains the filename of the video, a top-level attrs field that contains an Attributes instance containing video-level attributes, and a frames field that contains a dictionary keyed by frame number. Each frame contains an attrs field that stores an Attributes instance containing frame-level attributes describing the scene and an objects field that stores a DetectedObjects instance describing the objects that were detected in the frame.

For example, the JSON to the right shows a VideoLabels instance describing a video with one video-level attribute and a single frame with one frame-level attribute and one object.

VideoLabelsSchema

Example VideoLabelsSchema JSON

{
    "attrs": {
        "schema": {
            "video_quality": {
                "type": "eta.core.data.NumericAttribute",
                "name": "video_quality",
                "range": [0, 100]
            },
            "is_daytime": {
                "type": "eta.core.data.BooleanAttribute",
                "name": "is_daytime"
            }
        }
    },
    "frames": {
        "schema": {
            "scene": {
                "type": "eta.core.data.CategoricalAttribute",
                "name": "scene",
                "categories": ["intersection", "bridge", "overpass", "on ramp", "off ramp"]
            },
            "vehicle_count": {
                "type": "eta.core.data.NumericAttribute",
                "name": "vehicle_count",
                "range": [0, 100]
            },
            "is_daytime": {
                "type": "eta.core.data.BooleanAttribute",
                "name": "is_daytime"
            }
        }
    },
    "objects": {
        "car": {
            "schema": {
                "make": {
                    "type": "eta.core.data.CategoricalAttribute",
                    "name": "make",
                    "categories": ["Ford", "Chevrolet", "Honda", "Toyota", "Nissan"]
                }
            }
        },
        "person": {
            "schema": {
                "pose": {
                    "type": "eta.core.data.CategoricalAttribute",
                    "name": "pose",
                    "categories": ["walk", "stand", "run", "sit", "lie_flat", "jump", "crawl"]
                }
            }
        }
    }
}

A JSON file describing the taxonomy of video-level, frame-level, and object-level attributes that may be generated when processing a video. This type is represented in ETA by the eta.core.types.VideoLabelsSchema class, and instances of this type can be read/generated using the eta.core.video.VideoLabelsSchema class.

VideoLabelsSchema files have an attrs field that contains an AttributesSchema that describes the schema of each video-level attribute that may be generated. They also contain a frames field that contains an AttributesSchema that describes the schema of each frame-level attribute that may be generated. Finally, they contain an objects field that maps the set of object labels that may be detected to AttributesSchema instances that describe each of the object-level attributes that may be generated for each object.

The JSON to the right shows an example of an VideoLabelsSchema instance describing the schema of a hypothetical video-based analytic.

Status

Platform Status

Example Request

curl https://api.voxel51.com/v1/status/all \
  -H "Authorization: Bearer ${TOKEN}"
from voxel51.users.api import API

api = API()
status = api.get_platform_status()
let voxel51 = require('.');

let api = new voxel51.users.api.API();
api.getPlatformStatus().then(function(status) {
  // Use status
});

Example Response

HTTP/1.1 200 OK
{
  "statuses": {
    "platform": true,
    "jobs": true
  }
}
# status
{
    "platform": True,
    "jobs": True
}
// status
{
  platform: true,
  jobs: true
}

Gets the current status of the Voxel51 Platform and its component services.

The following table describes the meaning of each status flag:

Field Type Description
platform Boolean whether the platform is up. No API calls can be issued when the platform is down
jobs Boolean whether the job compute cluster is up. Jobs cannot be started when the jobs cluster is down

Status Codes

The Voxel51 Platform API issues standar HTTP/1.1 status codes in all responses. The status codes fall into the following categories:

Success Codes

The following codes are used when a request is successful:

Code Message Description
200 OK your request was successfully executed
201 Created you request to create the specified resource was successful
204 No Content your request was successfully processed and no content is returned in response

Error Codes

The following codes are used when a request fails:

Code Message Description
400 Bad Request your request was invalid
401 Unauthorized your API token was invalid
403 Forbidden you did not have permission to access the specified resource
404 Not Found the specified route could not be found
500 Internal Error something went wrong on our end