API Docs

Density API

The Density API hosts real-time and historical people count data for your Density-enabled spaces.

The Density API is built upon REST, returns JSON responses, and supports cross-origin resource sharing. Standard HTTP verbs are used to perform CRUD operations, and the API returns standard HTTP response codes to indicate errors. API versioning is implemented via namespaces. Token authentication is used to authenticate every API request.

Base URL

https://api.density.io/v2

Authentication

All API endpoints are authenticated using your API token, found in the dashboard.

Your token must be included in the Authorization HTTP header, prefixed by the string literal "Bearer" with a single space separating the two strings. Any API call made without the proper Authorization header will return a 403 error.

HTTP Authorization Header

Authorization: Bearer YOUR_API_TOKEN

Errors

Density endpoints use standard HTTP error codes. The response includes any additional information about the error.

Error Codes

400 Bad Request

The request sent to the API is invalid. Additional information will be returned in the response body.

403 Forbidden

The client is not allowed to perform this request. Can be caused by a missing or invalid API token.

404 Not Found

The requested resource does not exist.

409 Conflict

The request conflicts with another request.

Timestamps

All timestamps sent to the API must be formatted as strings according to the ISO 8601 standard for UTC timestamps. The API will return all timestamps in the same UTC format.

Most programming platforms have built-in utilities to convert between local time and UTC.

ISO 8601 UTC Timestamp

2016-05-23T10:00:00.000Z

Pagination

Density endpoints that return multiple results will be paginated to 200 items by default.

For these endpoints the root of the response object will contain the total number of results, the next and previous page URLs, and an array with the current page of results. If all results fit onto a single page, the next and previous page URLs will be null.

Query String Parameters

page
integer
default: 1

If included, the endpoint will return a particular page of data.

page_size
integer
default: 200

If included, the endpoint will return pages of this size. The maximum page size is 1000.

Example Request

$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  https://api.density.io/v2/spaces/?page=4&page_size=15

Paginated Response

{
  "total": 89,
  "next": "https://api.density.io/v2/spaces/?page=5&page_size=15",
  "previous": "https://api.density.io/v2/spaces/?page=3&page_size=15",
  "results": [
    …
  ]
}

CSV Export

The Density API can return data in CSV format for convenience. To request CSV, set the Accept header to the value text/csv.

In CSV format, nested fields will be flattened, with the nested field names in order separated by a dot character (.).

CSV responses are not paged, all results will be returned. Large responses may take longer to prepare, and no more than 31 days of traffic data can be queried at a time.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: text/csv" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/events/\
?start_time=2017-09-19T08:00:00.000Z\
&end_time=2017-09-20T08:00:00.000Z

CSV Response

direction,doorway_id,id,sensor_serial_number,timestamp
1,drw_452554070478029236,evt_463842287353331919,Z444944692392493397,2017-09-19T12:23:45.405Z
-1,drw_452554070478029236,evt_463533857086374803,Z444944692392493397,2017-09-19T12:38:03.575Z
...

Counts and Events

The Density API provides real-time and historical people count for logical spaces. A "space" can be a room, a floor, a building, or a campus. Each space has a unique id for querying its data.

People count is represented by two concepts: counts and events. A "count" is the number of people in a space at a particular time. An "event" is an entrance or exit to or from a space at a particular time.

Space "counts" are sampled at regular intervals, and analytics for each interval are included in the API response. See Space Counts for details.

List Spaces

Each space includes a list of doorways linked to the space, the current_count of people in the space, the total capacity of the space, a daily_reset time, the space type (see list in Spaces section), and an optional parent space's ID. There are also optional address fields to be used to locate campuses and buildings.

The ancestry field returns an array of parent spaces. First element = closest, last = furthest.

There is validation on space types and parent associations. For example, you can have a floor that has a building as parent, but not the other way around.

To query foot traffic data for a space, use an id returned by this endpoint with the other two endpoints in this section. To manage the spaces and doorways in your environment with the Density API, see these sections: Spaces, Doorways, and Links.

GET /spaces/

Query String Parameters

doorway_id

If included, return only spaces associated with this doorway.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/spaces/

Example Response

{
  "total": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "spc_575377614718369795",
      "name": "Headquarters",
      "notes": "Company HQ",
      "meta": {
        "optional_meta_data": "abc123"
      },
      "description": "Company HQ",
      "parent_id": null,
      "space_type": "building",
      "function": null,
      "time_zone": "America/New_York",
      "daily_reset": null,
      "current_count": 3,
      "capacity": 65,
      "target_capacity": null,
      "safe_capacity": null,
      "safe_threshold_mode": null,
      "safe_threshold_value": null,
      "max_dwell_minutes": null,
      "doorways": [],
      "tags": [],
      "address": "123 First St, Ankh-Morpork, DW 90210-1219",
      "latitude": null,
      "longitude": null,
      "counting_mode": "doorways",
      "component_spaces": [],
      "floor_level": null,
      "space_mappings": [],
      "time_segments": [],
      "time_segment_groups": [],
      "size_area": null,
      "size_area_unit": null,
      "annual_rent": null,
      "annual_rent_currency": "USD",
      "assigned_teams": [],
      "sensors_total": 1,
      "image_url": null,
      "created_at": "2019-09-24T01:07:32.253Z",
      "updated_at": "2020-08-06T22:03:05.349Z",
      "description": "",
      "inherits_time_segments": false
    },
    {
      "id": "spc_575377614718369795",
      "name": "Main Office",
      "notes": "",
      "description": "",
      "parent_id": "spc_575377614718369795",
      "ancestry": [
        {
          "id": "spc_575377614718369795",
          "name": "Headquarters"
        }
      ],
      "space_type": "space",
      "function": "office",
      "time_zone": "America/New_York",
      "daily_reset": null,
      "current_count": 30,
      "capacity": 80,
      "target_capacity": null,
      "safe_capacity": null,
      "safe_threshold_mode": null,
      "safe_threshold_value": null,
      "max_dwell_minutes": null,
      "doorways": [],
      "tags": [],
      "address": null,
      "latitude": null,
      "longitude": null,
      "counting_mode": "doorways",
      "component_spaces": [],
      "floor_level": null,
      "space_mappings": [],
      "time_segments": [],
      "time_segment_groups": [],
      "size_area": null,
      "size_area_unit": null,
      "annual_rent": null,
      "annual_rent_currency": "USD",
      "assigned_teams": [],
      "sensors_total": 1,
      "image_url": null,
      "created_at": "2019-09-24T01:07:32.253Z",
      "updated_at": "2020-08-06T22:03:05.349Z",
      "description": "",
      "inherits_time_segments": false
    }
  ]
}

