NAV Navbar

Introduction

Welcome to Numina-Graph!

Numina-Graph is a GraphQL API for accessing all kinds of Numina data and analytics. This tutorial will:

If this is your first time working with GraphQL, you can get familiarized with the fundamentals here.

You can access the GraphQL endpoint at: https://api.numina.co/graphql

High Level Concepts

Numina-Graph provides access to two types of data:

Users can issue GraphQL queries to learn about both types of data. In addition, mutations are used to authenticate and to configure certain types of relational data.


Relational data model.

Key Terms


Example of a Behavior Zone.

Schema

For a detailed look at the various types and relationships in the schema, take a look at our schema documentation. And since this is a GraphQL API, you can also use introspection to examine the schema from the API itself.

Authentication

Numina-Graph uses JSON Web Tokens (JWT) to authenticate requests to our API. When you sign up with Numina, you will be given an account email and password to authenticate requests for your organization.

Example logIn mutation:

mutation {
  logIn(
      email:"you@youremail.com",
      password:"yourpassword") {
    jwt {
      token
      exp
    }
  }
}

To get a token, issue a logIn mutation (as a POST request) to the GraphQL endpoint with your username and password as parameters. If successful, the response will contain your token, as well as an expiry date and time. Tokens expire after 24 hours by default.

Example logIn response body:

{
  "data": {
    "logIn": {
      "jwt": {
        "exp": "2019-03-26T21:16:15.763782",
        "token": "alongtokenstring"
      }
    }
  }
}

Once you have a token, include the token value as the HTTP Authorization header in subsequent POST requests to authorize your queries and mutations.

Relational Data

Queries

Users can query relational data that falls under the umbrella of their organization.

Example devices query:

query {
  devices {
    count
    edges {
      node {
        rawId
        name
        serialno
      }
    }
  }
}

For example, we can request information about any devices that belong to our organization. A number of different fields could be requested; here, we're requesting just the device name and serial number, as well as a rawId that can be used as a unique way to identify the device in other requests.

Send the following query as a POST request to the GraphQL endpoint:

Example devices query response body:

{
  "data": {
    "devices": {
      "count": 1,
      "edges": [
        {
          "node": {
            "name": "abc-12",
            "serialno": "NUM200B000S0001",
            "rawId": "39617ed712sd566babcac89jbdcc6f19"
          }
        }
      ]
    }
  }
}

Mutations

Mutations allow you to update and delete relational data belonging to your organization, including modifying your organization, device, and Behavior Zone data.

Example updateDevice mutation:

mutation {
  updateDevice(
      deviceId:"d92d6xmayb324751b0c63f872nz08f95",
      device:{name: "abc-15"}) {
    device {
      rawId
      name
      serialno
    }
  }
}

In this example, we use the updateDevice mutation to edit the name of a given device. Here, the deviceId is the rawID obtained from the devices query in the previous section.

Example updateDevice response body:

{
  "data": {
    "updateDevice": {
      "device": {
        "name": "abc-15",
        "rawId": "d92d6xmayb324751b0c63f872nz08f95",
        "serialno": "NUM200B000S0001"
      }
    }
  }
}

The response reflects the updated device name, showing that our mutation was successful.

Example createBehaviorZone mutation:

mutation {
  createBehaviorZone(
    serialno:"NUM200B000S0001",
    demarcation:[[376,123],[459,94],[557,106],[543,185],[511,236],
    [473,265],[361,247],[347,184]],
  text: "My Zone") {
    behaviorZone {
      rawId
    }
  }
}

In this example, we use the createBehaviorZone mutation to create a new Behavior Zone for a device. The Behavior Zone is defined by a demarcation which is a set of [x,y] pixel coordinates of the zone's vertices. We also describe the Behavior Zone with a text description. Sandbox users can use our Behavior Zone Creator to design Behavior Zones visually.

Example createBehaviorZone response body:

{
  "data": {
    "createBehaviorZone": {
      "behaviorZone": {
        "rawId": 1770
      }
    }
  }
}

The response here provides the ID of the newly created Behavior Zone, which can be used in subsequent analytics queries as a spatial filter on the sensor data.

