Introduction
Welcome to the Unleash live API suite, where innovation meets efficiency!
Media Drive API: The Media Drive API unlocks the power of your Unleash live account's media storage and allows you to upload, manage, and retrieve media assets.
Mission API: The Mission API provides you with a comprehensive set of tools to streamline mission planning and execution. Using this API, you can programmatically list, upload and download the smart inspect or waypoint missions, allowing you to automate and optimize your unmanned aerial vehicle (UAV) operations.
Flight Logs API: With the Flight Logs API, you can access the flight data captured by your UAVs through Unleash live. Retrieve detailed flight logs, including telemetry, sensor readings, and performance metrics. Integrate your flight management system (eg AVCRM) to easily comply with regulatory requirements around tracking flight logs.
Analytics API: The Analytics API opens up a world of A.I. generated analytics data derived from your Unleash live account. Empower your in-house platforms with data-driven decision-making capabilities.
Annotation API: The Annotation API provides access to AI-generated annotations related to inspections. These annotations detail various detected features such as cracks, corrosion, or other anomalies, including their severity, location, and additional metadata. By connecting to this endpoint, users can retrieve detailed information about each annotation to assist in decision-making and further analysis.
Unleash CLI: Unleash Command Line Interface (CLI) is an easy way to deploy the models into production. Users need to prepare their model files in a folder and upload them to their account using their command line. We encourage you to explore and try our samples to use your Unleash live API. To access our samples, simply visit Samples API Github repository.
API Documentation
Version: 2.0.0
Authentication
HTTP
API request required authentication header with JWT token being received from AWS COGNITO service. You will need a user login and user password to send such request. We recommend to use aws sdk library as a handy helper. List of official AWS SDK in multiple programing language
We have prepared example code which shows authorization flow written in node.js
Basic node.js configuration required to run below script:
{
"name": "unleash-live-api",
"dependencies": {
"amazon-cognito-identity-js": "^6.1.2",
"aws-sdk": "^2.1336.0",
"graphql-request": "^5.2.0",
"jwt-decode": "^3.1.2"
}
}
exampleConfig.js
export const API_URL_DEFAULT = "api.unleashlive.com";
export const FLIGHTS_CDN_DEFAULT = "https://flights.unleashlive.com";
export const USER_NAME = 'test@user-name.com';
export const PASSWORD = 'test-password';
export const GRAPHQL_ENDPOINT = 'https://mediadrive-api.unleashlive.com/graphql';
export const FOLDER_ID = 'test-folder-id';
export const UPLOAD_BUCKET_NAME = 'library-upload-syd-cloud';
export const MEDIA_DRIVE_BUCKET_NAME = 'library-syd-cloud';
export const ACCOUNT_ID = '590171865298';
"test@user-name.com": The same login email that is used to login in cloud.unleashlive.com.
"test-pass": Password to the above login email.
cognito.js
import AmazonCognitoIdentity from "amazon-cognito-identity-js";
import jwt_decode from "jwt-decode";
import AWS from "aws-sdk";
import {ACCOUNT_ID} from "../examples/exampleConfig.js";
const REGION = 'ap-southeast-2';
const IDENTITY_POOL_ID = 'ap-southeast-2:359c9d8b-02e4-457f-b185-4f3ff3f639d7';
const POOL_DATA = {
UserPoolId: 'ap-southeast-2_UnpJmDeN5',
ClientId: '7jhe1lfkb5pvhbkicc3d14m0ej'
};
export function initClient(idToken) {
AWS.config.region = REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
AccountId: ACCOUNT_ID,
IdentityPoolId: IDENTITY_POOL_ID,
Logins: {
[`cognito-idp.${REGION}.amazonaws.com/${POOL_DATA.UserPoolId}`]: idToken
},
});
}
export function getUserPool() {
return new AmazonCognitoIdentity.CognitoUserPool(POOL_DATA);
}
export function getCognitoUser(email) {
const userData = {
Username: email,
Pool: getUserPool()
};
return new AmazonCognitoIdentity.CognitoUser(userData);
}
export function decodeJWTToken(token) {
const {email, exp, auth_time, token_use, sub} = jwt_decode(token.idToken);
return {token, email, exp, uid: sub, auth_time, token_use};
}
export function getAuthDetails(email, password) {
const authenticationData = {
Username: email,
Password: password,
};
return new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
}
export function getCredentials() {
return new AWS.CognitoIdentityCredentials({
AccountId: ACCOUNT_ID,
IdentityPoolId: AWS.config.credentials.params.IdentityPoolId,
Logins: AWS.config.credentials.params.Logins,
});
}
action.js, general scripts used before any action
import {initClient, decodeJWTToken, getAuthDetails, getCognitoUser} from "./cognito.js";
export function signIn(email, password) {
return new Promise((resolve) => {
getCognitoUser(email).authenticateUser(getAuthDetails(email, password), {
onSuccess: (result) => {
const jwtTokenPayload = result.getIdToken().decodePayload();
const token = {
accessToken: result.getAccessToken().getJwtToken(),
idToken: result.getIdToken().getJwtToken(),
refreshToken: result.getRefreshToken().getToken(),
identityId: jwtTokenPayload['custom:identityId'],
companyId: jwtTokenPayload['custom:companyId'],
teamId: jwtTokenPayload['custom:teamId'],
}
initClient(token.idToken);
return resolve({statusCode: 200, response: decodeJWTToken(token)});
},
onFailure: (err) => {
return resolve({statusCode: 400, response: err.message || JSON.stringify(err)});
},
});
});
}
exampleSignIn.js
import {signIn} from "../src/actions.js";
signIn(USER_NAME, PASSWORD)
.then(async (response) => {
// Perform media drive actions
})
.catch(e => {
console.error(e);
});
Every graphQL request should be sent with obligatory header authorization
.
Every REST request should be sent with obligatory header X-Amz-Cognito-Security-Token
.
Quick Hint:
If you are using other programming language, you can use the following command in your terminal to generate Security token:
aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --region ap-southeast-2 --client-id 7jhe1lfkb5pvhbkicc3d14m0ej --auth-parameters USERNAME=<USER_LOGIN_EMAIL>,PASSWORD=<PASSWORD>
API KEY
This authentication method is mainly used to fetch analytics data generated during your AI sessions. Please contact here or your Account Manager to sort out API keys for you. Further, you can also email us at support@unleashlive.com.
Media Drive
Pre-requisites
- node 19.x
- Valid Account in cloud.unleashlive.com Cloud.unleashlive.com
Operation Types
Media drive api is build with support of GraphQL. It allows to perform few types of operations:
Name | Description |
---|---|
Mutation |
Create, Update, Delete media drive item |
Query |
Get , List existing items |
Data Types
Media Drive item
Name | Type | Constraints | Description |
---|---|---|---|
id |
String | optional | Item Id |
teamId |
String | optional | Item teamId resource belongs to |
parentId |
String | optional | Parent item Id. (In most cases it represents folder id) |
tags |
String | optional | String which represent assigned tags to the item |
type |
Enum | optional | Enum of custom types |
location |
String | optional | Representation of hierarchy where item is placed. Each Id is seperated by "#" |
deviceId |
String | optional | Id of device which was used to create an Item (if any) |
name |
String | optional | The name of an item |
createdAt |
String | optional | UTC Timestamp of item creation |
updatedAt |
String | optional | UTC Timestamp of item last update |
ownerId |
String | optional | Id of an author user |
s3Path |
String | optional | Physical location of a file assigned with an item |
metadata |
Object | optional | File Metadata |
mimeType |
String | optional | Any available mime type plus custom types |
annotations |
String | optional | Stringify Annotations object |
Media Drive Metadata
Name | Type | Constraints | Description |
---|---|---|---|
size |
Number | Optional | ... |
childItemsNumber |
Int | Optional | ... |
addonId |
String | Optional | ... |
deviceId |
String | Optional | ... |
annotationCount |
Int | Optional | ... |
make |
String | Optional | ... |
model |
String | Optional | ... |
orientation |
Int | Optional | ... |
software |
String | Optional | ... |
camaperturevalue |
Float | Optional | ... |
camfnumber |
Float | Optional | ... |
camfocallength |
Float | Optional | ... |
camfocallengthin35mmformat |
Int | Optional | ... |
camiso |
Int | Optional | ... |
gpsalt |
Float | Optional | ... |
gpsaltref |
Int | Optional | ... |
gpslat |
Float | Optional | ... |
gpslatref |
String | Optional | ... |
gpslng |
Float | Optional | ... |
gpslngref |
String | Optional | ... |
baseAltitude |
Float | Optional | ... |
exifimagewidth |
Int | Optional | ... |
exifimageheight |
Int | Optional | ... |
gimbalpitchdegree |
Float | Optional | ... |
automationid |
String | Optional | ... |
createdate |
AWSTimestamp | Optional | ... |
modifydate |
AWSTimestamp | Optional | ... |
lastmodified |
AWSTimestamp | Optional | ... |
type |
String | Optional | ... |
width |
Int | Optional | ... |
height |
Int | Optional | ... |
bounds |
[[Float]] | Optional | ... |
oldpath |
String | Optional | ... |
oldPath |
String | Optional | ... |
is360 |
Boolean | Optional | ... |
duration |
Float | Optional | ... |
isPanoramic |
Boolean | Optional | ... |
Media Drive Custom MimeType possible values
Name | Description |
---|---|
application/vnd.unleashlive.folder |
Media drive item representing folder |
application/vnd.unleashlive.model |
Media drive item representing model wrapper |
application/vnd.unleashlive.model.2d |
Media drive item representing 2D model |
application/vnd.unleashlive.model.3d |
Media drive item representing 3D model |
application/vnd.unleashlive.model.vr |
Media drive item representing VR model |
application/vnd.unleashlive.model.pc |
Media drive item representing Point Cloud model |
Media Drive item.type possible values
Key | Value |
---|---|
I |
Image |
V |
Video |
M |
Model |
R |
Report |
FL |
Flight log |
D |
General document |
U |
Undefined type |
Media Drive Annotations Object type
Key | Value |
---|---|
{addonId} |
Annotation |
Media Drive Annotation Object type
Key | Type | Constrains |
---|---|---|
addonId |
String | Required |
labels |
Image labels map | Optional |
sessionInfo |
Sessions info | Optional |
Media Drive ImageLabelsMap type
Key | Value |
---|---|
{id} |
SingleLabel |
Media Drive SessionsInfo type
Name | Type | Constraints | Description |
---|---|---|---|
title |
String | Optional | ... |
value |
String or String[] | Required | ... |
order |
String | Optional | ... |
placeholder |
String | Optional | ... |
Media Drive SingleLabel type
Key | Type | Constrains |
---|---|---|
shapeType |
Shape types | Required |
category |
String | Required |
severity |
Number | Optional |
comment |
String | Optional |
color |
String | Optional |
updatedAt |
UTC Timestamp | Required |
bbox |
Number[] | Optional |
area |
Number | Optional |
distance |
Number | Optional |
isAI |
Boolean | Optional |
isAccepted |
Boolean | Optional |
isModified |
Boolean | Optional |
Media Drive ShapeTypes enum
Key | Value |
---|---|
Polygon |
POLYGON |
Rectangle |
RECTANGLE |
Point |
POINT |
Authenticate requests
Each request has to be authenticated with a valid JWT token. The token is passed in the authorization
header.
To learn on how to get JWT token go to
Get media
Example get query:
query GetLibraryItem {
get(
item: {id: "ItemId1"}
) {
teamId
location
type
tags
createdAt
deviceId
id
name
parentId
s3Path
updatedAt
mimeType
annotations
metadata {
addonId
camaperturevalue
camfnumber
camfocallength
camfocallengthin35mmformat
camiso
childItemsNumber
exifimageheight
exifimagewidth
gpsalt
gpslat
gpslatref
gpslng
gpslngref
height
isPanoramic
lastmodified
make
model
orientation
size
software
type
width
}
}
}
exampleGet.js
import * as graphQlRequest from 'graphql-request'
import {signIn} from "../src/actions.js";
import {FOLDER_ID, GRAPHQL_ENDPOINT, PASSWORD, USER_NAME} from "./exampleConfig.js";
const GraphQLClient = graphQlRequest.GraphQLClient;
const gql = graphQlRequest.gql;
export function getFolderItem(signInResponse, id) {
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const getQuery = gql`
query GetLibraryItem{
get(item: {id: "${id}"}) {
id,
location
}
}`
return graphQLClient.request(getQuery);
}
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const folderItem = (await getFolderItem(signInResponse,FOLDER_ID)).get;
console.log(folderItem);
})
.catch(e => {
console.error(e);
});
Example get response:
{
"data": {
"get": {
"teamId": "teamId1",
"location": "teamId1",
"type": "F",
"tags": "aiResultsNum:1",
"createdAt": 1678802206809,
"deviceId": null,
"id": "ItemId1",
"name": "Sample folder",
"parentId": "teamId1",
"s3Path": "12345/78910.mp4",
"updatedAt": 1678976523362,
"mimeType": "application/vnd.unleashlive.folder",
"annotations": null,
"metadata": {
"addonId": null,
"camaperturevalue": null,
"camfnumber": null,
"camfocallength": null,
"camfocallengthin35mmformat": null,
"camiso": null,
"childItemsNumber": 13,
"exifimageheight": null,
"exifimagewidth": null,
"gpsalt": null,
"gpslat": null,
"gpslatref": null,
"gpslng": null,
"gpslngref": null,
"height": null,
"isPanoramic": null,
"lastmodified": null,
"make": null,
"model": null,
"orientation": null,
"size": 0,
"software": null,
"type": null,
"width": null,
},
}
}
}
Operation type: Query. Used to fetch full object by known itemId
.
Query input parameters
Key | Type | Description | Constrain |
---|---|---|---|
item |
{id: String} | Object with selected item's Id | Required |
Query output type
List media
Example list query:
query list {
list(
sort: desc
location: "teamId1/folderId1"
limit: 48
) {
items {
teamId
location
type
tags
createdAt
deviceId
id
name
parentId
s3Path
updatedAt
mimeType
metadata {
isPanoramic
duration
}
}
nextToken {
pk
sk
locationCreatedAt
teamId
teamIdType
createdAt
searchNameCreatedAt
searchName
deviceId
type
}
}
}
exampleList.js
import {signIn} from "../src/actions.js";
import {FOLDER_ID, GRAPHQL_ENDPOINT, PASSWORD, USER_NAME} from "./exampleConfig.js";
import * as graphQlRequest from "graphql-request";
import {getFolderItem} from "./exampleGet.js";
const GraphQLClient = graphQlRequest.GraphQLClient;
const gql = graphQlRequest.gql;
export function listItems(signInResponse, location) {
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const listQuery = gql`
query list {
list(
sort: desc
location: "${location}"
limit: 2
) {
items {
teamId
location
type
tags
createdAt
deviceId
id
name
parentId
s3Path
updatedAt
mimeType
metadata {
isPanoramic
duration
}
},
nextToken {
pk
sk
locationCreatedAt
teamId
teamIdType
createdAt
searchNameCreatedAt
searchName
deviceId
type
}
}
}`
return graphQLClient.request(listQuery);
}
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const folderItem = (await getFolderItem(signInResponse, FOLDER_ID)).get;
const location = [folderItem.location, folderItem.id].join("/");
const listResponse = await listItems(signInResponse, location);
console.log(listResponse);
})
.catch(e => {
console.error(e);
});
Example graphql list response:
{
"data": {
"list": {
"items": [
{
"teamId": "teamId1",
"location": "teamId1/folderId1",
"type": "D",
"tags": null,
"createdAt": 1678976522491,
"deviceId": "deviceId1",
"id": "1",
"name": "testDocument.json",
"parentId": "folderId1",
"s3Path": "1234/2b0d6d59-d221-4dc1-9cf4-78677a002127.json",
"updatedAt": 1678976539957,
"mimeType": "application/json",
"metadata": {
"isPanoramic": null,
"duration": null,
},
},
{
"teamId": "teamId1",
"location": "teamId1/folderId1",
"type": "V",
"tags": null,
"createdAt": 1678976459317,
"deviceId": "deviceId1",
"id": "2",
"name": "testClip.mp4",
"parentId": "folderId1",
"s3Path": "1234/2453702b-8764-4f55-bd81-487f58ec556a.mp4",
"updatedAt": 1678976491797,
"mimeType": "video/mp4",
"metadata": {
"isPanoramic": null,
"duration": 1202.003,
},
},
{
"teamId": "teamId1",
"location": "teamId1/folderId1",
"type": "F",
"tags": "aiResultsNum:1",
"createdAt": 1678124970355,
"deviceId": "deviceId1",
"id": "3",
"name": "Test folder",
"parentId": "folderId1",
"s3Path": "<path-of-file>",
"updatedAt": 1678976549956,
"mimeType": "application/vnd.unleashlive.folder",
"metadata": {
"isPanoramic": null,
"duration": null,
},
},
{
"teamId": "teamId1",
"location": "teamId1/folderId1",
"type": "I",
"tags": "MTY2MDg0NzMyNDMzOSNmYjcwNGIwMy02MjhhLTQyNDEtYmY5OC00NWNkNTFiN2MyNzc#MTY1ODc1NzkwNTUzOSM0OGUxZThiNi0zODA0LTRkMTQtYTJkYi0yOGY1ZmM4ZjUyMmM#aiResultsNum:1",
"createdAt": 1524474282000,
"deviceId": "deviceId1",
"id": "4",
"name": "DJI_0590.JPG",
"parentId": "folderId1",
"s3Path": "1234/efd72fa2-11a8-4369-84c0-8a159d8d3189.jpg",
"updatedAt": 1678907063236,
"mimeType": "image/jpeg",
"metadata": {
"isPanoramic": null,
"duration": null,
},
}
],
"nextToken": null,
}
}
}
List operation is a Query type operation. It should be used to fetch all subitems of known parentId
. This variable
can be fetched by:
- knowing a
teamId
for which items should be listed - knowing a
folderId
for which items should be listed
Move media
Example move mutation:
mutation MoveItems {
move(
moveItems: [{id: "itemId1"}]
to: {id: "itemId11"}
) {
id
parentId
location
}
}
exampleMove.js
import * as graphQlRequest from 'graphql-request'
import {signIn} from "../src/actions.js";
import {FOLDER_ID, GRAPHQL_ENDPOINT, PASSWORD, USER_NAME} from "./exampleConfig.js";
import {getFolderItem} from "./exampleGet.js";
const GraphQLClient = graphQlRequest.GraphQLClient;
const gql = graphQlRequest.gql;
export function moveItem(signInResponse, id, toId) {
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const moveQuery = gql`
mutation MoveItems {
move(
moveItems: [{id: "${id}"}]
to: {id: "${toId}"}
) {
id
parentId
location
}
}
`
return graphQLClient.request(moveQuery);
}
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const moveResponse = await moveItem(signInResponse, FOLDER_ID, 'itemId11');
console.log(moveResponse);
const folderItem = (await getFolderItem(signInResponse, FOLDER_ID)).get;
console.log(folderItem);
})
.catch(e => {
console.error(e);
});
Example move response:
{
"data": {
"move": [
{
"id": "itemId1",
"parentId": "itemId11",
"location": "teamId1/itemId11",
}
]
}
}
Action will move list of selected items along with it's all sub items to destination item.
Move mutation, input parameters
Key | Type | Description | Constrain |
---|---|---|---|
moveItems |
{id: String}[] | List of objets with selected item's Id | Required |
to |
{id: String} | Destination object | Required |
Rename media
Example rename request:
mutation RenameItems {
rename(
item: {id: "itemId1"}
newName: "New name"
) {
id
}
}
exampleRename.js
import * as graphQlRequest from 'graphql-request'
import {signIn} from "../src/actions.js";
import {FOLDER_ID, GRAPHQL_ENDPOINT, PASSWORD, USER_NAME} from "./exampleConfig.js";
import {getFolderItem} from "./exampleGet.js";
const GraphQLClient = graphQlRequest.GraphQLClient;
const gql = graphQlRequest.gql;
export function renameItem(signInResponse, id) {
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const renameQuery = gql`
mutation RenameItems {
rename(
item: {id: "${id}"}
newName: "New name"
) {
id
}
}
`
return graphQLClient.request(renameQuery);
}
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const renameResponse = await renameItem(signInResponse, FOLDER_ID);
console.log(renameResponse);
const folderItem = (await getFolderItem(signInResponse, FOLDER_ID)).get;
console.log(folderItem);
})
.catch(e => {
console.error(e);
});
Example rename response:
{
"data": {
"rename": {
"id": "itemId1",
}
}
}
Action will rename selected item
Rename mutation, input parameters
Key | Type | Description | Constrain |
---|---|---|---|
item |
{id: String} | Object with selected item's Id | Required |
newName |
String | New name which will be stored | Required |
Upload media
exampleUpload.js
import AWS from 'aws-sdk';
import {signIn} from "../src/actions.js";
import {FOLDER_ID, PASSWORD, UPLOAD_BUCKET_NAME, USER_NAME} from "./exampleConfig.js";
import * as uuid from "uuid";
import * as fs from "fs";
import {getCredentials} from "../src/cognito.js";
import {getFolderItem} from "./exampleGet.js";
const FILE_NAME = 'logo.png';
const FILE_PATH = `./assets/${FILE_NAME}`;
function getFileKey(companyId, teamId, identityId, fileName) {
// return [companyId, teamId, identityId, uuid.v4(), fileName].join('/')
return [identityId, uuid.v4(), fileName].join('/')
}
signIn(USER_NAME, PASSWORD)
.then(async (response) => {
const companyId = response.response.token.companyId;
const teamId = response.response.token.teamId;
const identityId = response.response.token.identityId;
const folderItem = (await getFolderItem(FOLDER_ID)).get;
const parentId = folderItem.id;
const location = [folderItem.location, folderItem.id].join("/");
// Upload file to it's destination
fs.readFile(FILE_PATH, (err, data) => {
if (err) throw err;
const s3Client = new AWS.S3({
credentials: getCredentials(),
params: {Bucket: UPLOAD_BUCKET_NAME}
});
const params = {
Bucket: UPLOAD_BUCKET_NAME, // pass your bucket name
Key: getFileKey(companyId, teamId, identityId, FILE_NAME),
Body: data,
Metadata: {
location: location,
parentId: parentId,
name: FILE_NAME,
}
};
s3Client.upload(params, function(s3Err, data) {
if (s3Err) throw s3Err
console.log(`File uploaded successfully at ${data.Location}`)
});
});
})
.catch(e => {
console.error(e);
});
We recommend using AWS SDK lib to perform upload.
Metadata which can be passed with a file
Key | Description | Constrain | Example value | |
---|---|---|---|---|
deviceid | Device which will be assign with item | Optional | deviceId1 | |
location | Location to which file will be uploaded | Optional | teamId1/itemId11 | |
name | Name which will be assign to a media drive item | Optional | New name | |
parentId | Parent to which file will be uploaded | Optional | itemId11 (Deprecated) |
Download media
exampleDownload.js
import { signIn } from "../../auth/src/actions.js";
import {
FOLDER_ID,
MEDIA_DRIVE_CDN,
PASSWORD,
USER_NAME,
} from "../../config/variables.js";
import { listItemsImages } from "./list.js";
import { getFolderItem } from "./get.js";
import * as https from "https";
import * as fs from "fs";
import {download} from "../../common/downloadFile.js";
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const folderItem = (await getFolderItem(signInResponse, FOLDER_ID)).get;
const location = [folderItem.location, folderItem.id].join("/");
const listResponse = (await listItemsImages(signInResponse, location)).list
.items;
const imageItem = listResponse.find((item) => item.type === "I");
return download(MEDIA_DRIVE_CDN, imageItem.s3Path, imageItem.name);
})
.catch((e) => {
console.error(e);
});
Example script presents how to download file from library. Example flow does below steps:
- Sign-in with username and password
- Get folder by known ID (not required step if we have id and file)
- List folder items (only needed if we want to first search for a files)
- Select very first image from fetched list (only for example purpose)
- Download an image and save it to local machine
fs.writeFileSync(imageItem.name, imgBuffer);
Delete media
Example delete mutation:
mutation DeleteItems {
delete(
deleteItems: [{id: "itemId1"}, {id: "itemId2"}]
) {
deleteItems {
id
}
ownerId
}
}
exampleDelete.js
import * as graphQlRequest from 'graphql-request'
import {signIn} from "../src/actions.js";
import {GRAPHQL_ENDPOINT, PASSWORD, USER_NAME} from "./exampleConfig.js";
const GraphQLClient = graphQlRequest.GraphQLClient;
const gql = graphQlRequest.gql;
export function deleteItem(signInResponse) {
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const deleteQuery = gql`
mutation DeleteItems {
delete(
deleteItems: [{id: "itemId1"}, {id: "itemId2"}]
) {
deleteItems {
id
}
ownerId
}
}
`
return graphQLClient.request(deleteQuery);
}
signIn(USER_NAME, PASSWORD)
.then(async (signInResponse) => {
const deleteResponse = (await deleteItem(signInResponse))
console.log(deleteResponse);
const getQuery = gql`
query GetLibraryItem{
get(item: {id: "itemId1"}) {
id,
name
}
}`
const graphQLClient = new GraphQLClient(GRAPHQL_ENDPOINT, {
headers: {
authorization: signInResponse.response.token.idToken,
},
})
const getResponse = await graphQLClient.request(getQuery);
console.log(getResponse);
})
.catch(e => {
console.error(e);
});
Example delete response:
{
"data": {
"delete": {
"deleteItems": [
{
"id": "itemId1"
}, {
"id": "itemId2"
}
],
"ownerId": "userId1",
}
}
}
Action will remove list of selected items along with it's all subitems.
Delete mutation, input parameters
Key | Type | Description | Constrain |
---|---|---|---|
deleteItems |
{id: String}[] | List of objets with selected item's Id | Required |
Flight Logs
List logs
List logs is basic REST endpoint
GET: /v1/flights
Query Parameters:
dateFrom
(optional): Returns flight logs from the specified timestamp, including that timestamp.
dateTo
(optional): Returns flight logs up to the specified timestamp, including that timestamp.
For instance:
https://api.unleashlive.com/v1/flights?dateFrom=1709654015526
returns everything from particular timestamp including that timestamp
https://api.unleashlive.com/v1/flights?dateTo=1709654015526
returns everything to particular timestamp including that timestamp
https://api.unleashlive.com/v1/flights?dateFrom=1709654015525&dateTo=1709654015528
returns everything in between those 2 timestamps
The timestamp needs to be in UNIX timestamp format, in milliseconds.
flights/examples/list.js
You can either use programming language of your choice or you can try the endpoint with simple CURL.
export async function listFlightLogs(signInResponse) {
const requestOptions = {
hostname: API_URL,
port: 443,
path: '/v1/flights',
method: 'GET',
headers: {
'content-type': 'application/json',
'x-amz-cognito-security-token': signInResponse.response.token.idToken
},
};
return await sendGet(requestOptions);
}
Download log
In order to download a file you need to know its path and a FLIGHTS_CDN which is: https://flights.unleashlive.com
To store a file locally with the same name which is presented on unleash live platform use name = flightLog.name
.
import https from "https";
import fs from "fs";
export function download(cdn, filePath, name) {
const file = fs.createWriteStream(name);
return https.get(
[cdn, filePath].join("/"),
function (response) {
response.pipe(file);
// after download completed close filestream
file.on("finish", () => {
file.close();
console.log("Download Completed");
});
}
);
}
function getFileNameFromPath(filePath) {
const filePathParts = filePath.split('/');
return filePathParts[filePathParts.length - 1];
}
try {
const signInResponse = await signIn(USER_NAME, PASSWORD);
const flightLogs = await listFlightLogs(signInResponse);
const firstItem = flightLogs[0];
const localFileName = getFileNameFromPath(firstItem.s3Path);
await download(FLIGHTS_CDN, firstItem.s3Path, localFileName);
} catch (e) {
console.error(e);
}
Missions
Upload mission
Uploading mission is a basic post request to below endpoint
POST: /v1/mission
mission/examples/upload.js
export async function uploadMission(signInResponse) {
const requestOptions = {
hostname: API_URL,
port: 443,
path: '/v1/mission',
method: 'POST',
headers: {
'content-type': 'application/json',
'x-amz-cognito-security-token': signInResponse.response.token.idToken
},
};
return await sendPost(requestOptions, BODY);
}
try {
const signInResponse = await signIn(USER_NAME, PASSWORD);
const uploadResponse = await uploadMission(signInResponse);
console.log(uploadResponse);
} catch (e) {
console.error(e);
}
Analytics
Description
This API exposes Unleash live read-only endpoints, allowing developers and users to retrieve AI-generated analytics data.
API access is currently an optional addon, please contact your account manager to request a demo or for more information.
URL
The current analytics API can be found at:
https://api.unleashlive.com/v1
Parameters
All in-use parameters appear here, consult each endpoint for more information on what is required.
Headers
curl -X GET -H "x-api-key: <API-KEY>" <URL>
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', <ENDPOINT>, headers={'x-api-key': <API-KEY>})
r.data
Only one custom header is required to use the Analytics API - your individual customer API key.
Information about how to get api key API KEY
x-api-key: <API KEY>
Variables
Name | Type | Constraints | Description | Example |
---|---|---|---|---|
deviceId | string | required, uuid format | Unique Device ID | Wabcdb35be35bb72 |
unixUTCTimeStampFrom | integer | required, uuid format | Unix epoch, milliseconds | 1597630156000 |
unixUTCTimeStampTo | integer | required, uuid format | Unix epoch, milliseconds | 1597630156000 |
pageNumber | integer | required, uuid format | Page number | 0 |
Endpoints
All current valid endpoints.
Version
curl -X GET -H "x-api-key: <API-KEY>" https://api.unleashlive.com/v1/analytics/version
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/version', headers={'x-api-key': <API-KEY>})
r.data
{"1.0.1"}
Retrieve current API version number.
Returns version number in the format "1.0.1"
, and should be used for testing and confirmation of valid API key.
API Endpoint
GET /analytics/version
Devices
curl -X GET -H "x-api-key: <API-KEY>" https://api.unleashlive.com/v1/analytics/devices
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/devices', headers={'x-api-key': <API-KEY>})
r.data
["Wb8fabc31378ce07","W022abc5be35bb72","Weea288bc1faaddd"]
Returns a list of all valid devices for a given API Key and account in the format:
["Wabcdb35be35bb72", ...]
Where each item corresponds to an Unleash live Device ID.
API Endpoint
GET /analytics/devices
Sessions
curl -X GET -H "x-api-key: <API-KEY>" https://api.unleashlive.com/v1/analytics/sessions
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/sessions', headers={'x-api-key': <API-KEY>})
r.data
["1595418530512","1595452859625","1595492155987"]
Returns a list of all sessions for a given API Key and account in the format:
["1595418530512", ...]
Where each item corresponds to an Unleash live session ID.
API Endpoint
GET /analytics/sessions
Size Optimized Data
curl -X GET -H "x-api-key: <API-KEY>" https://api.unleashlive.com/v1/analytics/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}', headers={'x-api-key': <API-KEY>})
r.data
{"keys": ["class_name","count","device_id","frame_number","model_id","session_id","source_file_name","timestamp"],
"total_num_pages":1,
"data":[["person",1,"Wabcdb35be35bb72",110251,"starter-ai","1597622730877","Wabcdb35be35bb72?token=sneaky-firefox-288","2020-08-17T02:08:49.000Z"],
["person",3,"Wabcdb35be35bb72",110252,"starter-ai","1597622730878","Wabcdb35be35bb72?token=sneaky-firefox-288","2020-08-17T02:08:49.000Z"]]}
Retrieve raw analytics data generated between two given dates.
This endpoint is size-optimized - three fields are returned:
Field | Type | Description |
---|---|---|
keys | list (string) | A list of all keys used in the data field, in order of use. |
total_num_pages | integer | The number of pages available for the requested data. |
data | list (mixed) | List containing all requested data. |
API Endpoint
GET /analytics/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}
Tableau Formatted Data
curl -X GET -H "x-api-key: <API-KEY>" https://api.unleashlive.com/v1/analytics/tableau/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/tableau/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}', headers={'x-api-key': <API-KEY>})
r.data
{"total_num_pages":1,
"data":[{"timestamp":"2020-08-17T02:08:49.000Z","class_name":"person","count":1,"device_id":"Wabcdb35be35bb72","source_file_name":"Wabcdb35be35bb72?token=sneaky-firefox-288","frame_number":110251,"model_id":"starter-ai","session_id":"1597622730877"},
{"timestamp":"2020-08-17T02:08:49.000Z","class_name":"truck","count":1,"device_id":"Wabcdb35be35bb72","source_file_name":"Wabcdb35be35bb72?token=sneaky-firefox-288","frame_number":110252,"model_id":"starter-ai","session_id":"1597622730877"}]}
Retrieve tableau formatted analytics data generated between two given dates.
This endpoint is descriptive, allowing data to be read nativily by services such as Tableau and salesforce easily.
Field | Type | Description |
---|---|---|
total_num_pages | integer | The number of pages available for the requested data. |
data | list (mixed) | List containing all requested data. |
API Endpoint
GET /analytics/tableau/{deviceId}/{unixUTCTimeStampFrom}/{unixUTCTimeStampTo}/{pageNumber}
Annotations
Annotation Api Description
Annotation API allows you to access AI annotation data collected as part of inspections. This documentation describes the available endpoints, their parameters, and how to interact with them.
Annotation Api Authentication
To authorize, use this code:
curl "https://api.unleashlive.com/v1/inspections" \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
r = requests.get("https://api.unleashlive.com/v1/inspections", headers=headers)
Make sure to replace
YOUR_API_KEY
with your API key.
Unleash Live uses API keys to allow access to the API. You can obtain an API key from your account settings or by contacting Unleash Live support.
The API expects the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer YOUR_API_KEY
Get All Inspections
curl "https://api.unleashlive.com/v1/analytics/inspections" \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
url = "https://api.unleashlive.com/v1/analytics/inspections"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
response = requests.get(url, headers=headers)
print(response.json())
// Response example
[
{
"id": "inspection1",
"name": "Inspection 1",
"teamId": "team123",
"folderId": "folder456",
"createdAt": 1631026800,
"tasksCount": 5
},
{
"id": "inspection2",
"name": "Inspection 2",
"teamId": "team789",
"folderId": "folder123",
"createdAt": 1631113200,
"tasksCount": 3
}
]
This endpoint retrieves a list of all inspections available in the account.
GET https://api.unleashlive.com/v1/analytics/inspections
Get All Annotations
curl "https://api.unleashlive.com/v1/analytics/annotations" \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
url = "https://api.unleashlive.com/v1/analytics/annotations"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
response = requests.get(url, headers=headers)
print(response.json())
// Response example
[
{
"category": "crack",
"timestamp": 1234567890,
"distance": 2.5,
"area": 15,
"description": "Long crack near edge",
"severity": 3,
"assetId": "asset123",
"context": {
"hubHeightM": 80,
"turbineNo": "T01",
"bladeManufacturer": "BladesCo",
"siteName": "Wind Farm Alpha",
"powerRatingMW": 2.5,
"bladeLengthM": 50,
"bladeType": "Type A",
"rotorDiameterM": 100,
"manufacturer": "TurbineCorp",
"wtgType": "Horizontal Axis"
}
},
{
"category": "corrosion",
"timestamp": 1234567891,
"description": "Corrosion on surface",
"severity": 2
}
]
This endpoint retrieves a list of all annotations generated as part of the inspection.
GET https://api.unleashlive.com/v1/analytics/annotations/[teamId]/[folderId]
Replace [teamId] and [folderId].
Data Models
AnnotationResult:
Field | Type | Description |
---|---|---|
category | string | Category of the annotation |
timestamp | number | Inspection time |
distance | number | Distance from hub in meters (optional) |
area | number | Defect area in square centimeters (optional) |
description | string | Description of the annotation (optional) |
severity | number | Severity level (1-5, higher number indicates higher severity) (optional) |
assetId | string | ID of the associated asset (optional) |
context | object | Additional context information (optional) |
Context Object:
Field | Type | Description |
---|---|---|
hubHeightM | number | Hub height in meters |
turbineNo | string | Turbine number |
bladeManufacturer | string | Manufacturer of the blade |
siteName | string | Name of the site |
powerRatingMW | number | Power rating in megawatts |
bladeLengthM | number | Blade length in meters |
bladeType | string | Type of blade |
rotorDiameterM | number | Rotor diameter in meters |
manufacturer | string | Manufacturer of the turbine |
wtgType | string | Wind turbine generator type |
Unleash live Stream CLI
Version: 1.0.0
Unleash Stream CLI is a command-line interface tool that enables users to interact with the Unleash live streaming platform. Using the CLI, users can easily manage and control their local RTMP/RTSP/UDP streams and connect them to their Unleash live account.
The Unleash Stream CLI consists of two parts:
- Unleash Stream service
- Management command-line tool
During installation, the service is configured to run in the background, ensuring continuous streaming to the Unleash live platform, regardless of the state of the current user session.
Prerequisites
Unleash Stream CLI requires that the machine it is running on is Unix based running on either x86 or aarm64 architecture.
For Linux distributions supported, the requirement is glib in version 2.17+ and linux kernel version of 3.2+
For Unleash Stream CLI to work correctly make sure that devices you want to restream to Unleash live are accessible to the machine that you are running the tool on, and there is internet connection available.
Installation
To install Unleash Stream CLI on x86 based Linux system You can run:
Quick Tip: Click on shell at your top right to view the script.
wget -O - https://unleash-stream-cli.s3.ap-southeast-2.amazonaws.com/linux-x86/install.sh | bash -s -- install
There are installers available for aarm64 Linux and macOS.
This will execute installation script that downloads locally unleash-stream-cli binary for your system and starts the service mode using systemd.
Before using the unleash-stream-cli command ensure that ~/.local/bin/unleash-stream-cli
is on the system PATH.
You can view your existing path by running:
echo $PATH
echo $PATH
Unleash live Devices
When the unleash-stream service is running, you can communicate with the service using Unleash-stream-cli commands that allow you to add, remove, start, or stop the streams.
First, ensure that you have access to your Unleash live account and that you have created devices in your profile to mirror your local cameras or streaming devices.
To create a device, follow the link, go to the devices section, and click on "Add Device". This article provides more detailed directions for adding a new device for the first time.
Each created device has its unique Stream URL to which you can stream. To see it, navigate to the stream page and click the Manage
button next to the relevant device.
This stream URL contains important information about your device that you will use to send your local stream to the Unleash live platform.
Example stream URL looks like this:
rtmp://stream.unleashlive.com/rtmp/W123a4b5678c9de0?token=fluffy-black-dog-11
It contains the Unleash live domain and RTMP parts, followed by the Device ID (which starts with W), and then the generated account token for authorization (using the token parameter, for example fluffy-black-dog-11
).
These pieces of information will allow us to add the new stream using the unleash-stream CLI.
Unleash Stream CLI Commands
Available commands can be displayed using:
unleash-stream-cli —help
unleash-stream-cli —help
Each of the commands can be also inspected using
unleash-stream-cli COMMAND —help
unleash-stream-cli COMMAND —help
Consult this contextual help in case of any problems.
Start Restreaming
Once the devices are created and ready to use, you can begin sending your local streams to Unleash live. The Unleash Stream CLI supports a variety of streams from different devices (RTMP, RTSP, HTTP, UDP) and allows them to run in the background. It also automatically restarts the streams if any issues are encountered during the streaming process.
The Unleash Stream CLI provides the ability to manage multiple streams. To start restreaming, ensure that your camera/stream is accessible and that you have its stream URL. The URL can be in the format of RTMP, RTSP, or HTTP (such as an m3u8 playlist).
To add the stream and start restreaming to selected Unleash live device you can execute:
unleash-stream-cli add 'SOURCE_URL' -D 'UNLEASHLIVE_DEVICE_STREAM_URL'
unleash-stream-cli add 'SOURCE_URL' -D 'UNLEASHLIVE_DEVICE_STREAM_URL'
SOURCE_URL is your local stream URL that you want to restream. UNLEASHLIVE_DEVICE_STREAM_URL is the URL from the Unleash live Device Management section for the selected device taken from Unleash live Devices.
Examples of valid source URLs (consult the documentation of your streaming device for the exact stream location of your device)
'rtmp://192.168.0.1:1935/main'
'rtsp://username:password@10.0.0.1:443/subStream'
'https://cams.remote.com/cdn/chunks.m3u8'
Ensure that you put the source URL in quotes (either ' or ") especially when using RTSP with user/password authentication or in case of any other stream URL with special characters. The same thing applies to Unleash live Device Stream URL parameter.
The stream should appear on the Unleash live stream page. as your created device shortly after adding it via the CLI.
Streams Management
From this point on, you can add additional streams for different devices or monitor and check the status of the currently running ones. To do so, run:
unleash-stream-cli list
unleash-stream-cli list
This command will provide information about the status of the currently added streams and also allow for direct management if needed.
This command will return the following information:
- source URL
- destination URL
- streaming process log file path
- PID of the streaming process
- status (running, stopped, failed)
- number of failed attempts (Unleash Stream CLI will stop retrying after 5 failed attempts to restream)
To gain more insight into the status of the stream or troubleshoot any issues, it is helpful to examine the streaming process log file. Any networking problems or stream stability issues should be evident from the information provided in the log file.
If you encounter any difficulties that cannot be easily resolved, please reach out to Unleash live Support at support@unleashlive.com or directly contact your Unleash live Account Manager.
For additional management of the streams, it is possible to:
- stop
- start previously added but stopped or failed streams
- remove added stream from the list after stopping
To manage the streams, you need to provide the Unleashlive Device ID when calling the corresponding unleash-stream-cli methods. The Unleashlive Device ID can be obtained from the device configuration view on the stream page of your Unleashlive account. It is in the format of WXXXXXXXXXXXXXXX, where 'W' is followed by 15 lowercase alphanumeric characters.
To find the Unleashlive Device ID, refer to the fragment provided here: Unleash live Devices.
For example, to stop the device W123a4b5678c9de0 from streaming use:
unleash-stream-cli stop 'W123a4b5678c9de0'
unleash-stream-cli stop 'W123a4b5678c9de0'
Updating or Uninstalling CLI
Unleash live support team will contact you when there is a new update being released. To update an existing installation of Unleash Stream CLI, you can use the same installation script but with changed parameters.
wget -O - https://unleash-stream-cli.s3.ap-southeast-2.amazonaws.com/linux-x86/install.sh | bash -s -- update
wget -O - https://unleash-stream-cli.s3.ap-southeast-2.amazonaws.com/linux-x86/install.sh | bash -s -- update
Keep in mind, this will stop and remove currently running streams and will restart Unleash Stream service.
To completely uninstall Unleash Stream CLI you can run:
wget -O - https://unleash-stream-cli.s3.ap-southeast-2.amazonaws.com/linux-x86/install.sh | bash -s -- uninstall
wget -O - https://unleash-stream-cli.s3.ap-southeast-2.amazonaws.com/linux-x86/install.sh | bash -s -- uninstall
For any extra assistance, you can also contact us here or you can email us at support@unleashlive.com.
Unleash CLI
Unleash Command Line Interface (CLI) is an easy way to deploy the models into production. Users need to prepare their model files in a folder and upload them to their account using their command line.
Model deployment requirements
To successfully deploy your model, we require the following components:
- Model Overview:
- Please provide a concise description of the model, outlining the specific problem it addresses and its approach to solving that problem.
- Base Model or Deep Learning Architecture
- If your model is built upon an existing architecture or framework, such as Yolo family, Detectron2, ResNet, etc., please specify the architecture.
- If the model was designed from scratch, include the architecture details in PyTorch, TensorFlow, or ONNX format.
- Analytics/Post-processor code
- please provide the code If there is any analytics or post-processor algorithms are needed on top of the main model.
- Desired Output Format
- Specify the required columns or data in the output CSV. This will help ensure that the results from your model align with our needs.
- Annotation Preparation
- Clarify how you plan to prepare annotations for detections or AI-Clip results. Providing details about the annotation process will help streamline integration.
- Sample Output
- Including a sample output will offer clarity on the expected format and assist in verifying the results.
- Dependencies
- State the versions of PyTorch/TensorFlow and any other third-party libraries that your model depends on.
- Additionally, provide information about the CUDA version required for GPU acceleration.
- Deployment Script
- Preferably, supply a simple script that allows us to execute your model on our end. This will serve as a validation step, confirming that the model functions as intended in the deployment environment.
By providing these details, we can ensure a smooth deployment process and verify that your model aligns with our requirements.
Errors
Error Code
Unleash live API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request - Wrong or missing parameters. |
403 | Forbidden - Your API key is wrong or access denied. |
422 | Validation failed - Parameters content failed validation. |
500 | Internal Server Error - We had a problem with our server. Try again later. |
503 | Service Unavailable - We're temporarily offline for maintenance. Please try again later. |
Error Response Format
curl -X GET -H "x-api-key: none" https://api.unleashlive.com/v1/analytics/version
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.unleashlive.com/v1/analytics/version', headers={'x-api-key': ''})
r.data
{"message":"Forbidden"}
Standard error messages are returned upon an incomplete or invalid API request. Example shown on json.
FAQ
For the FAQs please follow this link: knowledge.unleashlive.com.
For any extra assistance, please contact us here. or you can email us at support@unleashlive.com