Space Counts

List counts for a space over a period of time, sampled at regular intervals. Each sample contains a timestamp and the count at that time. Each sample also includes an interval object with start and end times, and a nested analytics object containing the min count, max count, total events, total entrances, total exits, utilization, target utilization, entry_rate (per minute) and exit_rate (per minute) for the interval. In each interval, utilization and target_utilization are calculated based on the max count for that interval. utilization is calculated by max / capacity, and target_utilization by max count / target_capacity.

The response also contains a metrics object with aggregate metrics for each type of event (entrances, exits, count and max).

Counts can optionally be filtered by one or more time segment or time segment group.

GET /spaces/:space_id/counts/

Query String Parameters

* start_time
required | string

Sample counts starting at this timestamp. Must be formatted as an ISO 8601 UTC timestamp.

* end_time
required | string

Sample counts until just before this timestamp. Must be formatted as an ISO 8601 UTC timestamp.

interval
interval
default: 1h

If present, sample counts at this interval. Must be an integer followed by s (seconds), m (minutes), h (hours), d (days), or w (weeks)

order
ASC or DESC
default: ASC

Order the count samples in ascending or descending chronological order.

time_segments
can be included multiple times

A time segment ID associated with this space to filter count results by.

time_segment_groups
can be included multiple times

A time segment group ID associated with this space to filter count results by.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/counts/\
?start_time=2017-09-19T15:00:00Z\
&end_time=2017-09-19T17:00:00Z\
&time_segments=tsm_579017521479286820\
&time_segments=tsm_578329221793841160

Example Response

{
  "total": 2,
  "next": null,
  "previous": null,
  "metrics": {
    "entrances": {
      "total": 40,
      "average": 1.5,
      "peak": {
        "value": 6,
        "timestamp": "2020-08-30T20:00:00.000Z"
      }
    },
    "exits": {
      "total": 38,
      "average": 1.5,
      "peak": {
        "value": 6,
        "timestamp": "2020-08-30T20:00:00.000Z"
      }
    },
    "count": {
      "average": 1.1,
      "min": {
        "value": 0,
        "timestamp": "2020-08-31T08:00:00.000Z"
      },
      "max": {
        "value": 3,
        "timestamp": "2020-08-31T15:00:00.000Z"
      }
    },
    "target_utilization": {
      "average": null,
      "min": null,
      "max": null,
      "durations": {
        "0": "0:00:00",
        "40": "0:00:00",
        "80": "0:00:00",
        "100": "0:00:00"
      }
    }
  },
  "results": [
    {
      "timestamp": "2020-08-30T15:00:00.000Z",
      "count": 0,
      "interval": {
        "start": "2020-08-30T15:00:00.000Z",
        "end": "2020-08-30T15:59:59.999Z",
        "analytics": {
          "min": 0,
          "max": 1,
          "events": 4,
          "entrances": 2,
          "exits": 2,
          "utilization": null,
          "target_utilization": null,
          "entry_rate": 0.0,
          "exit_rate": 0.0
        }
      }
    },
    {
      "timestamp": "2020-08-30T16:00:00.000Z",
      "count": 0,
      "interval": {
        "start": "2020-08-30T16:00:00.000Z",
        "end": "2020-08-30T16:59:59.999Z",
        "analytics": {
          "min": 0,
          "max": 1,
          "events": 10,
          "entrances": 5,
          "exits": 5,
          "utilization": null,
          "target_utilization": null,
          "entry_rate": 0.1,
          "exit_rate": 0.1
        }
      }
    }
  ]
}

Space Events

List individual entrances and exits into or out of a space over a period of time. Each event contains a timestamp and direction (1 for entrance, -1 for exit).

GET /spaces/:space_id/events/

Query String Parameters

* start_time
required | string

Query traffic starting at this time. Must be formatted as an ISO 8601 UTC timestamp.

end_time
string
default: now

Query traffic until this time. Must be formatted as an ISO 8601 UTC timestamp.

doorway_id
string

Query only traffic through this doorway.

direction
1 or -1

Query only traffic matching this direction.

order
ASC or DESC
default: ASC

Order the traffic events in ascending or descending chronological order.

time_segments
can be included multiple times

A time segment ID associated with this space to filter event results by.

time_segment_groups
can be included multiple times

A time segment group ID associated with this space to filter event results by.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/events/\
?start_time=2017-09-19T15:00:00Z\
&end_time=2017-09-19T17:00:00Z

Example Response

{
  "total": 138,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "evt_459087893936210613",
      "sensor_serial_number": "Z457234837531526031",
      "doorway_id": "drw_452554070478029236",
      "timestamp": "2016-09-19T15:32:10.409Z",
      "direction": -1
    },
    {
      "id": "evt_459087875221226161",
      "sensor_serial_number": "Z457234837531526031",
      "doorway_id": "drw_452554070478029236",
      "timestamp": "2016-09-19T15:32:19.148Z",
      "direction": 1
    },
    ...
  ]
}

Use Cases

This section describes common use cases and the API calls used to query the appropriate data.

Count Samples

Sample the count every five minutes for 24 hours. The count field in each result is the number of people who were in the space at the corresponding timestamp.

Use this call to find out how your space is used throughout one day.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/counts/\
?start_time=2017-09-19T08:00:00Z\
&end_time=2017-09-20T08:00:00Z\
&interval=5m\
&page_size=288

Example Response

