Skip to content

ExoSense GraphQL API

Info

The API is available at the Organization ExoSense Tier.

Overview

The ExoSense API uses GraphQL, a query language for supporting requests for data, modify objects, or to delete / create objects such as assets. GraphQL can be compared to REST and RPC (Remote Procedure Calls)

The ExoSense API is provided for software integrations such as but not limited to:

  • Retrieving and displaying Asset status and/or signal values in another business software tool.
  • Automating the creation of Assets during manufacturing of devices
  • Automating user invitations from a separate registration system or billing process

Info

Currently the API is not recommended for nor does it fully support building custom user applications.

API Endpoint

This API has a single endpoint specific to your ExoSense instance and does not change no matter what query is being made, which is a difference from RESTful APIs.

https://<$YOUR_EXOSENSE_INSTANCE_DOMAIN>/api/graphql 

<$YOUR_EXOSENSE_INSTANCE> is your ExoSense domain (e.g. example.apps.exosite.io)

Using the GraphQL API

All requests take the following HTTP format. Note that the call is an HTTP POST request with a JSON encoded body for the operations. This API supports two operations, being queries and mutations.

POST https://<$YOUR_EXOSENSE_INSTANCE_DOMAIN>/api/graphql 
Authorization: Automation $TOKEN
Content-Type: application/json
Accept: */*

{
    "query": "....",
    "operationName": "....",
    "variables": {"myvar1":"value1","myvar2":"value2", ...}
}
  • The query field in the JSON object is required.
  • The value for query is a GraphQL query encoded as a string.
  • operationName and variables optional fields, operationName is only required if multiple operations are present in the query.

Hint

GraphQL queries are like a GET request in a RESTful API. GraphQL mutations operate like POST, PATCH, and DELETE.

Queries

The GraphQL query essentially asks for fields in an object. A very simple example shows how to ask for a list of assets with the asset id and name. The object being 'assets'. Note that this call as is assumes all assets at the root level of the API token permission access.

For more information of GraphQL queries, the graphql.org site covers these details in more depth

Learn about GraphQL Queries

# Example of a Query, for Assets and to include the id and name fields
{
  assets {
    id
    name
  }
}
// Response JSON object
{
  "data": {
    "assets": [
      {
        "id": "6fe9fdcd-926e-4b39-a224-f0fd8c00a99b",
        "name": "Customer A Child 1 Asset 1"
      },
      {
        "id": "c6b918c7-a61d-4be9-aed6-06582d243e87",
        "name": "Customer A Child 1 Asset 2"
      },
      {
        "id": "85290cc8-db5b-4506-9f66-e1944f0a7322",
        "name": "Customer A Child 1 Asset 3"
      },
      {
        "id": "da965bda-d9ea-48d0-b2bf-869773744d3c",
        "name": "Customer A Child 1 Asset 4"
      },
      {
        "id": "73b79e78-d159-4c3e-b40d-f8b55dd9e286",
        "name": "Customer A Child 1 Asset 5"
      },
      {
        "id": "3a5b452a-a1b3-4efb-90c2-128853424491",
        "name": "Customer A Child 1 Asset 6"
      },
      {
        "id": "21811b22-d01a-4867-b1b2-81a2b554b63c",
        "name": "Customer A Child 1 Asset 7"
      },
      {
        "id": "3582118a-d390-457e-9836-2e72331d2b70",
        "name": "Customer A Child 1 Asset 8"
      }
    ]
  }
}

Arguments

Arguments allow you to specify query details for the the object and all nested objects. An example is to include the pagination argument (which happens to be an object itself) in with the assets query to limit the number of returned items.

# Query with arguments
{
  assets(pagination: {limit:3,offset:0}) {
    id name
  }
}
// JSON response, noting that only 3 assets were returned
{
  "data": {
    "assets": [
      {
        "id": "6fe9fdcd-926e-4b39-a224-f0fd8c00a99b",
        "name": "Customer A Child 1 Asset 1"
      },
      {
        "id": "c6b918c7-a61d-4be9-aed6-06582d243e87",
        "name": "Customer A Child 1 Asset 2"
      },
      {
        "id": "85290cc8-db5b-4506-9f66-e1944f0a7322",
        "name": "Customer A Child 1 Asset 3"
      }
    ]
  }
}

Aliases

Aliases allow you to query the same field but different arguments, so the result can be differentiated.

# Example query using aliases
{
  asset1: asset(id: "6fe9fdcd-926e-4b39-a224-f0fd8c00a99b") {
    name
  }
  asset2: asset(id: "c6b918c7-a61d-4be9-aed6-06582d243e87") {
    name
  }
}
{
  "data": {
    "asset1": {
      "name": "Customer A Child 1 Asset 1"
    },
    "asset2": {
      "name": "Customer A Child 1 Asset 2"
    }
  }
}

Note that GraphQL Fragments can also be used for more complex queries that reuse many of the same variables/fields, check out the GraphQL documentation for more information.

Operation Name & Type

Operation names are recommended, though optional unless you have a multi-operational document in which they are required. They allow the code to be more user friendly, in addition to helping with debugging. It's like a function name in programming.

The operation type is either query mutation or subscriptiondescribing the type of operation. It's required unless using shorthand syntax (the simple examples above). Shorthand syntax assumes no name or variables are provided.

# Example that includes the Operation Type and Name
query GetAllAssets {
  assets(pagination:{limit:3}) {
    name id
  }
}
// Resulting JSON object response
{
  "data": {
    "assets": [
      {
        "id": "6fe9fdcd-926e-4b39-a224-f0fd8c00a99b",
        "name": "Customer A Child 1 Asset 1"
      },
      {
        "id": "c6b918c7-a61d-4be9-aed6-06582d243e87",
        "name": "Customer A Child 1 Asset 2"
      },
      {
        "id": "85290cc8-db5b-4506-9f66-e1944f0a7322",
        "name": "Customer A Child 1 Asset 3"
      }
    ]
  }
}

Mutations

Mutations allow server side operations such as creating, deleting, and modifying objects. Mutations are similar to queries in syntax and responses. The one distinction is that when there are multiple fields in a mutation, they run in series, rather than parallel.

# example mutation request to delete an asset
mutation DeleteAsset  {
  deleteAsset(id: "3582118a-d390-457e-9836-2e72331d2b70") {
    id
  }
}
//response
{
  "data": {
    "deleteAsset": {
      "id": "3582118a-d390-457e-9836-2e72331d2b70"
    }
  }
}

Variables

Variables allow the client application making API requests to use a static string for the query but support dynamic variables that could be changed based on user inputs, etc. Note that the variable has to be declared for the query including specifying the type (in this case the type is Pagination ). Note that types are defined by the API itself. The variable is then passed in with the HTTP requests JSON body. Variables are declared with a $ prefix.

# query that includes a variable
query GetAllAssets($UserPaginationSetting: Pagination ) { 
  assets(pagination: $UserPaginationSetting) 
  {
    name id
  }
}

# the variables dictionary to pass in with the static string
{
    "UserPaginationSetting": {
        "limit": 3
    }
}
POST /api/graphql HTTP/2
Host: example.apps.exosite.io
Content-Type: application/json
Authorization: Automation <TOKEN HERE>
Accept: */*
Content-Length: 195

