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.
https://api.density.io/v2
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.
Authorization: Bearer YOUR_API_TOKEN
Density endpoints use standard HTTP error codes. The response includes any additional information about the error.
The request sent to the API is invalid. Additional information will be returned in the response body.
The client is not allowed to perform this request. Can be caused by a missing or invalid API token.
The requested resource does not exist.
The request conflicts with another request.
The user has sent many requests in a given amount of time (see rate limit)
Density API services are rate limited to prevent unintentional abuse of our service and ensure a reliable experience for all our developers and integrations. The API is limited to 60 requests per minute, per token, evaluated each minute.
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
.
If included, the endpoint will return a particular page of data.
If included, the endpoint will return pages of this size. The maximum page size is 1000.
$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/spaces/?page=4&page_size=15
{
"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": [
…
]
}
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.
2016-05-23T10:00:00.000Z
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.
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/
If included, return only spaces associated with this doorway.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/spaces/
{
"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
}
]
}
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/
Sample counts starting at this timestamp. Must be formatted as an ISO 8601 UTC timestamp.
Sample counts until just before this timestamp. Must be formatted as an ISO 8601 UTC timestamp.
If present, sample counts at this interval. Must be a non-zero, positive integer followed by s
(seconds), m
(minutes), h
(hours), d
(days), or w
(weeks). We currently support the following durations: 1 minute, 5 minutes, 10 minutes, 15 minutes, 1 hour, 1 day, 1 week, or 1 month
Order the count samples in ascending or descending chronological order.
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
{
"total": 2,
"next": null,
"previous": null,
"metrics": {
"entrances": {
"total": 40,
"average": 1.5,
"peak": {
"value": 6,
"timestamp": "2020-08-30T20:00:00+00:00"
}
},
"exits": {
"total": 38,
"average": 1.5,
"peak": {
"value": 6,
"timestamp": "2020-08-30T20:00:00+00:00"
}
},
"count": {
"average": 1.1,
"min": {
"value": 0,
"timestamp": "2020-08-31T08:00:00+00:00"
},
"max": {
"value": 3,
"timestamp": "2020-08-31T15:00:00+00:00"
}
},
"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+00:00",
"count": 0,
"interval": {
"start": "2020-08-30T15:00:00+00:00",
"end": "2020-08-30T15:59:59.999999+00:00",
"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+00:00",
"count": 0,
"interval": {
"start": "2020-08-30T16:00:00+00:00",
"end": "2020-08-30T16:59:59.999999+00:00",
"analytics": {
"min": 0,
"max": 1,
"events": 10,
"entrances": 5,
"exits": 5,
"utilization": null,
"target_utilization": null,
"entry_rate": 0.1,
"exit_rate": 0.1
}
}
}
]
}
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 traffic starting at this time. Must be formatted as an ISO 8601 UTC timestamp.
Query traffic until this time. Must be formatted as an ISO 8601 UTC timestamp.
Query only traffic through this doorway.
Order the traffic events in ascending or descending chronological order.
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
{
"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
},
...
]
}
This section describes common use cases and the API calls used to query the appropriate data.
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.
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
{
"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
}
}
},
....
]
}
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.
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
{
"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
}
}
},
...
]
}
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 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/
The earliest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.
The latest timestamp to include. Should be formatted as an ISO 8601 UTC timestamp.
Order the sensor events in ascending or descending chronological order.
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
{
"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
}
]
}
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
:
Possible values for function
:
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:
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
fieldUTILIZATION_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 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/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/
{
"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
}
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/
The name of the space.
Notes about the space.
Free-form JSON metadata to store on the space.
The timezone of the space in tzdata format.
The maximum number of people that can legally occupy the space.
The target maximum number of people occupying the space.
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.
How the safe threshold is calculated. Can be SAFE_CAPACITY
, UTILIZATION_PERC_LEGAl
orUTILIZATION_PERC_TARGET
.
The proportion of the legal capacity or target capacity (depending on safe_threshold_mode), above which the space is deemed in unsafe.
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.
The space type: space (default), floor, building, or campus.
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
)
The ID of the parent space if in a hierarchy.
Street address of the space.
Only allowed in spaces whose space_type
is building
. The rent of the building.
The currency for the annual_rent number. The default is USD
.
The area of the space.
The unit for the size_area number. The default is square_feet
.
Latitude for precision mapping.
Longitude for precision mapping.
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/
{
"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 a space.
PUT /spaces/:space_id/
The name of the space.
Notes about the space.
Free-form JSON metadata to store on the space.
The timezone of the space in tzdata format.
The maximum number of people that can legally occupy the space.
The target maximum number of people occupying the space.
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.
How the safe threshold is calculated. Can be SAFE_CAPACITY
, UTILIZATION_PERC_LEGAl
orUTILIZATION_PERC_TARGET
.
The proportion of the legal capacity or target capacity (depending on safe_threshold_mode), above which the space is deemed in unsafe.
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.
The space type: space (default), floor, building, or campus.
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
)
The ID of the parent space if in a hierarchy.
Street address of the space.
Only allowed in spaces whose space_type
is building
. The rent of the building.
The currency for the annual_rent number. The default is USD
.
The area of the space.
The unit for the size_area number. The default is square_feet
.
Latitude for precision mapping.
Longitude for precision mapping.
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/
{
"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 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/
The current name of the space. Must be an exact match.
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 a space.
POST /spaces/:space_id/tags/
The tag name. Alphanumeric characters, underscore or minus sign only.
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/
{
"tag_name": "tech_garden"
}
Untag a space.
DELETE /spaces/:space_id/tags/:tag_name/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/tags/tech_garden/
Assign a team to a space.
POST /spaces/:space_id/assigned_teams/
The team name.
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/
{
"id": "ast_839584474655096000",
"team_name": "HR"
}
Remove a team from a space.
DELETE /spaces/:space_id/assigned_teams/:assigned_team_id/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/spaces/spc_452554024357462439/assigned_teams/ast_839584474655096000/
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 all doorways for an account.
GET /doorways/
If included, return only doorways associated with this space.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/doorways/
{
"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"
}
],
}
Add a new doorway to your environment.
POST /doorways/
A unique name for the doorway.
A description for the doorway.
The serial_number
of the sensor attached to this doorway, if any.
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/
{
"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
}
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/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_437303389773103967/
{
"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 a doorway.
PUT /doorways/:doorway_id/
A unique name for the doorway.
A description for the doorway.
The serial_number
of the sensor attached to this doorway, if any.
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/
{
"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 a doorway from your environment.
DELETE /doorways/:doorway_id/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_458687903724209131/
Tag a doorway.
POST /doorways/:doorway_id/tags/
The tag name. Alphanumeric characters, underscore or minus sign only.
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/
{
"tag_name": "tech_garden"
}
Untag a doorway.
DELETE /doorways/:doorway_id/tags/:tag_name/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/doorways/drw_437303389773103967/tags/tech_garden/
Before a space can be updated by real-time events, it must be associated with at least one doorway. A Density link represents an association between a space and a doorway. The space to doorway relationsip is many-to-many, so space can be linked to more than one doorway, and a doorway can be linked to more than one space. Each link has a sensor_placement
value set to 1
(if the sensor is mounted inside this space) or -1
(if the sensor is mounted outside this space).
Links are immutable and cannot be updated once created. To reconfigure spaces and doorways, first delete the old links, then create new links with the new configuration.
All space types can be linked with doorways except campus
.
Index of all links between spaces and doorways in your environment.
GET /links/
If present, only show links to this space.
If present, only show links to this doorway.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/links/
{
"total": 2,
"next": null,
"previous": null,
"results": [
{
"id": "lnk_456547828936737752",
"space_id": "spc_439805443284402880",
"doorway_id": "drw_437303389773103967",
"space_name": "Conference Room",
"doorway_name": "Conference Room Door",
"sensor_placement": 1,
"created_at": "2018-09-01T17:45:13.356Z"
},
{
"id": "lnk_456547824910205905",
"space_id": "spc_452554024357462439",
"doorway_id": "drw_452554070478029236",
"space_name": "Office",
"doorway_name": "Office Door",
"sensor_placement": 1,
"created_at": "2018-09-01T17:45:13.356Z"
}
]
}
Link a space to a doorway.
POST /links/
The id
of the space.
The id
of the doorway.
Must be 1
if the sensor is mounted inside this space, or -1
if the sensor is mounted outside this space.
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"space_id": "spc_458687913710846960",
"doorway_id": "drw_458687903724209131",
"sensor_placement": 1
}' \
https://api.density.io/v2/links/
{
"id": "lnk_458691022738686632",
"space_id": "spc_458687913710846960",
"doorway_id": "drw_458687903724209131",
"space_name": "Kitchen (Updated)",
"doorway_name": "Kitchen Door",
"sensor_placement": 1,
"created_at": "2018-09-01T17:45:13.356Z"
}
Un-link a doorway from a space. Note that a space must be linked to at least one doorway in order to be updated by real-time events.
DELETE /links/:link_id/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/links/lnk_456547828936737752/
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.
Index of all tags for an account.
GET /tags/
$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/tags/
{
"total": 1,
"next": null,
"previous": null,
"results": [
{
"name": "tech_garden"
},
{
"name": "real_estate"
}
]
}
List all spaces and doorways for a single tag. Note that additional details must be queried for each individual item.
GET /tags/:tag_name/
$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/tags/tech_garden/
{
"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"
}
]
}
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.
Returns all time segments that exist for your account.
GET /time_segments/
$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/time_segments/
{
"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"
]
}
]
}
Detail information about a time segment.
GET /time_segments/
$ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/time_segments/tsm_579017521479286820
{
"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"
]
}
Add a new time segment to your organization. Returns the resulting time segment object with its assigned ID.
POST /time_segments/:time_segment_id
The name of the time segment.
A 24-hour time in the local time zone. This is the time of day the segment starts.
A 24-hour time in the local time zone. This is the time of day the segment ends.
Days of the week that the time segment is "on". Must be capitalized.
List of existing space IDs to connect with this time segment.
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/
{
"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 an existing time segment.
PUT /time_segments/:time_segment_id/
The name of the time segment.
A 24-hour time in the local time zone. This is the time of day the segment starts.
A 24-hour time in the local time zone. This is the time of day the segment ends.
Days of the week that the time segment is "on". Must be capitalized.
List of existing space IDs to connect with this time segment.
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/
{
"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 a time segment.
Warning: This action cannot be undone
DELETE /time_segments/:time_segment_id/
curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/time_segments/tsm_579017521479286820/
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 in your environment.
GET /sensors/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/sensors/
{
"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"
}
]
}
View the current status of a sensor.
GET /sensors/:serial_number/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/sensors/Z458914847325684272/
{
"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"
}
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).
If a sensor is tied to multiple spaces, you will receive an event for each space.
List webhooks in your environment.
GET /webhooks/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/webhooks/
{
"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"
}
]
}
Add a new webhook to your environment.
POST /webhooks/
The URL to which Density will send event data.
An object containing header/value pairs used when POSTing.
The name of this webhook.
The description of this webhook.
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/
{
"id": "whk_579141278554390567",
"name": null,
"description": null,
"endpoint": "https://your-website.com/webhook_action/",
"version": "v2",
"headers": {
"Authorization": "Bearer xyzzy"
}
}
Detailed information about a webhook.
GET /webhooks/:webhook_id/
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/webhooks/whk_579141278554390567/
{
"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 a webhook.
PUT /webhooks/:webhook_id/
The URL to which Density will send event data.
An object containing header/value pairs.
The name of this webhook.
The description of this webhook.
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/
{
"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 a webhook from your environment.
DELETE /webhooks/:webhook_id/
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2\
/webhooks/whk_458914869530329656/
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.
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",
"organization_id": "org_123",
"organization_name": "Density",
"direction": 1,
"count": 32
}
{
"timestamp": "2018-09-19T01:02:03.001Z",
"space_id": "spc_439805443284402881",
"doorway_id": "drw_437303389773103967",
"organization_id": "org_123",
"organization_name": "Density",
"direction": -1,
"count": 104
}
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.
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
curl -X POST -H "Authorization: Bearer YOUR_API_TOKEN" \
https://api.density.io/v2/sockets
{
"url":"wss://sockets.density.io:8443/v2/?code=skc_fQhnu2a",
"ttl":300
}
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:
{
"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"
}