{
  "total": 288,
  "next": null,
  "previous": null,
  "metrics": {
    "entrances": {
      "total": 31,
      "average": 0.1,
      "peak": {
        "value": 3,
        "timestamp": "2019-09-19T20:10:00.000Z"
      }
    },
    "exits": {
      "total": 30,
      "average": 0.1,
      "peak": {
        "value": 3,
        "timestamp": "2019-09-19T16:50:00.000Z"
      }
    },
    "count": {
      "average": 0.7,
      "min": {
        "value": 0,
        "timestamp": "2019-09-19T15:00:00.000Z"
      },
      "max": {
        "value": 2,
        "timestamp": "2019-09-19T18:20:00.000Z"
      }
    },
    "target_utilization": {
      "average": null,
      "min": null,
      "max": null,
      "durations": {
        "0": "0:00:00",
        "40": "0:00:00",
        "80": "0:00:00",
        "100": "0:00:00"
      }
    }
  },
  "results": [
    {
      "timestamp": "2019-09-19T08:00:00.000Z",
      "count": 0,
      "interval": {
        "start": "2019-09-19T08:00:00.000Z",
        "end": "2019-09-19T08:04:59.999Z",
        "analytics": {
          "min": 0,
          "max": 0,
          "events": 0,
          "entrances": 0,
          "exits": 0,
          "utilization": null,
          "target_utilization": null,
          "entry_rate": 0.0,
          "exit_rate": 0.0
        }
      }
    },
  ....
  ]
}

Total Entrances

Get the total number of entrances into a space every day for one week. Each result's interval object has a nested analytics object with data for that interval, including the total number of entrances.

Use this call to find out how many people are visiting your space on different days of the week.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/counts/\
?start_time=2017-09-17T08:00:00Z\
&end_time=2017-09-24T08:00:00Z\
&interval=1d\
&page_size=7

Example Response

{
  "total": 7,
  "next": null,
  "previous": null,
  "metrics": {
    "entrances": {
      "total": 54,
      "average": 7.7,
      "peak": {
        "value": 31,
        "timestamp": "2017-09-22T08:00:00.000Z"
      }
    },
    "exits": {
      "total": 55,
      "average": 7.9,
      "peak": {
        "value": 30,
        "timestamp": "2017-09-22T08:00:00.000Z"
      }
    },
    "count": {
      "average": 0.6,
      "min": {
        "value": 0,
        "timestamp": "2017-09-22T08:00:00.000Z"
      },
      "max": {
        "value": 2,
        "timestamp": "2017-09-22T08:00:00.000Z"
      }
    },
    "target_utilization": {
      "average": null,
      "min": null,
      "max": null,
      "durations": {
        "0": "0:00:00",
        "40": "0:00:00",
        "80": "0:00:00",
        "100": "0:00:00"
      }
    }
  },
  "results": [
    {
      "timestamp": "2017-09-17T08:00:00.000Z",
      "count": 0,
      "interval": {
        "start": "2017-09-17T08:00:00.000Z",
        "end": "2017-09-18T07:59:59.999Z",
        "analytics": {
          "min": 0,
          "max": 43,
          "events": 468,
          "entrances": 234,
          "exits": 234
        }
      }
    },
    ...
  ]
}

Individual Exits

List individual exits from a space over a 24-hour period. Each result has a timestamp and a direction (which in this example will always be -1).

Use this call to find out exactly when people are leaving your space.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/events/\
?start_time=2017-09-19T08:00:00Z\
&end_time=2017-09-20T08:00:00Z\
&direction=-1\
&page_size=1000

Example Response

{
  "total": 234,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "evt_459087848717419179",
      "sensor_serial_number": "Z457234837531526031",
      "doorway_id": "drw_452554070478029236",
      "timestamp": "2016-09-19T08:03:19.148Z",
      "direction": -1
    },
    ...
  ]
}

Sensor Events

The Density API also provides a low-level stream of "sensor events". These events are not necessarily one-to-one with traffic events at any space, because sensors can be mounted on either side of a doorway.

This endpoint should only be used for testing configured sensors and environments.

List Sensor Events

List low-level "sensor events" for a sensor and a period of time. Each sensor event contains a timestamp and a trajectory relative to the sensor. The trajectory is not necessarily equal to any direction relative to a space (i.e. an entrance or exit).

This call should only be used for testing sensor performance.

GET /sensors/:serial_number/events/

Query String Parameters

* start_time
required | string

The earliest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.

end_time
string
default: now

The latest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.

trajectory
1 or -1

Query only sensor events matching this trajectory (relative to the sensor). If the sensor is mounted on the inside of your space, 1 means an entry and -1 means an exit.

order
ASC or DESC
default: ASC

Order the sensor events in ascending or descending chronological order.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/sensors/Z444944692392493397/events/\
?start_time=2017-09-19T15:00:00Z
&end_time=2017-09-19T15:01:00Z

Example Response

{
  "total": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "evt_459087875221226161",
      "doorway_id": "drw_452554070478029236",
      "sensor_serial_number": "Z444944692392493397",
      "timestamp": "2017-09-19T15:00:10.436Z",
      "trajectory": 1
    },
    {
      "id": "evt_459087822347829922",
      "doorway_id": "drw_452554070478029236",
      "sensor_serial_number": "Z444944692392493397",
      "timestamp": "2017-09-19T15:00:19.003Z",
      "trajectory": -1
    }
  ]
}

Simulate Event

Simulate a low-level sensor event. Real sensors will automatically create their own events.

This call should only be used for testing sensor and doorway placement.

POST /sensors/:serial_number/events/

Request Body

* trajectory
required | 1 or -1

The trajectory of the traffic event, relative to the sensor. If the sensor is mounted on the inside of your space, 1 means an entry and -1 means an exit.

timestamp
string
default: now

The time the event was detected. Must be formatted as an ISO 8601 UTC timestamp.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "timestamp": "2016-09-19T15:45:00.000Z",
    "trajectory": 1
}' \
https://api.density.io/v2\
/sensors/Z444944692392493397/events/

Example Response

{
    "id": "evt_459087817750872736",
    "doorway_id": "drw_452554070478029236",
    "sensor_serial_number": "Z444944692392493397",
    "timestamp": "2016-09-19T15:45:00.000Z",
    "trajectory": 1
}

Resets

The count at each space may be reset to 0 daily, so that drift (counting error) doesn't accumulate over time, ensuring long-term accuracy.

To reset the current count or to view historical resets at a space, use the /spaces/:space_id/resets/ endpoint. In production, you can configure the daily_reset property on a space to automatically reset its count at that (UTC) time every day.

