NAV Navbar
  • Introduction
  • Authentication
  • Model
  • Haystack Operations
  • Errors
  • Introduction

    Current's Haystack API for integration with Building Analytics products uses the Project Haystack specification for a tag-based RESTful HTTP API. This document contains a description of the API features available in this API. Where appropriate, references will be made to the Project Haystack specification to clarify format or function.

    Please set the Haystack base URL to use the following examples:


    Revision History


    To get an access token and store it as an environment variable, use this code:

    export token=`curl -k -d "grant_type=client_credentials" -u "sandbox-client:sandbox-secret" | 
      sed 's/.*access_token\":\"//; s/\",\"token_type.*//'`

    Make sure to replace sandbox-client and sandbox-secret with your client name and client secret.

    Access to Current's Haystack API is authenticated via an OAuth2 authentication framework. This framework delegates the authentication to an external entity. Once authenticated, roles and permissions are provided by an authorisation server.

    Current's Haystack API expects the access token to be included in all API requests to the server in a header that look like the following:

    Authorization: Bearer $token

    Once generated access tokens are valid for 12 hours.


    Please read the Project Haystack documentation on the TagModel used in the Haystack API. The TagModel is used to model sites and the equipment in them. It is a fundamental concept that needs to be understood to use the Haystack API.


    Current's Haystack API uses the following entities to model buildings:

    Entity Description
    region The region tag is not specified in Project Haystack, but is commonly used to define a collection of site. It may be reflect government-administrative collections (counties, states, etc.) or commonly-used geographical collections (south-east, north-west) or any arbitrary user-specific administrative collections ("California Operations", "North-West Efficiency Initiative").
    site Building or other type of facility with unique street address.
    space A logical space within a building, e.g. "floor 1" or "kitchen".
    equip Equipment or an asset being controlled or monitored in a site. Examples of equipment including lighting groups and HVAC zones.
    point Points are typically a digital or analog sensor or actuator entity (sometimes called hard points). Points can also represent a configuration value such as a setpoint or schedule log (sometimes called soft points). Point entities are tagged with the point tag.
    device Models a physical device. In Current's Haystack implementation this is most commmonly a ZigBee device or a gateway that manages multiple devices.
    physical point The raw data reported by a device. Has both the point and physical marker tags.

    The following diagram shows the relationships between entities supported in the Haystack API: alt text


    A tag is a name/value pair applied to an entity. A tag defines a fact or attribute about an entity. For example if we apply the site tag to an entity, then we are declaring that the entity represents a building. If we also add the geoAddr tag we are declaring the street address of the building.

    A marker tag is a tag that does not have a value and is used to describe a fact about an entity.

    Project Haystack defines a large number of tags that can be applied to entities. The following tables describe marker tags and marker tag combinations are commonly used in Current's Haystack implementaiton:

    Equip Tags

    The following marker tags can be present on equip entities:

    Marker Tag Meaning
    lightsGroup The lightsGroup is a collection of lights that are controlled as a collective - a single control strategy and schedule is applied for all lights within the lightsGroup, which may consist of one or more wireless devices controlling one or more lights each.
    hvac Associated with HVAC (Heating, Ventilating, Air Conditioning)
    sensor Area or space being monitored with sensors

    Point Tags

    The following marker tags can be present on point entities:

    Marker Tag Kind Unit Equip/Device Meaning
    lights, cmd boolean none equip Zone's on/off light state
    lights, ovr boolean none equip Zone's lighting state override
    lights, cmd  number percentage  equip Zone's light level intensity (%)
    lights, ovr boolean  none  equip Zone's light intensity override
    occupancyIndicator, sensor boolean none  equip Zone's occupancy state
    occupancyIndicator, sensor, physical boolean none  device Device's occupancy state
    temp, sensor, physical number celsius device Temperature
    temp, sensor, outside, physical number celsius device Outside Temperature
    temp, sensor, physical number celsius device Cooler Temperature
    temp, sensor, physical number celsius device Freezer Temperature
    temp, sensor, mixed, air, physical number celsius device Duct Mixed Air Temperature
    temp, sensor, discharge, air, physical number celsius device Duct Supply Air Temperature
    temp, sensor, return, air, physical number celsius device Duct Return Air Temperature
    temp, sensor, zone number celsius device Space Remote Temperature
    heat, stage1, physical boolean none device HVAC system's heating stage 1 is active
    heat, stage2, physical boolean none device HVAC system's heating stage 2 is active
    heat, stage3, physical boolean none device HVAC system's heating stage 3 is active
    cool, stage1, physical boolean none device HVAC system's cooling stage 1 is active
    cool, stage2, physical boolean none device HVAC system's cooling stage 2 is active
    fan, cmd, physical boolean none device Fan State
    temp, zone aggregated, sensor number celsius equip Thermostat Temperature
    sp, cooling, zone, temp number celsius equip Cooling Setpoint
    sp, heating, zone, temp number celsius equip Heating Setpoint
    ovr, temp, zone, cooling number boolean equip Cooling Setpoint Override
    ovr, temp, zone, heating number boolean equip Heating Setpoint Override
    energy, supply, sensor number kWh equip Supply Energy
    energy, demand, sensor number kWh equip Generic Demand Energy
    energy, demand, sensor, lighting number kWh equip Lighting Demand Energy
    energy, demand, sensor, gas number kWh equip Gas Heating Demand Energy
    energy, demand, sensor, elec number kWh equip Electric Heating Demand Energy
    energy, demand, sensor, cooling number kWh equip Cooling Demand Energy
    energy, demand, sensor, fan number kWh equip Fan Demand Energy
    - number kW equip Instantaneous Energy Demand
    sensor, faultStat boolean none equip Zone's fault status. True if one or more devices in the zone has an equipment fault. Note: Only supported for a small subset of devices.
    sensor, commsStat boolean none equip Zone's communication's status. False if one or more devices in the zone has communciations errors.
    occupantCountIndicator, sensor number none equip Zone's people count
    commStatus boolean none equip A value of 'false' indicates a communication a device associated with this equipment has communication issues
    commStatus boolean none gateway device A value of 'false' indicates that the gateway is disconnected from the IoT gateway cloud service. While a gateway is disconnected time-series events will be stored by the gateway until it can reconnect to the IoT Gateway.
    cpuLoad number none gateway device The CPU load of the gateway. This event is published every 5 minutes.
    analogInput number none device Value between 0 and 65,535 representing the value of a 0-10V analog input
    analogOutput number none device Value between 0 and 65,535 representing the value of a 0-10V analog output.
    binaryInput boolean none device A true/false value representing a the state of a general purpose binary input.
    binaryOutput boolean none device A true/false value representing a the state of a general purpose binary output.

    ControlScope and Device Profile

    ControlScope's Device Profile capability allows you to create your own custom device types for analog and binary I/O. The user defined Type field is converted to a tag. This can make it easier to filter and find data from your custom device type.

    For example if your ControlScope site included a Device Profile with the Water Leak Detector type then in the Haystack API devices that are assigned this Device Profile would would have a waterLeakDector tag.

    The raw time-series data is recorded by the Haystack API. You will need to apply the mapping function defined in the Device Profile in your API client.

    Device Tags

    The following tags can be present on device entities:

    Tag Meaning
    gateway Device entities that have this marker tag are gateways, e.g. a WAC60.
    ieeeAddress The device's unique IEEE Address (which is sometimes referred to as an EUI64).

    Reference Tags

    The following tags are used by entities to reference other entities:

    Reference Tag Meaning
    regionRef A reference to the region the entity is in.
    siteRef A reference to the site the entity is in.
    spaceRef A reference to a space. Spaces can reference other spaces. Equip can reference spaces too.
    parentDeviceRef Devices that are managed by a gateway will have a reference back to their gateway
    deviceRef Physical points have a reference back to their device.
    externalRefIds All entities can have a list of external references.
    equipRef Points have a refence to their equipment
    equipRefIds A list of equipment physical points are associated with

    Haystack Operations


    To use about:

      curl -X GET --header "Authorization: Bearer $token" "https://$hs/about"

    The about operation returns ZINC structured like this:

    ``,"UTC","v1-pds-haystack-service-556f89bbbd-z2hl4","Current Haystack Server","3.0","1.0.0-rc.1",2019-03-12T02:30:29.437Z UTC,2019-03-08T06:01:22.355Z UTC

    The about operation queries basic information about the server.

    HTTP Request

    GET https://$hs/about


    No query parameters


    A single row grid with following columns:

    Parameter Description
    haystackVersion String version of REST implementation, must be "3.0"
    tz String of server's default timezone
    serverName String name of the server or project database
    serverTime Current DateTime of server's clock
    serverBootTime DateTime when server was booted up
    productName String name of the server software product
    productUri URI of the product's web site
    productVersion String version of the server software product


    Example of how to use curRead to read the most recent value for multiple points:

    curl -v -X GET --header "Authorization: Bearer $token" "https://$hs/curRead?id=@2883cde7-f922-4118-97ca-1c9aa3231cca,@e8040771-ab06-4d02-814d-9313fb0dd855,@124280c8-96c5-4194-a62a-d29b46821982"

    Response from the above query:

    "NO_FAULT",@2883cde7-f922-4118-97ca-1c9aa3231cca,T,2019-03-11T20:07:21.621-07:00 Los_Angeles
    "NO_FAULT",@e8040771-ab06-4d02-814d-9313fb0dd855,T,2019-03-11T20:07:21.621-07:00 Los_Angeles
    "NO_FAULT",@124280c8-96c5-4194-a62a-d29b46821982,T,2019-03-11T20:07:21.621-07:00 Los_Angeles

    The curRead operation is used to read the most recent value for points that have the cur marker tag.

    This operation has been designed to return a large number of points very quickly. If you need to poll the Haystack API to retrieve the current value use the curRead operation in preference to the read operation.

    A single curRead request can return approximately 50 points when called using HTTP GET and 250 points when called using HTTP POST.

    HTTP Request

    GET https://$hs/curRead?id=<id>,<id>,...

    POST https://$hs/curRead



    A grid with a the following columns. Add a row to the grid for each data point that you wish to request.

    Parameter Description
    id Ref identifier of current value data point


    Rows of the result grid represent timetamp/value pairs with a DateTime ts column and a val column for each scalar value. In addition the grid metadata includes:

    Paramater Description
    id Ref of the point being read
    val The last value recorded
    ts The time the value was recorded
    qod Indicates whether the data is of good quality or not


    To use formats:

      curl -X GET --header "Authorization: Bearer $token" "https://$hs/formats"

    The formats operation returns ZINC structured like this:


    The formats operation is used to query which MIME types are available to read and write grids.

    HTTP Request

    GET https://$hs/formats


    No query parameters


    A grid where each row represents one supported MIME type with following columns:

    Parameter Description
    mime String MIME type encoded as "mediaType/subType", these value must not include parameters. Any "text/" media type must be be encoded using UTF-8
    receive Marker tag if server can read this format in requests (client can POST this format)
    send Marker tag if server can write this format in responses (client can request response in this format)


    Examples of how to use hisRead to read data for a single point over various time windows:

    curl -X GET --header "Authorization: Bearer $token" 'https://$hs/hisRead?id=@2883cde7-f922-4118-97ca-1c9aa3231cca&range=2019-03-05,2019-03-06'
    curl -X GET --header "Authorization: Bearer $token" 'https://$hs/hisRead?id=@2883cde7-f922-4118-97ca-1c9aa3231cca&range=today'
    curl -X GET --header "Authorization: Bearer $token" 'https://$hs/hisRead?id=@2883cde7-f922-4118-97ca-1c9aa3231cca&range=yesterday'

    An example hisRead response:

    ver:"3.0" id:@2883cde7-f922-4118-97ca-1c9aa3231cca hisStart:2019-03-05T00:00:00-08:00 Los_Angeles hisEnd:2019-03-07T00:00:00-08:00 Los_Angeles
    2019-03-05T00:00:21.621-08:00 Los_Angeles,T
    2019-03-05T00:00:51.621-08:00 Los_Angeles,F
    2019-03-05T00:01:21.621-08:00 Los_Angeles,T
    2019-03-05T00:01:51.621-08:00 Los_Angeles,F
    2019-03-05T00:02:21.621-08:00 Los_Angeles,T
    2019-03-05T00:02:51.621-08:00 Los_Angeles,F
    2019-03-05T00:03:21.621-08:00 Los_Angeles,T

    The hisRead operation is used to read time-series data from historized points.

    HTTP Request

    GET https://$hs/hisRead?id=<id>&ranges=<range>

    POST https://$hs/hisRead



    A grid with a the following columns. Add a row to the grid for each data point that you wish to request.

    Parameter Description
    id Ref identifier of historized point
    range Str encoding of a date-time range



    // request
    // reponse
    ver:"3.0" id:@2883cde7-f922-4118-97ca-1c9aa3231cca hisStart:2019-03-11T00:00:00-07:00 Los_Angeles hisEnd:2019-03-12T00:00:00-07:00 Los_Angeles
    2019-03-11T00:00:21.621-07:00 Los_Angeles,T
    2019-03-11T00:00:51.621-07:00 Los_Angeles,F
    2019-03-11T00:01:21.621-07:00 Los_Angeles,T
    2019-03-11T00:01:51.621-07:00 Los_Angeles,F
    2019-03-11T00:02:21.621-07:00 Los_Angeles,T
    2019-03-11T00:02:51.621-07:00 Los_Angeles,F
    2019-03-11T00:03:21.621-07:00 Los_Angeles,T
    2019-03-11T00:03:51.621-07:00 Los_Angeles,F
    2019-03-11T00:04:21.621-07:00 Los_Angeles,T
    2019-03-11T00:04:51.621-07:00 Los_Angeles,F
    2019-03-11T00:05:21.621-07:00 Los_Angeles,T

    Rows of the result grid represent timetamp/value pairs with a DateTime ts column and a val column for each scalar value. In addition the grid metadata includes:

    Parameter Description
    id Ref of the point we read
    hisStart DateTime timestamp for exclusive range start in point's timezone
    hisEnd DateTime timestamp for inclusive range end in point's timezone

    The range Str is formatted as one of the following options:

    Ranges are exclusive of start timestamp and inclusive of end timestamp. The {date} and {dateTime} options must be correctly Zinc encoded. DateTime based ranges must be in the same timezone of the entity (timezone conversion is explicitly disallowed). Date based ranges are always inferred to be from midnight of starting date to midnight of the day after ending date using the timezone of the his entity being queried.

    The nav operation is used navigate a project for learning and discovery. This operation allows servers to expose the database in a human-friendly tree (or graph) that can be explored.

    To use nav:

      curl -X GET --header "Authorization: Bearer $token" 

    The nav operation returns ZINC structured like this:

    "Melbourne","Melbourne",@102d6e47-309c-413a-96fe-08e6b3768eed,"44 Lakeview Drive,Scoresby,3179,AUSTRALIA","44 Lakeview Drive",@a6fface2-6de5-413f-9af4-58ecc0c592ba,"1000 square_foot","3179","a6fface2-6de5-413f-9af4-58ecc0c592ba","Scoresby",[@0a0741b8-ec9a-459a-aac5-bd4118fffc18],M,"AUSTRALIA"
    "Los_Angeles","San Ramon",@ecd60d3e-9fea-40e1-8782-53df01f7846b,"2700 Camino Ramon,San Ramon,94583,UNITED STATES","2700 Camino Ramon",@998dd578-bb4a-4004-991b-8bb7ba6aee4b,"2000 square_foot","94583","998dd578-bb4a-4004-991b-8bb7ba6aee4b","San Ramon",[@e0bbefc7-3a83-4086-99b9-c11d21ffb888],M,"UNITED STATES"

    HTTP Request

    GET https://$hs/nav


    A grid with a single row and a navId column. If the grid is empty or navId is null, then the request is for the navigation root.


    A grid of navigation children for the navId specified by the request. There is always a navId column which indicates the opaque identifier used to navigate to the next level of that row. If the navId of a row is null, then the row is a leaf item with no children.

    Navigation rows don't necessarily always correspond to records in the database. However, if the navigation row has an id column then it is safe to assume the row maps to a record in the database. Clients should treat the navId as an opaque identifier.


    The ops operation queries which operations are available on the server.

    To use ops:

      curl -X GET --header "Authorization: Bearer $token" "https://$hs/ops"

    The ops operation returns ZINC structured like this:

    "about","Summary information for server"
    "ops","Operations supported by this server"
    "formats","Grid data formats supported by this server"
    "read","Read entity records in database"
    "curRead","Read current value for a point or group of points"
    "nav","Navigate record tree"
    "hisRead","Read time series from historian"

    HTTP Request



    No query parameters


    A grid where each row represents a single operation with the following columns:

    Parameter Description
    name String name of the operation in the URI namespace
    summary String short description of the operation


    The read operation is used to read a set of entity records either by their unique identifier or using a filter.

    This operation has been designed to help a client learn the structure of the sites of interest. Once the initial structure has been learnt this operation should be called infrequently. Use the curRead operation to retrieve the current value of points.

    Examples of how to read with several different filters:

      curl -v -X GET -G --header "Authorization: Bearer $token" 'https://$hs/read' --data-urlencode 'filter=site' --data-urlencode 'limit=5'
      curl -v -X GET -G --header "Authorization: Bearer $token" 'https://$hs/read' --data-urlencode 'filter=space and siteRef->dis=="Melbourne"' --data-urlencode 'limit=5'
      curl -v -X GET -G --header "Authorization: Bearer $token" 'https://$hs/read' --data-urlencode 'filter=equip and siteRef->dis=="Melbourne"' --data-urlencode 'limit=5'
      curl -v -X GET -G --header "Authorization: Bearer $token" 'https://$hs/read' --data-urlencode 'filter=device and siteRef->dis=="Melbourne"' --data-urlencode 'limit=5'
      curl -v -X GET -G --header "Authorization: Bearer $token" 'https://$hs/read' --data-urlencode 'filter=point and siteRef->dis=="Melbourne" and occupancyIndicator' --data-urlencode 'limit=5'

    Example response


    Example of how to read by id:

    curl -v -X GET --header "Authorization: Bearer $token" "https://$hs/read?id=@2883cde7-f922-4118-97ca-1c9aa3231cca"

    Example response ver:"3.0" cur,tz,occupancyIndicator,point,dis,regionRef,his,equipRef,id,kind,siteRef,enum,externalRefIds,unit,sensor M,"Los_Angeles",M,M,"Occupancy",@ecd60d3e-9fea-40e1-8782-53df01f7846b,M,@c587e0d8-9648-42c0-99b6-869772c76e21,@2883cde7-f922-4118-97ca-1c9aa3231cca,"Bool",@998dd578-bb4a-4004-991b-8bb7ba6aee4b,"Vacant,Occupied",[@180560e8-93f1-4090-a873-6abcdfef92e2.OCCUPANCY],,M

    HTTP Request

    GET https://$hs/read?filter=<filter>&limit=<limit>

    GET https://$hs/read?id=<id1>

    Request (by filter):

    A grid with a single row and following columns:

    Parameter Description
    filter Required string encoding of filter. Refer to Project Haystack for the filter syntax.
    limit Optional number which specifies maximum number of entities to return in response. The maximum number of entities that can be returned in a single request is 20,000.

    Request (by id):

    A grid of one or more rows and one column:

    Parameter Description
    id a Ref identifier


    Example of filter read request:

    "point and siteRef==@siteA",1000

    Example of read by id with two identifiers:


    Example of a read response where the second id is not found:


    Grid with a row for each entity read. If a filter read and no matches were found this will be an empty grid with no rows. If a read by id, then each row corresponds to the request grid and its respective row ordering. If an id from the request was not found, the response includes a row of all null cells.


    Error Handling

    There are three type of errors which may occur when a client makes a request to a server:

    Network errors occur when the client cannot make a successful TCP connection to the server. This might include invalid host name, port number, or network outage. Typically these sorts of errors are raised as I/O exceptions by the client's runtime.

    HTTP errors occur when TCP connections can be successfully established, but the server cannot successfully handle the URI or request grid at the HTTP layer. The following HTTP status codes must be used in these cases:

    Error Code Meaning
    400 The client failed to specify a required header such "Content-Type"
    401 Unauthorized -- Your API key is wrong.
    403 The client is not authorized to access the op
    404 The URI does not map to a valid operation URI
    406 The client "Accept" header requested an supported MIME type
    415 The client posted the request grid using an supported MIME type
    500 Internal Server Error -- We had a problem with our server. Try again later.
    501 The HTTP method is other than "GET" or "POST"
    503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

    Request errors occur after the server has successfully read the request grid. If the server cannot fulfill the request for any reason, then it must return HTTP response code of 200 with a error grid as the body. HTTP error codes must only be used if the request grid itself cannot be read. Request errors include but are not limited to:

    Error Grid

    If a operation failed after a request grid is successfully read by a server, then the server returns an error grid. An error grid is indicated by the presence of the err marker tag in the grid metadata. All error grids must also include a dis tag in the grid metadata with a human readable descripton of the problem. If the server runtime supports stack traces, this should be reported as a multi-line string via the errTrace tag in the grid metadata.

    Example of an error grid encoded as Zinc:

    ver:"3.0" err dis:"Cannot resolve id: badId" errTrace:"UnknownRecErr: badId\n ...."

    Clients must always check for the present of the err grid marker tag to determine if the reponse is an error or a valid result.