Analytics Data

You can also use Numina-Graph to query for advanced analytics on the data generated by your organization's devices.

Counts

Counts queries are used to get counts of objects that were observed in a given time interval.

Example feedCountMetrics query:

query {
  feedCountMetrics(
    serialnos:["NUM200B1234"],
    startTime:"2019-03-11T00:00:00",
    endTime:"2019-03-12T00:00:00",
    objClasses:["pedestrian"],
    timezone:"America/New_York",
    interval:"6h") {
    edges {
      node {
        serialno
        result
        objClass
        time
      }
    }
  }
}

In this example, we're using the feedCountMetrics query to find the number of pedestrians detected by a specified device on March 11, 2019, grouped by 6 hour intervals. Similarly, we could use the zoneCountMetrics query to get counts of objects in a Behavior Zone.

Example feedCountMetrics response body:

{
  "data": {
    "feedCountMetrics": {
      "edges": [
        {
          "node": {
            "objClass": "pedestrian",
            "result": 595.0,
            "serialno": "NUM200B000S0001",
            "time": "2019-03-11T00:00:00-04:00"
          }
        },
        {
          "node": {
            "objClass": "pedestrian",
            "result": 7479.0,
            "serialno": "NUM200B000S0001",
            "time": "2019-03-11T06:00:00-04:00"
          }
        },
        {
          "node": {
            "objClass": "pedestrian",
            "result": 28245.0,
            "serialno": "NUM200B000S0001",
            "time": "2019-03-11T12:00:00-04:00"
          }
        },
        {
          "node": {
            "objClass": "pedestrian",
            "result": 12146.0,
            "serialno": "NUM200B000S0001",
            "time": "2019-03-11T18:00:00-04:00"
          }
        }
      ]
    }
  }
}

The response body contains result sets for each 6 hour interval on March 11 - four intervals in total. Each interval is denoted by its start time.

Heatmaps

A heatmap is an array of values representing the spatial distribution of activity levels. Numina-Graph provides heatmaps of object counts that can be used to visualize what paths objects travel within the sensing area.

Example feedHeatmaps query:

query {
  feedHeatmaps(
    serialno: "NUM200B000S0001",
    startTime:"2019-05-01T00:00:00",
    endTime:"2019-05-02T00:00:00",
    objClasses:["pedestrian"],
    timezone:"America/New_York") {
    edges {
      node {
        time
        objClass
        heatmap
      }
    }
  }
}

In this example, we're using the feedHeatmaps query to determine where pedestrian travel is concentrated over the course of a single day. Similarly, the zoneHeatmaps query can be used to get heatmaps of objects in a Behavior Zone.

Example feedHeatmaps response body:

{
  "data": {
    "feedHeatmaps": {
      "edges": [
        {
        "node": {
          "heatmap": [
            [244,60,0.204],
            [246,60,0.204],
            [247,60,0.408],
            [239,61,0.322],
            ...
            ],
          "objClass": "pedestrian"
          }
        }
      ]
    }
  }
}

The heatmap data in the response is an array of coordinate-value tuples, in the form [x,y,value] where x and y are the horizontal and vertical pixel coordinates (top-left origin) for a 640x480 image.


Example of a heatmap visualization.

API Sandbox

Our API Sandbox is geared towards third-party developers interested in getting their feet wet with the Numina API by exploring real, street-level data. We have created a "sandbox" environment with ten days of real data from a sensor deployment in Downtown Brooklyn in New York City. This data includes:

With this data, we hope that interested developers can understand how to perform data analyses on the impact of specific street-level phenomena (such as construction, weather, etc). If you're interested in this sandbox environment, please request access and check out our annotated blog post to see how you can leverage the Numina API to understand your streets better.

Exploring Further

This is a very brief introduction to what users can do with Numina's API. To explore further, check out our schema documentation. Then, set up a GraphQL client such as Insomnia or GraphiQL and start sending queries to Numina-Graph. You can use the Behavior Zone Creator to design Behavior Zones for spatial analysis of the Sandbox data. We've also published an annotated blog post where you can read how we used the Numina API to provide street-level insight for Downtown Brooklyn Partnership.