List Resets

List resets for a space and a period of time. Each reset contains a timestamp and the new count.

GET /spaces/:space_id/resets/

Query String Parameters

* start_time
required | string

The earliest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.

end_time
string
default: now

The latest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/resets/\
?start_time=2017-09-19&end_time=2017-09-20

Example Response

{
  "total": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "rst_458961873618862211",
      "space_id": "spc_452554024357462439",
      "timestamp": "2016-09-19T08:00:00",
      "count": 0,
      "pre_reset_count": 1
    }
  ]
}

Reset Count

Reset the count for a space. The count parameter can be used to reset the count to a number other than 0.

POST /spaces/:space_id/resets/

Request Body

count
integer
default: 0

Reset the count to this value.

timestamp
string
default: now

The time of the reset. Should be formatted as an ISO 8601 UTC timestamp.

Spaces

The Density API can also be used to create and link spaces and doorways. Most integrations will not need to use these endpoints, as interactive tools to do so will be provided.

A space can be located within, adjacent to, or overlapping another space. For example, the interior of a conference room can be a space. The interior of the entire building can be a space as well. As long as you can put a name to an indoor region with foot traffic, it can be a space.

Possible values for space_type:

  • space (default)
  • floor
  • building
  • campus

Possible values for function:

  • amenities_space
  • break_room
  • cafe
  • collaboration
  • conference_room
  • dining_area
  • event_space
  • focus_quiet
  • gym
  • kitchen
  • lab
  • library
  • lounge
  • meeting_room
  • office
  • phone_booth
  • place_of_worship
  • reception
  • restroom
  • retail
  • theater
  • wellness_room

A space hierarchy is created by the (optional) parent field. These connections are validated so that campuses contain buildings, floors are within buildings, and so on.

A few rules on our space hierarchy:

  • The hierarchy is Campus > Building > Floor > Space.
  • A building can be stand-alone or belong to a campus.
  • A space can belong to a campus, building, floor, or another space.
  • A space can only have one child space.

Spaces can be further organized with tags.

A safety threshold can be defined for each space, to make use of Density's Safe features and Safe Display, through the safe_threshold_value field. There are 3 safe threshold modes, defined by the safe_threshold_mode field:

  • SAFE_CAPACITY: The space is considered unsafe when the number of people in it exceeds the number defined in the space's safe_capacity field
  • UTILIZATION_PERC_TARGET: The space is considered unsafe when the number of people in it is more than a proportion of the target_capacity. The proportion is defined in the safe_threshold_value field. For example, if the target_capacity is 10, and safe_threshold_value is 0.6, the space is considered unsafe when there are more than 6 people.
  • UTILIZATION_PERC_LEGAL: The space is considered unsafe when the number of people in it is more than a proportion of the legal_capacity. The proportion is defined in the safe_threshold_value field.

Density spaces connected to other rooms and spaces through integrations will have the connected reflected in the space_mappings field.

Should you need to store certain metadata to correlate Density spaces with your own internal spaces, you can use the freeform meta field to save a json structure.

Get Space

Get detailed information about a space. Includes the current count, the daily reset time, the list of doorways linked to this space, space type, and address information, and its parent in the space hierarchy.

The ancestry field returns an array of parent spaces. First element = closest, last = furthest.

GET /spaces/:space_id/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/

Example Response

{
  "id": "spc_452554024357462439",
  "name": "Conference Rm A",
  "notes": "The conf room",
  "meta": {
    "optional_meta_data": "abc123"
  },
  "description": "The conf room",
  "parent_id": "spc_352554024357462131",
  "ancestry": [
    {
      "id": "spc_352554024357462131",
      "name": "Floor A"
    },
    {
      "id": "spc_552573639257462532",
      "name": "Building 123"
    }
  ],
  "space_type": "space",
  "function": "conference_room",
  "capacity": 50,
  "target_capacity": null,
  "safe_capacity": null,
  "safe_threshold_mode": null,
  "safe_threshold_value": null,
  "max_dwell_minutes": null,
  "time_zone": "America/New_York",
  "daily_reset": "13:00",
  "current_count": 5,
  "doorways": [
    {
      "id": "drw_452554070478029236",
      "name": "Front Door",
      "link_id": "lnk_835699047305052422",
      "sensor_placement": 1
    }
  ],
  "tags": [
    "tech_garden"
  ],
  "address": "1516 1st St Suite 902, New York, NY 10001",
  "latitude": null,
  "longitude": null,
  "counting_mode": "doorways",
  "component_spaces": [],
  "floor_level": null,
  "space_mappings": [],
  "time_segments": [
    {
      "id": "tsm_578329221793841160",
      "name": "Main Lunchtime",
      "start": "11:00:00",
      "end": "12:00:00",
      "days": [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
      ]
    }
  ],
  "time_segment_groups": [
    {
      "id": "tsg_578329608869380107",
      "name": "All Lunches"
    }
  ],
  "size_area": null,
  "size_area_unit": null,
  "annual_rent": null,
  "annual_rent_currency": "USD",
  "assigned_teams": [],
  "sensors_total": 1,
  "image_url": null,
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "inherits_time_segments": false
}

Create Space

Add a space to your environment. To link doorways to this space, use the POST /links endpoint after creating the space with this endpoint.

POST /spaces/

Request Body

* name
required | string

The name of the space.

notes
string

Notes about the space.

meta
json

Free-form JSON metadata to store on the space.

time_zone
string

The timezone of the space in tzdata format.

capacity
integer

The maximum number of people that can legally occupy the space.

target_capacity
integer

The target maximum number of people occupying the space.

safe_capacity
integer

If safe_threshold_mode is set to SAFE_CAPACITY, this is the maximum number of people that can occupy the space for it to be deemed safe.

safe_threshold_mode
string

How the safe threshold is calculated. Can be SAFE_CAPACITY, UTILIZATION_PERC_LEGAl orUTILIZATION_PERC_TARGET.

safe_threshold_value
float

The proportion of the legal capacity or target capacity (depending on safe_threshold_mode), above which the space is deemed in unsafe.

daily_reset
string

A 24-hour time in the local time zone. The space's count will automatically reset to 0 at this time every day. The default daily reset time is 04:00.

space_type
string

