Eluvio Tagger API v1.0.0
Authentication
- HTTP Authentication, scheme: bearer
Access to content fabric objects and resources is governed by an Ethereum-compatible blockchain. Each API resource (for example a library, content type or content object) is governed by a blockchain 'smart-contract'. All content fabric API operations require authentication using the "Bearer" token scheme. This scheme encompasses both "authentication" (identifying the caller) and "authorization" (specification of the operations that the caller has access to). The "Bearer" token is obtained by executing specific 'smart-contract' blockchain transactions for the API resources being accessed.
Private fabric nodes or development environments can also be configured for alternative authentication schemes. Currently this includes "Basic" authentication and, for development environments, no authentication.
The "Bearer" token can be specified as follows:
-
as an HTTP header
Authorization: Bearer TOKEN -
as a query parameter
?authorization=TOKEN
Bearer token general format: PAYLOAD.SIGNATURE
Where PAYLOAD is a base64 encoding of the JSON object:
{
"qspace_id": "SPACE-ID",
"qlib_id": "LIBRARY-ID",
"addr": "BLOCKCHAIN-ADDRESS",
"tx_id" : "BLOCKCHAIN-TRANSACTION-ID"
}
SIGNATURE is a base64 encoding of the Ethereum signature, calculated as specified by the Ethereum protocol: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
Creating, modifying and accessing content fabric objects require either "access" or "update" transaction IDs. These operations can only be executed by full blockchain user accounts, which must be funded in order to execute transactions. Once the transaction is executed by the blockchain, its ID will be specified in the token field "tx_id".
Consumer operations don't require funded blockchain accounts, and they are restricted to "viewer" operations, which are only available on content objects that have been specifically published for consumer access. The token is generated by executing a state channel transaction - the state channel allows for low latency response to the user (not requiring waiting for the execution of a blockchain transaction) and mass scalability by posting aggregated transactions to the blockchain in large batches.
Discover models
List available models
Code samples
# You can also use wget
curl -X GET /models \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
GET /models HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/models',
method: 'get',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/models',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.get '/models',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.get('/models', params={
}, headers = headers)
print r.json()
URL obj = new URL("/models");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/models", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/models', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
GET /models
Returns the list of models available on this tagger instance, including each model's type and the tag track it writes to.
Example responses
200 Response
{
"models": [
{
"name": "celeb",
"description": "Celebrity Identification",
"type": "frame",
"tag_tracks": [
{
"name": "celebrity_detection",
"label": "Celebrity Detection"
}
]
}
]
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | List of available models | ModelsResponse |
Operate tagging
Delete a job
Code samples
# You can also use wget
curl -X DELETE /jobs/{job_id}?authorization=string \
-H 'Authorization: Bearer {access-token}'
DELETE /jobs/{job_id}?authorization=string HTTP/1.1
var headers = {
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/jobs/{job_id}',
method: 'delete',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Authorization':'Bearer {access-token}'
};
fetch('/jobs/{job_id}?authorization=string',
{
method: 'DELETE',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.delete '/jobs/{job_id}',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Authorization': 'Bearer {access-token}'
}
r = requests.delete('/jobs/{job_id}', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/jobs/{job_id}?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("DELETE", "/jobs/{job_id}", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('DELETE','/jobs/{job_id}', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
DELETE /jobs/{job_id}
Soft-deletes a job by id. Deleted jobs are excluded from all list and status responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| job_id | path | string | true | ID of the job to delete |
| tenant | query | string | false | Tenant id. If the provided token has admin authority for the tenant than this allows you to delete jobs from other users. |
| authorization | query | string | true | none |
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 204 | No Content | Job deleted successfully | None |
| 400 | Bad Request | Bad Request | None |
| 403 | Forbidden | Unauthorized | None |
| 404 | Not Found | Job not found | None |
Tag content
Code samples
# You can also use wget
curl -X POST /{qid}/tag?authorization=string \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
POST /{qid}/tag?authorization=string HTTP/1.1
Content-Type: application/json
Accept: application/json
var headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/tag',
method: 'post',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const inputBody = '{
"options": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
},
"jobs": [
{
"model": "asr",
"model_params": {
"fps": 1.5
},
"overrides": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
}
}
]
}';
const headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/tag?authorization=string',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.post '/{qid}/tag',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.post('/{qid}/tag', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/tag?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("POST", "/{qid}/tag", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('POST','/{qid}/tag', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
POST /{qid}/tag
Body parameter
{
"options": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
},
"jobs": [
{
"model": "asr",
"model_params": {
"fps": 1.5
},
"overrides": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
}
}
]
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| qid | path | string | true | Source content to tag. |
| authorization | query | string | true | none |
| body | body | StartJobsRequest | true | Tagging options |
Example responses
200 Response
{
"jobs": [
{
"job_id": "1234",
"model": "asr",
"stream": "audio_1",
"started": true,
"message": "successfully started",
"error": null
}
]
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Success | StartTaggingResponse |
| 400 | Bad Request | Bad Request | None |
| 502 | Bad Gateway | Bad Gateway | None |
Query job statuses
Code samples
# You can also use wget
curl -X GET /job-status?authorization=string \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
GET /job-status?authorization=string HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/job-status',
method: 'get',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/job-status?authorization=string',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.get '/job-status',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.get('/job-status', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/job-status?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/job-status", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/job-status', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
GET /job-status
Returns jobs matching the given filters. If no tenant or user filter is provided, the endpoint automatically scopes results to the authenticated user. Querying by tenant requires tenant admin privileges.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authorization | query | string | true | none |
| qid | query | string | false | Filter by content id. |
| status | query | string | false | Filter by job status. |
| tenant | query | string | false | Filter by tenant. Requires tenant admin privileges. |
| user | query | string | false | Filter by user address. Must match the authenticated user unless querying as tenant admin. |
| model | query | string | false | Filter by model name (e.g. "asr", "celeb"). |
| title | query | string | false | Filter by content title (case-insensitive substring match). |
| start | query | integer | false | Pagination offset. |
| limit | query | integer | false | Maximum number of jobs to return. Null for no limit. |
Enumerated Values
| Parameter | Value |
|---|---|
| status | queued |
| status | running |
| status | completed |
| status | failed |
| status | stopped |
Example responses
200 Response
{
"jobs": [
{
"qid": "iq__3Bs4xdLS9obhmQVWHNJvJ457ZL2X",
"job_id": "efd8e379-9256-40bc-9aa6-1fab74234f85",
"status": "running",
"model": "asr",
"stream": "video",
"created_at": "2026-03-25T03:33:38.746127",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"tenant": "iten2fY3bSh8Q7zY1t6vGZ8mUNFLHAWM",
"user": "0x9d7186b18ecbb5751719795415e9b8146e1bed2b",
"title": "Casablanca",
"error": null,
"progress": 0.56,
"tagging_progress": "120/214",
"tag_details": {
"tag_status": "Fetching content",
"time_running": 70.05,
"progress": 0.56,
"tagging_progress": "120/214",
"total_parts": 214,
"downloaded_parts": 150,
"tagged_parts": 120,
"warnings": {
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
}
}
],
"meta": {
"total": 8,
"start": 0,
"limit": null,
"count": 8
}
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Success | StatusResponse |
| 403 | Forbidden | Forbidden — insufficient privileges for the requested filter | None |
Query job statuses for a single content
Code samples
# You can also use wget
curl -X GET /{qid}/job-status?authorization=string \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
GET /{qid}/job-status?authorization=string HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/job-status',
method: 'get',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/job-status?authorization=string',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.get '/{qid}/job-status',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.get('/{qid}/job-status', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/job-status?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/{qid}/job-status", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/{qid}/job-status', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
GET /{qid}/job-status
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| authorization | query | string | true | none |
Example responses
200 Response
{
"jobs": [
{
"qid": "iq__3Bs4xdLS9obhmQVWHNJvJ457ZL2X",
"job_id": "efd8e379-9256-40bc-9aa6-1fab74234f85",
"status": "running",
"model": "asr",
"stream": "video",
"created_at": "2026-03-25T03:33:38.746127",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"tenant": "iten2fY3bSh8Q7zY1t6vGZ8mUNFLHAWM",
"user": "0x9d7186b18ecbb5751719795415e9b8146e1bed2b",
"title": "Casablanca",
"error": null,
"progress": 0.56,
"tagging_progress": "120/214",
"tag_details": {
"tag_status": "Fetching content",
"time_running": 70.05,
"progress": 0.56,
"tagging_progress": "120/214",
"total_parts": 214,
"downloaded_parts": 150,
"tagged_parts": 120,
"warnings": {
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
}
}
],
"meta": {
"total": 8,
"start": 0,
"limit": null,
"count": 8
}
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Success | StatusResponse |
| 404 | Not Found | No jobs found | None |
Get tagging history across models
Code samples
# You can also use wget
curl -X GET /{qid}/tag-status \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
GET /{qid}/tag-status HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/tag-status',
method: 'get',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/tag-status',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.get '/{qid}/tag-status',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.get('/{qid}/tag-status', params={
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/tag-status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/{qid}/tag-status", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/{qid}/tag-status', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
GET /{qid}/tag-status
Returns an overview of each model that has been run against the given content, including the track it writes to, the last time it was run, and its percent completion.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| qid | path | string | true | Content object id to check status for |
| authorization | query | string | false | Fabric authorization token |
Example responses
200 Response
{
"models": [
{
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"percent_completion": 0.85
},
{
"model": "asr",
"track": "speech_to_text",
"last_run": "2026-02-24T12:00:00Z",
"percent_completion": 1
}
]
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Tagging status summary for every model that has been run on the content | ContentStatusResponse |
Get detailed job history for a model
Code samples
# You can also use wget
curl -X GET /{qid}/tag-status/{model} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
GET /{qid}/tag-status/{model} HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/tag-status/{model}',
method: 'get',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/tag-status/{model}',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.get '/{qid}/tag-status/{model}',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.get('/{qid}/tag-status/{model}', params={
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/tag-status/{model}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/{qid}/tag-status/{model}", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/{qid}/tag-status/{model}', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
GET /{qid}/tag-status/{model}
Returns a detailed breakdown of a single model's tagging history on the given content, including a high-level summary and a list of every job that has been run.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| qid | path | string | true | Content object id to check status for |
| model | path | string | true | Model identifier (e.g. "celeb", "asr") |
| authorization | query | string | false | Fabric authorization token |
Example responses
200 Response
{
"summary": {
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"tagging_progress": 0.85,
"num_content_parts": 120
},
"jobs": [
{
"time_ran": "1h 0m 0s",
"source_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"job_status": {
"status": "Completed",
"time_ran": "1h 0m 0s"
},
"upload_status": {
"num_job_parts": 60,
"num_tagged_parts": 60
}
}
]
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Detailed model tagging status including job history | ModelStatusResponse |
Stop tagging jobs by content
Code samples
# You can also use wget
curl -X POST /{qid}/stop?authorization=string \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
POST /{qid}/stop?authorization=string HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/stop',
method: 'post',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/stop?authorization=string',
{
method: 'POST',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.post '/{qid}/stop',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.post('/{qid}/stop', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/stop?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("POST", "/{qid}/stop", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('POST','/{qid}/stop', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
POST /{qid}/stop
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| qid | path | string | true | Stop all jobs against this content. |
| authorization | query | string | true | none |
Example responses
200 Response
{
"jobs": [
{
"job_id": "1234",
"message": "string"
}
],
"message": "string"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Success | StopTaggingResponse |
Stop tagging jobs by model
Code samples
# You can also use wget
curl -X POST /{qid}/stop/{model}?authorization=string \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
POST /{qid}/stop/{model}?authorization=string HTTP/1.1
Accept: application/json
var headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
$.ajax({
url: '/{qid}/stop/{model}',
method: 'post',
data: '?authorization=string',
headers: headers,
success: function(data) {
console.log(JSON.stringify(data));
}
})
const fetch = require('node-fetch');
const headers = {
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/{qid}/stop/{model}?authorization=string',
{
method: 'POST',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.post '/{qid}/stop/{model}',
params: {
'authorization' => 'string'
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.post('/{qid}/stop/{model}', params={
'authorization': 'string'
}, headers = headers)
print r.json()
URL obj = new URL("/{qid}/stop/{model}?authorization=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("POST", "/{qid}/stop/{model}", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('POST','/{qid}/stop/{model}', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
POST /{qid}/stop/{model}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| qid | path | string | true | Content object id |
| model | path | string | true | Model name |
| authorization | query | string | true | none |
Example responses
200 Response
{
"jobs": [
{
"job_id": "1234",
"message": "string"
}
],
"message": "string"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Success | StopTaggingResponse |
Schemas
StartJobsRequest
{
"options": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
},
"jobs": [
{
"model": "asr",
"model_params": {
"fps": 1.5
},
"overrides": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
}
}
]
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| options | TaggerOptions | false | Knobs that apply to all tagger jobs in the request. |
| jobs | [JobSpec] | true | List of individual job parameters. |
TaggerOptions
{
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| destination_qid | string | false | Content where tags should be written to. Empty string indicates that they should be written to the same content that we are tagging. |
| replace | boolean | false | Replace already existing tagstore tags. Set to true to retag, set to false to enbable diff-based tagging. |
| max_fetch_retries | integer | false | If a fetch operation fails, we can retry this many times before the job is marked as failed. |
| scope | object | false | Scope of tagging. The format should match one of the Scope schemas. The type of scope provided as well as the parameters affets what media will get tagged. |
JobSpec
{
"model": "asr",
"model_params": {
"fps": 1.5
},
"overrides": {
"destination_qid": "",
"replace": false,
"max_fetch_retries": 3,
"scope": {
"type": "video",
"start_time": 100,
"end_time": 200
}
}
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| model | string | true | Name of model to run |
| model_params | object | false | Model level parameters |
| overrides | TaggerOptions | false | none |
ScopeVideo
{
"type": "video",
"start_time": 0,
"end_time": 600,
"stream": "audio_1"
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | true | Scope identifier to remove ambiguity |
| start_time | integer | false | Start tagging at this point in the media stream (in seconds) |
| end_time | integer | false | End tagging at this point in the media stream (in seconds) |
| stream | string | false | Audio or video stream to tag. If this value is not set, it's value will be automatically set depending on the model and the content. |
Enumerated Values
| Property | Value |
|---|---|
| type | video |
ScopeProcessor
{
"type": "processor",
"start_time": 0,
"end_time": 600,
"chunk_size": 600,
"stream": "video"
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | true | Scope identifier to remove ambiguity |
| start_time | integer | false | Start tagging at this point in the media stream (in seconds) |
| end_time | integer | false | End tagging at this point in the media stream (in seconds) |
| chunk_size | integer | false | Processor will be fed intervals of this size to tag |
| stream | string | false | Media stream |
Enumerated Values
| Property | Value |
|---|---|
| type | processor |
ScopeAssets
{
"type": "assets",
"assets": [
"assets/hello1.jpg",
"assets/hello2.jpg"
]
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | true | Scope identifier to remove ambiguity |
| assets | [string] | false | List of asset paths to tag |
Enumerated Values
| Property | Value |
|---|---|
| type | assets |
ScopeLivestream
{
"type": "livestream",
"stream": "video",
"segment_length": 4,
"max_duration": 0
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | true | Scope identifier to remove ambiguity |
| stream | string | false | Media stream |
| segment_length | integer | false | Tagging interval size (in seconds) |
| max_duration | integer|null | false | Maximum amount of content from livestream to tag (in seconds) |
Enumerated Values
| Property | Value |
|---|---|
| type | livestream |
StartTaggingResponse
{
"jobs": [
{
"job_id": "1234",
"model": "asr",
"stream": "audio_1",
"started": true,
"message": "successfully started",
"error": null
}
]
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| jobs | [StartStatus] | true | Start status for each job in the request |
StartStatus
{
"job_id": "1234",
"model": "asr",
"stream": "audio_1",
"started": true,
"message": "successfully started",
"error": null
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| job_id | string | true | Job id |
| model | string | true | Model name |
| stream | string | true | Stream name |
| started | boolean | true | Did the job start yes or no |
| message | string | true | Additional information or words of positive affirmation |
| error | string|null | false | Error message if the job failed |
StatusResponse
{
"jobs": [
{
"qid": "iq__3Bs4xdLS9obhmQVWHNJvJ457ZL2X",
"job_id": "efd8e379-9256-40bc-9aa6-1fab74234f85",
"status": "running",
"model": "asr",
"stream": "video",
"created_at": "2026-03-25T03:33:38.746127",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"tenant": "iten2fY3bSh8Q7zY1t6vGZ8mUNFLHAWM",
"user": "0x9d7186b18ecbb5751719795415e9b8146e1bed2b",
"title": "Casablanca",
"error": null,
"progress": 0.56,
"tagging_progress": "120/214",
"tag_details": {
"tag_status": "Fetching content",
"time_running": 70.05,
"progress": 0.56,
"tagging_progress": "120/214",
"total_parts": 214,
"downloaded_parts": 150,
"tagged_parts": 120,
"warnings": {
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
}
}
],
"meta": {
"total": 8,
"start": 0,
"limit": null,
"count": 8
}
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| jobs | [JobStatus] | true | Individual job statuses |
| meta | PaginationMeta | true | Pagination metadata for list responses. |
JobStatus
{
"qid": "iq__3Bs4xdLS9obhmQVWHNJvJ457ZL2X",
"job_id": "efd8e379-9256-40bc-9aa6-1fab74234f85",
"status": "running",
"model": "asr",
"stream": "video",
"created_at": "2026-03-25T03:33:38.746127",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"tenant": "iten2fY3bSh8Q7zY1t6vGZ8mUNFLHAWM",
"user": "0x9d7186b18ecbb5751719795415e9b8146e1bed2b",
"title": "Casablanca",
"error": null,
"progress": 0.56,
"tagging_progress": "120/214",
"tag_details": {
"tag_status": "Fetching content",
"time_running": 70.05,
"progress": 0.56,
"tagging_progress": "120/214",
"total_parts": 214,
"downloaded_parts": 150,
"tagged_parts": 120,
"warnings": {
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
}
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| qid | string | true | Content object id that is being tagged |
| job_id | string | true | Job id |
| status | string | true | Current state of the job |
| model | string | true | Name of model |
| stream | string | true | Stream name |
| created_at | string(date-time) | true | ISO 8601 timestamp of when the job was created |
| params | TagArgs | true | Parameters that were used to run the tagging job. |
| tenant | string | true | Tenant identifier |
| user | string | true | Address of the user who submitted the job |
| title | string | true | Title of the content being tagged |
| error | string|null | false | Error message if the job failed or was cancelled |
| progress | number(float) | true | Overall job progress as a fraction (0.0 – 1.0) |
| tagging_progress | string | false | Deprecated: ratio of tagged_parts to total_parts. Use progress instead. |
| tag_details | TagDetails|null | false | Detailed progress information for the tagging job. Null if the job is still on the queue. |
Enumerated Values
| Property | Value |
|---|---|
| status | queued |
| status | running |
| status | cancelled |
| status | failed |
| status | succeeded |
TagDetails
{
"tag_status": "Fetching content",
"time_running": 70.05,
"progress": 0.56,
"tagging_progress": "120/214",
"total_parts": 214,
"downloaded_parts": 150,
"tagged_parts": 120,
"warnings": {
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
}
Detailed progress information for the tagging job.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| tag_status | string | true | Human-readable description of what the job is currently doing |
| time_running | number | true | How long the job has been running (in seconds) |
| progress | number(float) | true | Overall job progress as a fraction (0.0 – 1.0) |
| tagging_progress | string | true | Ratio of tagged parts to total parts (deprecated) |
| total_parts | integer | true | Total number of parts in scope for the tag request |
| downloaded_parts | integer | true | Number of parts that have been downloaded |
| tagged_parts | integer | true | Number of parts that have been tagged |
| warnings | TagWarnings|null | false | Warning summary, or null if there are no warnings |
TagWarnings
{
"num_warnings": 25,
"last_warning": "Failed to download part hqpe2EChvsWa6KNqFBqzn5yit7Z8NFLZ6DdxbcykW673Musy6JL4Vj"
}
Summary of warnings encountered during tagging.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| num_warnings | integer | true | Total number of warnings |
| last_warning | string | true | Most recent warning message |
PaginationMeta
{
"total": 8,
"start": 0,
"limit": null,
"count": 8
}
Pagination metadata for list responses.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| total | integer | true | Total number of matching items |
| start | integer | true | Offset of the first item returned |
| limit | integer|null | false | Maximum number of items requested, or null for no limit |
| count | integer | true | Number of items returned in this response |
ModelsResponse
{
"models": [
{
"name": "celeb",
"description": "Celebrity Identification",
"type": "frame",
"tag_tracks": [
{
"name": "celebrity_detection",
"label": "Celebrity Detection"
}
]
}
]
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| models | [ModelSpec] | true | List of available models |
ModelSpec
{
"name": "celeb",
"description": "Celebrity Identification",
"type": "frame",
"tag_tracks": [
{
"name": "celebrity_detection",
"label": "Celebrity Detection"
}
]
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | true | Model identifier |
| description | string | false | Human readable description of what the model does |
| type | string | true | Model type |
| tag_tracks | [TrackInfo] | true | Tag tracks this model writes to |
TrackInfo
{
"name": "celebrity_detection",
"label": "Celebrity Detection"
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | true | Track name as stored in the tag store |
| label | string | true | Human-readable label for the track |
StopTaggingResponse
{
"jobs": [
{
"job_id": "1234",
"message": "string"
}
],
"message": "string"
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| jobs | [StopStatus] | true | Stop statuses of individual jobs |
| message | string | true | Top level message |
StopStatus
{
"job_id": "1234",
"message": "string"
}
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| job_id | string | true | Job ID |
| message | string | true | Message |
ContentStatusResponse
{
"models": [
{
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"percent_completion": 0.85
},
{
"model": "asr",
"track": "speech_to_text",
"last_run": "2026-02-24T12:00:00Z",
"percent_completion": 1
}
]
}
Summary of tagging status across all models for a content object.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| models | [ContentModelStatusSummary] | false | List of per-model status summaries |
ContentModelStatusSummary
{
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"percent_completion": 0.85
}
High-level tagging status for one model on the content.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| model | string | false | Model identifier |
| track | string | false | Track the model writes its tags to |
| last_run | string | false | ISO 8601 timestamp of the most recent job run |
| percent_completion | number(float) | false | Fraction of content parts that have been tagged (0.0 – 1.0) |
ModelStatusResponse
{
"summary": {
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"tagging_progress": 0.85,
"num_content_parts": 120
},
"jobs": [
{
"time_ran": "1h 0m 0s",
"source_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"job_status": {
"status": "Completed",
"time_ran": "1h 0m 0s"
},
"upload_status": {
"num_job_parts": 60,
"num_tagged_parts": 60
}
}
]
}
Detailed status for a single model on a content object.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| summary | ModelStatusSummary | false | Aggregate summary for a model's tagging progress on a content object. |
| jobs | [JobDetail] | false | Chronological list of every job that has been run for this model |
ModelStatusSummary
{
"model": "celeb",
"track": "celebrity_detection",
"last_run": "2026-02-25T18:30:00Z",
"tagging_progress": 0.85,
"num_content_parts": 120
}
Aggregate summary for a model's tagging progress on a content object.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| model | string | false | Model identifier |
| track | string | false | Track the model writes its tags to |
| last_run | string | false | ISO 8601 timestamp of the most recent job run |
| tagging_progress | number(float) | false | Fraction of content parts that have been tagged (0.0 – 1.0) |
| num_content_parts | integer | false | Total number of parts in the content |
JobDetail
{
"time_ran": "1h 0m 0s",
"source_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"params": {
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
},
"job_status": {
"status": "Completed",
"time_ran": "1h 0m 0s"
},
"upload_status": {
"num_job_parts": 60,
"num_tagged_parts": 60
}
}
Details of a single tagging job run.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| time_ran | string | false | Duration that the job ran before stopping |
| source_qid | string | false | Content object id that was tagged |
| params | TagArgs | false | Parameters that were used to run the tagging job. |
| job_status | JobRunStatus | false | Status of a completed job run. |
| upload_status | JobUploadStatusSummary|null | false | Upload progress for this job. Null if the job did not reach the upload phase. |
TagArgs
{
"feature": "celeb",
"run_config": {
"fps": 2
},
"scope": {
"start_time": 0,
"end_time": 300
},
"replace": false,
"destination_qid": "iq__3C58dDYxsn5KKSWGYrfYr44ykJRm",
"max_fetch_retries": 3
}
Parameters that were used to run the tagging job.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| feature | string | false | Model identifier |
| run_config | object | false | Arbitrary runtime parameters passed to the model container |
| scope | object | false | Scope of the tagging job with respect to the content (e.g. time range or asset list) |
| replace | boolean | false | Whether already-tagged parts were retagged |
| destination_qid | string | false | Content object id that tags were written to |
| max_fetch_retries | integer | false | Maximum number of fetch retries that were allowed |
JobRunStatus
{
"status": "Completed",
"time_ran": "1h 0m 0s"
}
Status of a completed job run.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | false | Final status of the job |
| time_ran | string | false | Duration the job ran before stopping |
JobUploadStatusSummary
{
"num_job_parts": 60,
"num_tagged_parts": 60
}
Summary of how many parts were uploaded for a job.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
| num_job_parts | integer | false | Total number of parts in the job |
| num_tagged_parts | integer | false | Number of parts that were successfully tagged and uploaded |