NAV
javascript graphql json shell python

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

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

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:

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:

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:

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:

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:

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:

  1. Model Overview:
    • Please provide a concise description of the model, outlining the specific problem it addresses and its approach to solving that problem.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. Sample Output
    • Including a sample output will offer clarity on the expected format and assist in verifying the results.
  7. 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.
  8. 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