The space type: space (default), floor, building, or campus.

function
string

The function of the space: (amenities_space, break_room, cafe, collaboration, conference_room, dining_area, event_space, focus_quiet, gym, kitchen, lab, library, lounge, meeting_room, office, phone_booth, place_of_worship, reception, restroom, retail, theater, wellness_room)

parent_id
string

The ID of the parent space if in a hierarchy.

address
string

Street address of the space.

annual_rent
float

Only allowed in spaces whose space_type is building. The rent of the building.

annual_rent_currency
string

The currency for the annual_rent number. The default is USD.

size_area
float

The area of the space.

size_area_unit
string

The unit for the size_area number. The default is square_feet.

latitude
float

Latitude for precision mapping.

longitude
float

Longitude for precision mapping.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "name": "Kitchen",
    "notes": "Office Kitchen",
    "daily_reset": "14:00"
}' \
https://api.density.io/v2/spaces/

Example Response

{
  "id": "spc_458687913710846960",
  "name": "Kitchen",
  "notes": "",
  "meta": null,
  "space_type": "space",
  "function": null,
  "time_zone": "America/New_York",
  "daily_reset": "04:00",
  "current_count": 0,
  "capacity": null,
  "target_capacity": null,
  "safe_capacity": null,
  "safe_threshold_mode": null,
  "safe_threshold_value": null,
  "max_dwell_minutes": null,
  "parent_id": null,
  "ancestry": [],
  "address": null,
  "latitude": null,
  "longitude": null,
  "counting_mode": "doorways",
  "component_spaces": [],
  "floor_level": null,
  "space_mappings": [],
  "doorways": [],
  "tags": [],
  "time_segments": [],
  "time_segment_groups": [],
  "size_area": null,
  "size_area_unit": null,
  "annual_rent": null,
  "annual_rent_currency": "USD",
  "assigned_teams": [],
  "sensors_total": 0,
  "image_url": null,
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "description": "",
  "inherits_time_segments": false
}

Update Space

Update a space.

PUT /spaces/:space_id/

Request Body

name
string

The name of the space.

notes
string

Notes about the space.

meta
json

Free-form JSON metadata to store on the space.

time_zone
string

The timezone of the space in tzdata format.

capacity
integer

The maximum number of people that can legally occupy the space.

target_capacity
integer

The target maximum number of people occupying the space.

safe_capacity
integer

If safe_threshold_mode is set to SAFE_CAPACITY, this is the maximum number of people that can occupy the space for it to be deemed safe.

safe_threshold_mode
string

How the safe threshold is calculated. Can be SAFE_CAPACITY, UTILIZATION_PERC_LEGAl orUTILIZATION_PERC_TARGET.

safe_threshold_value
float

The proportion of the legal capacity or target capacity (depending on safe_threshold_mode), above which the space is deemed in unsafe.

daily_reset
string

A 24-hour time in the local time zone. The space's count will automatically reset to 0 at this time every day. The default daily reset time is 04:00.

space_type
string

The space type: space (default), floor, building, or campus.

function
string

The function of the space: (amenities_space, break_room, cafe, collaboration, conference_room, dining_area, event_space, focus_quiet, gym, kitchen, lab, library, lounge, meeting_room, office, phone_booth, place_of_worship, reception, restroom, retail, theater, wellness_room)

parent_id
string

The ID of the parent space if in a hierarchy.

address
string

Street address of the space.

annual_rent
float

Only allowed in spaces whose space_type is building. The rent of the building.

annual_rent_currency
string

The currency for the annual_rent number. The default is USD.

size_area
float

The area of the space.

size_area_unit
string

The unit for the size_area number. The default is square_feet.

latitude
float

Latitude for precision mapping.

longitude
float

Longitude for precision mapping.

Example Request

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "name": "Big Kitchen",
    "daily_reset": "13:00",
    "capacity": 20
}' \
https://api.density.io/v2\
/spaces/spc_458687913710846960/

Example Response

{
  "id": "spc_458687913710846960",
  "name": "Big Kitchen",
  "notes": "The Larger Office Kitchen",
  "meta": {
    "optional_meta_data": "abc123"
  },
  "description": "The Larger Office Kitchen",
  "space_type": "building",
  "function": "lab",
  "time_zone": "America/Los_Angeles",
  "daily_reset": "13:00",
  "current_count": 0,
  "capacity": 100,
  "target_capacity": 50,
  "safe_capacity": 20,
  "safe_threshold_mode": "SAFE_CAPACITY",
  "safe_threshold_value": 0.8,
  "max_dwell_minutes": 100,
  "parent_id": null,
  "ancestry": [],
  "address": null,
  "latitude": null,
  "longitude": null,
  "counting_mode": "doorways",
  "component_spaces": [],
  "floor_level": null,
  "space_mappings": [],
  "doorways": [],
  "tags": [],
  "time_segments": [],
  "time_segment_groups": [],
  "size_area": null,
  "size_area_unit": "square_feet",
  "annual_rent": 1000000.99,
  "annual_rent_currency": "USD",
  "assigned_teams": [],
  "sensors_total": 0,
  "image_url": null,
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "inherits_time_segments": false
}

Delete Space

Delete a space from your environment. If the request is successful, a 204 No Content response will be returned.

Warning: Deleting a space will destroy all historical counts for that space.

DELETE /spaces/:space_id/

Request Body

* name
required | string

The current name of the space. Must be an exact match.

Example Request

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "name": "Kitchen (Updated)"
}' \
https://api.density.io/v2\
/spaces/spc_458687913710846960/

Tag Space

Tag a space.

POST /spaces/:space_id/tags/

Request Body

* tag_name
required | string

The tag name. Alphanumeric characters, underscore or minus sign only.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "tag_name": "tech_garden"
}' \
https://api.density.io/v2/spaces/spc_452554024357462439/tags/

Example Response

{
  "tag_name": "tech_garden"
}

Untag Space

Untag a space.

DELETE /spaces/:space_id/tags/:tag_name/

Example Request

curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/tags/tech_garden/

Assign Team to Space

Assign a team to a space.

POST /spaces/:space_id/assigned_teams/

Request Body

* team_name
required | string