{
  "query":"query GetAllAssets($UserPaginationSetting: Pagination ) { \n  assets(pagination: $UserPaginationSetting) \n  {\n    name id\n  }\n}\n",
  "variables":{"UserPaginationSetting":{"limit":3}}
}

Format Notes

The examples provided in this document generally have been formatted for ease of readability. The following examples work exactly the same but the resulting query string passed into the HTTP request will contain any additional characters such as new lines.

query GetAllAssets {
  assets(pagination:{limit:3}) {
    name id
  }
}
# Note: drops the Operation Name
query { 
    assets(pagination:{limit:3}) {name id}
}
# Note: Shorthand syntax only supported for query type 
# and not recommended for documents containing many queries

{ assets(pagination:{limit:3}) {name id}}
# Note: Query is all on one line, otherwise same

query GetAllAssets { assets(pagination:{limit:3}) {name id}}

The resulting HTTP request for this last one looks like:

POST /api/graphql HTTP/2
Host: example.apps.exosite.io
Content-Type: application/json
Authorization: Automation <TOKEN WOULD BE HERE>
Accept: */*
Content-Length: 74

{"query":"query GetAllAssets { assets(pagination:{limit:3}) {name id}}"}

Authentication

This API uses Authentication Tokens that can be created in the application. Each token has a specific permission. This token is used in the Authorization header in the HTTP request. $TOKEN below is replaced with the actual token.

Authorization: Automation $TOKEN

Creating an API Token

If you haven't already, navigate to Setup > API Tokens and create a new token. The role you choose for the token, similar to a user role, will limit the ExoSense™ access granted to the token.

Save the token in a safe and secure location. You won't be able to access it again, so don't lose it. If you do lose it, a new token must be generated.

Responses

GraphQL responses takes the same shape as the query, returned as a JSON object. The response JSON object contains two fields, data and errors. The errors field is only returned if there were errors, otherwise it is not present.

{
  "data": { ... },
  "errors": [ ... ]
}

Resource Limitations

Info

Note: The limits are subject to change as we observe how developers use the the ExoSense GraphQL API.

Rate Limits

The rate limit for the ExoSense API is 60 requests per minute per API Token.

Other Limitations

The ExoSense solution runs on top of Exosite's Murano microservice platform. Each API request results in a set of scripts and function calls on the platform and into services (such as databases), some of which can be data / time intensive. There is a 10 second runtime limit for the resulting set of functions and scripting for each API request and when hit, will return immediately with an error.

Schema

GraphQL is powerful in that with a request, you can perform an introspection of the API realtime. (i.e. it is self documented) . Details about GraphQL Introspection

To perform this introspection, you can query the __schema and __type fields, although there are several tools that support GraphQL natively and provide an automated built-in way to view the documentation.

Tools

There are a number of tools that natively support GraphQL to test and run queries and introspect of the API, including Insomnia and Postman which are commonly used tools to test HTTP requests, REST APIs, etc.

https://insomnia.rest/graphql/

https://www.getpostman.com/product/api-client

Libraries

There are a number of libraries, tools, and services built for GraphQL, which can be found on the GraphQL organization site.

https://graphql.org/code/

Getting Started

Exosite provides an example JSON file that can be imported into Insomnia and provides a number of example queries and mutation requests. Please submit a support request to get a copy of this file.


Last update: April 10, 2021