The team name.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "team_name": "HR"
}' \
https://api.density.io/v2/spaces/spc_452554024357462439/assigned_teams/

Example Response

{
  "id": "ast_839584474655096000",
  "team_name": "HR"
}

Remove Team from Space

Remove a team from a space.

DELETE /spaces/:space_id/assigned_teams/:assigned_team_id/

Example Request

curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/assigned_teams/ast_839584474655096000/

Doorways

Each space has one or more doorways associated with it. Each doorway is an entrance or exit where a Density sensor can be mounted to detect traffic events. A doorway can be associated with more than one space, if an interior doorway separates two spaces or if two spaces overlap.

Active doorways must have a sensor attached - this is done by setting the sensor_serial_number value on the doorway. Every active doorway has exactly one sensor attached to it.

Doorways can be organized with tags (see below).

List Doorways

List all doorways for an account.

GET /doorways/

Query String Parameters

space_id

If included, return only doorways associated with this space.

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/doorways/

Example Response

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "drw_437303389773103967",
      "sensor_serial_number": "Z458467949888405826",
      "name": "Conference Room Door",
      "spaces": [
        {
          "id": "spc_546324050188690000",
          "name": "SF Office",
          "link_id": "lnk_814175826722420000",
          "sensor_placement": 1
        }
      ],
      "tags": [
        "tech_garden"
      ],
      "created_at": "2018-09-01T17:45:13.356Z",
      "updated_at": "2018-09-01T17:45:13.356Z"
    },
    {
      "id": "drw_452554070478029236",
      "sensor_serial_number": "Z457234837531526031",
      "name": "Office Door",
      "tags": [
        "tech_garden"
      ],
      "spaces": [
        {
          "id": "spc_546324050188690001",
          "name": "NYC Office",
          "link_id": "lnk_81417582672240001",
          "sensor_placement": 1
        }
      ],
      "created_at": "2018-09-01T17:45:13.356Z",
      "updated_at": "2018-09-01T17:45:13.356Z"
    }
  ],
}

Create Doorway

Add a new doorway to your environment.

POST /doorways/

Request Body

* name
required | string

A unique name for the doorway.

description
string

A description for the doorway.

sensor_serial_number
string

The serial_number of the sensor attached to this doorway, if any.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "name": "Kitchen Door",
    "description": "The doorway to the Kitchen"
}' \
https://api.density.io/v2/doorways/

Example Response

{
  "id": "drw_458687903724209131",
  "sensor_serial_number": null,
  "name": "Kitchen Door",
  "description": "The doorway to the Kitchen",
  "spaces": [],
  "tags": [],
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "multipoint": false
}

Get Doorway

Detailed information about a doorway. The spaces array is a summary of the spaces associated with this doorway. Each association in this array also has a sensor_placement used to configure complex environments. The sensor_placement will be 1 if the sensor is mounted on the inside of the space, and -1 if it is mounted on the outside. Note that a sensor should never be mounted outdoors.

GET /doorways/:doorway_id/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_437303389773103967/

Example Response

{
  "id": "drw_437303389773103967",
  "sensor_serial_number": "Z458467949888405826",
  "name": "Conference Room Door",
  "description": "The doorway to the Conference Room (inside the Office)",
  "spaces": [
    {
      "id": "spc_439805443284402880",
      "name": "Conference Room",
      "sensor_placement": 1
    }
  ],
  "tags": [
    "tech_garden"
  ],
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "multipoint": false
}

Update Doorway

Update a doorway.

PUT /doorways/:doorway_id/

Request Body

name
string

A unique name for the doorway.

description
string

A description for the doorway.

sensor_serial_number
string

The serial_number of the sensor attached to this doorway, if any.

Example Request

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "name": "Conference Room Door (Updated)"
}' \
https://api.density.io/v2\
/doorways/drw_437303389773103967/

Example Response

{
  "id": "drw_437303389773103967",
  "sensor_serial_number": "Z458467949888405826",
  "name": "Conference Room Door (Updated)",
  "description": "The doorway to the Conference Room (inside the Office)",
  "spaces": [
    {
      "id": "spc_439805443284402880",
      "name": "Conference Room",
      "sensor_placement": 1
    }
  ],
  "tags": [
    "tech_garden"
  ],
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z",
  "multipoint": false
}

Delete Doorway

Delete a doorway from your environment.

DELETE /doorways/:doorway_id/

Example Request

curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_458687903724209131/

Tag Doorway

Tag a doorway.

POST /doorways/:doorway_id/tags/

Request Body

* tag_name
required | string

The tag name. Alphanumeric characters, underscore or minus sign only.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "tag_name": "tech_garden"
}' \
https://api.density.io/v2\
/doorways/drw_437303389773103967/tags/

Example Response

{
  "tag_name": "tech_garden"
}

Untag Doorway

Untag a doorway.

DELETE /doorways/:doorway_id/tags/:tag_name/

Example Request

curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_437303389773103967/tags/tech_garden/

Tags

A tag is a text slug (alphanumeric, dash, or underscore only) that can be added to any space or doorway. Tags provide an easy mechanism for filtering and organizing spaces and doorways.

To tag or untag a space or doorway, use the endpoints in the space and doorway sections above.

List Tags

Index of all tags for an account.

GET /tags/

Example Request

$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \ 
  https://api.density.io/v2/tags/

Example Response

{
  "total": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "name": "tech_garden"
    },
    {
      "name": "real_estate"
    }
  ]
}

Get Tag

List all spaces and doorways for a single tag. Note that additional details must be queried for each individual item.

GET /tags/:tag_name/

Example Request

$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  https://api.density.io/v2/tags/tech_garden/

Example Response

{
  "name": "tech_garden",
  "spaces": [
    {
      "id": "spc_439805443284402880",
      "name": "Conference Room",
      "current_count": 3
    },
    {
      "id": "spc_452554024357462439",
      "name": "Office",
      "current_count": 7
    },
    {
      "id": "spc_458687913710846960",
      "name": "Kitchen (Updated)",
      "current_count": 1
    }
  ],
  "doorways": [
    {
      "id": "drw_437303389773103967",
      "name": "Conference Room Door (Updated)"
    },
    {
      "id": "drw_452554070478029236",
      "name": "Office Door"
    },
    {
      "id": "drw_458687903724209131",
      "name": "Kitchen Door"
    }
  ]
}

Time Segments

A time segment is a named timeframe that occurs between set start and stop times on the selected days of the week. Time segments can be linked to one or more spaces. Time segments are inherited: if a parent space is linked to a time segment, all of its children spaces are also linked to that time segment.

The start and end times will be converted to each space's timezone when being used to filter events and counts.

List Time Segments

Returns all time segments that exist for your account.

GET /time_segments/

Example Request

$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  https://api.density.io/v2/time_segments/

Example Response

{
    "total": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "tsm_579017521479286820",
            "label": "Early Lunch",
            "start": "11:00:00",
            "end": "12:00:00",
            "spaces": [
                {
                    "space_id": "spc_578330564667375651",
                    "name": "Downstairs Kitchen"
                }
            ],
            "days": [
                "Monday",
                "Wednesday",
                "Friday"
            ]
        },
        {
            "id": "tsm_578329221793841160",
            "label": "Late Lunch",
            "start": "12:00:00",
            "end": "13:00:00",
            "spaces": [
                {
                    "space_id": "spc_578329003530649603",
                    "name": "Main Cafe"
                }
            ],
            "days": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday"
            ]
        }
    ]
}

Get Time Segment

Detail information about a time segment.

GET /time_segments/

Example Request

$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  https://api.density.io/v2/time_segments/tsm_579017521479286820

Example Response

{

"id": "tsm_579017521479286820",
"label": "Early Lunch",
"start": "11:00:00",
"end": "12:00:00",
"spaces": [
    {
        "space_id": "spc_578330564667375651",
        "name": "Downstairs Kitchen"
    }
],
"days": [
    "Monday",
    "Wednesday",
    "Friday"
            ]
}

Create Time Segment

Add a new time segment to your organization. Returns the resulting time segment object with its assigned ID.

POST /time_segments/:time_segment_id

Request Body

* label
required | string

The name of the time segment.

* start
required | string

A 24-hour time in the local time zone. This is the time of day the segment starts.

* end
required | string

A 24-hour time in the local time zone. This is the time of day the segment ends.

* days
required | array

Days of the week that the time segment is "on". Must be capitalized.

* spaces
required | array

List of existing space IDs to connect with this time segment.

Example Request

curl --request POST \
  -H 'authorization: Bearer YOUR_API_TOKEN' \
  -H 'content-type: application/json' \
  -d '{
  "label": "Early Lunch",
  "start": "11:00:00",
  "end": "12:00:00",
  "days": [
    "Monday",
    "Wednesday",
    "Friday"
  ],
  "spaces": [
    "spc_578330564667375651"
  ]
}' \
http://api.density.io/v2/time_segments/

Example Response

{
  "id": "tsm_579017521479286820",
  "label": "Early Lunch",
  "start": "11:00:00",
  "end": "12:00:00",
  "spaces": [
    {
      "space_id": "spc_578330564667375651",
      "name": "Downstairs Kitchen"
    }
  ],
  "days": [
    "Monday",
    "Wednesday",
    "Friday"
  ]
}

Update Time Segment

Update an existing time segment.

PUT /time_segments/:time_segment_id/

Request Body

label
string

The name of the time segment.

start
string

A 24-hour time in the local time zone. This is the time of day the segment starts.

end
string

A 24-hour time in the local time zone. This is the time of day the segment ends.

days
array

Days of the week that the time segment is "on". Must be capitalized.

spaces
array

List of existing space IDs to connect with this time segment.

Example Request

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
  "label": "Early Lunch on Weekends",
  "days": [
    "Sunday",
    "Saturday"
  ]
}' \
https://api.density.io/v2\
/time_segments/tsm_579017521479286820/

Example Response

{
  "id": "tsm_579017521479286820",
  "label": "Early Lunch on Weekends",
  "start": "11:00:00",
  "end": "12:00:00",
  "spaces": [
    {
      "space_id": "spc_578330564667375651",
      "name": "Downstairs Kitchen"
    }
  ],
  "days": [
    "Sunday",
    "Saturday"
  ]
}

Delete Time Segment

Delete a time segment.

Warning: This action cannot be undone

DELETE /time_segments/:time_segment_id/

Example Request

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/time_segments/tsm_579017521479286820/

Sensors

A Density sensor is the physical hardware module that is mounted above a doorway. Each active doorway must have a sensor associated with it. Density sensors will be automatically updated with their current status.

List Sensors

List sensors in your environment.

GET /sensors/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/sensors/

Example Response

{
  "total": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "uuid": "50d76b5a-98a2-4d73-8032-b772dc469bf3",
      "organization_id": "org_241255233743740000",
      "serial_number": "Z458914847325684272",
      "doorway_id": "drw_458687903724209131",
      "doorway_name": "Conference Room Door",
      "sensor_type": "s5",
      "status": "online",
      "last_heartbeat": "2016-09-19T15:45:00",
      "current_disposition": "LIVE",
      "network_addresses": [
          {
              "if": "wlan0",
              "family": "ipv4",
              "mac": "88:3f:4a:00:00:01",
              "address": "192.168.1.7"
          }
      ],
      "firmware_version": "6966-35a94c6-shiny-tracking-engine-s5_1g-internal",
      "created_at": "2018-09-01T17:45:13.356Z",
      "updated_at": "2018-09-01T17:45:13.356Z"
    },
    {
      "uuid": "50d76b5a-98a2-4d73-8032-b772dc469bf3",
      "organization_id": "org_241255233743740000",
      "serial_number": "A0DJZ003",
      "doorway_id": "drw_458687903724209131",
      "doorway_name": "Kitchen Door",
      "sensor_type": "s5",
      "status": "online",
      "last_heartbeat": "2016-09-19T15:45:00",
      "current_disposition": "LIVE",
      "network_addresses": [
          {
              "if": "wlan0",
              "family": "ipv4",
              "mac": "88:3f:4a:00:00:00",
              "address": "192.168.1.2"
          }
      ],
      "firmware_version": "6966-35a94c6-shiny-tracking-engine-s5_1g-internal",
      "created_at": "2018-09-01T17:45:13.356Z",
      "updated_at": "2018-09-01T17:45:13.356Z"
    }
  ]
}

Get Sensor

View the current status of a sensor.

GET /sensors/:serial_number/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/sensors/Z458914847325684272/

Example Response

{
  "uuid": "50d76b5a-98a2-4d73-8032-b772dc469bf3",
  "organization_id": "org_241255233743740000",
  "doorway_id": "drw_458687903724209131",
  "doorway_name": "Kitchen Door",
  "sensor_type": "s5",
  "status": "online",
  "last_heartbeat": "2016-09-19T15:45:00",
  "current_disposition": "LIVE",
  "network_addresses": [
      {
          "if": "wlan0",
          "family": "ipv4",
          "mac": "88:3f:4a:00:00:00",
          "address": "192.168.1.2"
      }
  ],
  "firmware_version": "6966-35a94c6-shiny-tracking-engine-s5_1g-internal",
  "created_at": "2018-09-01T17:45:13.356Z",
  "updated_at": "2018-09-01T17:45:13.356Z"
}

Webhooks

A webhook subscription allows you to receive a callback to a specified endpoint on your own server. Density webhooks will be triggered after every event we receive from any of your sensors (called a count event), or a tailgating event.

If a sensor is tied to multiple spaces, you will receive an event for each space.

List Webhooks

List webhooks in your environment.

GET /webhooks/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/webhooks/

Example Response

{
    "total": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "whk_579139973911937061",
            "name": null,
            "description": null,
            "endpoint": "https://example.com/some-action/",
            "version": "v2",
            "headers": {},
            "enabled": true,
            "type": "counts"
        }
    ]
}]
}

Create Webhook

Add a new webhook to your environment.

POST /webhooks/

Request Body

* endpoint
required | string

The URL to which Density will send event data.

headers
array

An object containing header/value pairs used when POSTing.

name
string

The name of this webhook.

description
string

The description of this webhook.

Example Request

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "endpoint": "https://your-website.com/webhook_action/",
    "headers": {
        "Authorization": "Bearer xyzzy"
    }
}' \
https://api.density.io/v2/webhooks/

Example Response

{
    "id": "whk_579141278554390567",
    "name": null,
    "description": null,
    "endpoint": "https://your-website.com/webhook_action/",
    "version": "v2",
    "headers": {
        "Authorization": "Bearer xyzzy"
    }
}

Get Webhook

Detailed information about a webhook.

GET /webhooks/:webhook_id/

Example Request

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/webhooks/whk_579141278554390567/

Example Response

{
    "id": "whk_579141278554390567",
    "name": null,
    "description": null,
    "endpoint": "https://your-website.com/webhook_action/",
    "version": "v2",
    "headers": {
        "Authorization": "Bearer xyzzy"
    },
    "enabled": true,
    "type": "counts"
}

Update Webhook

Update a webhook.

PUT /webhooks/:webhook_id/

Request Body

endpoint
string

The URL to which Density will send event data.

headers
array

An object containing header/value pairs.

name
string

The name of this webhook.

description
string

The description of this webhook.

Example Request

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
    "endpoint": "https://some-website.com/other_endpoint"
}' \
https://api.density.io/v2\
/webhooks/whk_579141278554390567/

Example Response

{
    "id": "whk_579141278554390567",
    "name": null,
    "description": null,
    "endpoint": "https://your-website.com/other_endpoint/",
    "version": "v2",
    "headers": {
        "Authorization": "Bearer xyzzy"
    },
    "enabled": true,
    "type": "counts"
}
}

Delete Webhook

Delete a webhook from your environment.

DELETE /webhooks/:webhook_id/

Example Request

curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/webhooks/whk_458914869530329656/

Webhook Payload (Count)

When a count event is POSTed to your webhook, the JSON data will resemble the space and sensor events in previous sections. It will have additional information: the current count for the associated space and the ID of the space itself. The direction field will be 1 for entrance, -1 for exit.

If any additional headers are configured for the webhook, they will be included with the POST request.

Example of Webhook Data Received

A single event occurring at a doorway connected to two spaces

{
  "timestamp": "2018-09-19T01:02:03.001Z",
  "space_id": "spc_439805443284402880",
  "doorway_id": "drw_437303389773103967",
  "org_id": "org_123",
  "org_name": "Density",
  "direction": 1,
  "count": 32
}
{
  "timestamp": "2018-09-19T01:02:03.001Z",
  "space_id": "spc_439805443284402881",
  "doorway_id": "drw_437303389773103967",
  "org_id": "org_123",
  "org_name": "Density",
  "direction": -1,
  "count": 104
}

Webhook Payload (Tailgating)

When a tailgating event is POSTed to your webhook, the JSON data will resemble the following. It will have the doorway_id and the serial_number of the sensor at that doorway.

If any additional headers are configured for the webhook, they will be included with the POST request.

Example of Tailgating Webhook Data Received

{
  "timestamp": "2018-09-19T01:02:03.001Z",
  "doorway_id": "drw_437303389773103967",
  "serial_number": "Z458914847325684272"

}

Websockets

Using Density for a real-time use-case is easy with websockets. Websockets allow you to open a secure connection to our server and stream count data and events (entrances and exits) in real-time to your application.

This approach is the preferred method versus polling the API every few seconds.

Connecting to our websocket server is a two-step process.

  1. Obtain a secure Websocket URL from our API
  2. Connect to the Websocket stream from your client

Connecting

Create a new websocket connection. The ttl indicates how long the new socket URL is valid. In this case, the socket connection must be opened in the next 5 minutes (300 seconds).

POST /sockets

Example Request

curl -X POST -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/sockets

Example Response

{ 
    "url":"wss://sockets.density.io:8443/v2/?code=skc_fQhnu2a",
    "ttl":300
}

Streaming Websockets

There are a number of open-source clients that manage websocket connections. Here are some that we recommend:

Websocket events are in the following JSON format:

Example Response

{
  "payload": {
    "count": 0,
    "direction": -1,
    "event_id": "evt_643916192641188838",
    "space_id": "spc_578610575982985330",
    "timestamp": "2019-03-18T20:53:03.647Z",
    "type": "count"
  },
  "request_id": "5245250ce4a447e18f513b1863c80ea0",
  "version": "v2"
}