Johnson Controls Streaming API

Your Metasys system works continuously: sensors report current conditions, algorithms make adjustments, and alarms alert operators to potential issues. Streaming is how the Metasys API provides access to these _events_ using the HTML standard [server-sent events](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) (SSE). For further information, refer to [Mozilla developer guide](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events). In this document, _Streaming_ typically refers to the Metasys feature and _stream_ refers to the concept of the HTTP connection and the flow of data. Per the standard, a server-sent event usually contains three components, separated by newline, with the last component having a second newline to mark the end of the event. ```text id: \n event: \n data: \n\n ``` | Line Prefix | Explanation | | ----------- | ------------------------------------------------------------------- | | `id` | ordering id to enable the "pick up where you left off" reconnection | | `event` | message type | | `data` | message payload as a JSON string | Example: ```text id: b6d184ee-e137-44aa-b9b1-14bc704cd25d:1\n event: hello\n data: b6d184ee-e137-44aa-b9b1-14bc704cd25d\n\n ``` ## Getting Started To get started, you first need a client. There are SSE clients available in many languages. Begin by [getting a stream](#operation/getStream). Only one stream is needed regardless of the number of subscriptions you later create. As explained in the documentation for getting a stream, the first event, `hello`, is a special event because the `data` field contains your _stream ID_. Some operations support the `METASYS-SUBSCRIBE` header which transforms them from being a single request/response operations into a streaming subscription. The value of the header is the _stream ID_ from the `data` field of the `hello` event described above. As an example, refer to the [Get Activities](#operation/getActivities) operation for more details about this technique. This technique does not apply to every operation. See each operation's description to understand its Streaming capability. Not all _event_ data is currently exposed by Streaming. Future versions of the API will add further Streaming capabilities. ## Streaming Connection Maintenance There are a few behaviors to be aware of if you want your stream to work beyond the lifetime of the access token used to [get your stream](#operation/getStream). ### Keep Events Flowing After Initial Access Token Expiration Recall that your access token has an expiration time. To keep the stream longer than the lifetime of that access token, be sure to [refresh your token](#operation/getToken) just as you would when using non-Streaming portions of the API. Not only will you get a fresh token to use, but internally, your stream expirations are updated to match the expiration time of the new token. ### Reconnect and Using the Current Access Token in Reconnect Requests The server-sent events standard has a provision for reconnecting a lost connection. Call the same [get a stream](#operation/getStream) operation but also add the `Last-Event-Id` header with the `id` of the last event received. Most clients handle this for you. Metasys continues to buffer events for at least thirty seconds after the connection failure is detected, so you can resume streams that experienced brief outages. If Metasys has cleaned up your buffer or cannot find that `id` in the recently sent buffer, you will get a 204 response per the SSE specification. Because your existing stream is not resumable, your `Last-Event-Id` is no longer valid. The recovery path is to start anew by calling [get a stream](#operation/getStream) without the `Last-Event-Id` and subscribe again to data of interest. One critical aspect of reconnect is ensuring that the reconnect request is done with the current access token. As covered by [get a stream](#operation/getStream), Streaming lets you specify the token in either the `Authorization` header or query string. This flexibility accommodates a variety of clients. For example, the web browser client, `EventSource`, does not provide access to request headers, so you have to use the query string. For `EventSource`, this however poses an issue because the reconnect attempt will be done against the original URL which has a potentially outdated access token embedded in the query string. For that reason, if you want to use a JavaScript client, consider using the open source [EventSource component](https://github.com/EventSource/eventsource). The Metasys User Interface (MUI) employs this library to workaround the limitation of the browser's `EventSource` . When using it, use the `Authorization` header instead. Keep the options object passed to the constructor so you can update the `Authorization` property when you refresh your access token. Assuming: 1. Your access token is in variable `accessToken` 1. Variable `streamingUrl` is the URL for [get a stream](#operation/getStream) ```javascript const eventSourceOptions = { headers: { Authorization: `Bearer ${accessToken}`, }, }; const eventSource = new $window.EventSourcePolyfill( streamingUrl, eventSourceOptions ); ``` Before token expiration: 1. Get a [refreshed token](#tag/authentication/operation/getToken). Behind the scenes this also refreshes you stream expirations. 1. Modify `eventSourceOptions` with new token like example below ```javascript eventSourceOptions.headers.Authorization = `Bearer ${newToken}`; ``` ### Tips For Other Client Libraries SSE clients exist in many languages. Inclusion in this section is not an endorsement; however, if you chose one of these clients, these tips may prove useful for ensuring the current token is used for reconnect. #### C# - 3ventic EventSource When using the [3ventic EventSource for C#](https://github.com/3ventic/EvtSource) you will need to use Reflection to update `Uri` which is a private field within the EventSource that contains the location to [get a stream](#operation/getStream) with the access token embedded in the query string. ```csharp public static void SetField(Object obj, String fieldName, object value) { Type type = obj.GetType(); FieldInfo field = type.GetField( fieldName, BindingFlags.NonPublic | BindingFlags.Instance ); field.SetValue(obj, value); } // example usage Reflector.SetField(eventSource, "Uri", uriWithCurrentToken); ``` #### C# - LaunchDarkly EventSource When using the [LaunchDarkly EventSource for C#](https://github.com/launchdarkly/dotnet-eventsource) you will not call the `Reset` method to attempt a reconnect. Instead, dispose of the EventSource and then create a new instance, passing the the `LastEventId` from the last message and the URL to [get a stream](#operation/getStream) with a current access token embedded as a query string parameter. ## Streaming Events The following are types of events sent by Streaming along with example `data` payloads for each: - `hello` - Indicates Streaming connection was successful. Example Data Payload ```json "b6d184ee-e137-44aa-b9b1-14bc704cd25d" ``` - `heartbeat` - Indicates Streaming connection is alive. Example Data Payload ```json "2021-02-16T16:21:10.23Z" ```

Operations 1

GET /stream Get a stream #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/johnson-controls:johnson-controls-streaming-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

johnson-controls-streaming-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Johnson Controls Streaming API
  version: Version 6 for 16.0
  x-logo:
    url: source/images/logo.svg
    href: https://jci-metasys.github.io/
  x-releases:
  - '14.0'
  - '14.1'
  - '15.0'
  - '16.0'
  x-revision: 'Commit ID: 4b227676a'
  description: 'Operations tagged streaming across 2 of this provider''s published API definitions: metasys-api-v6-16.json, johnson-controls-metasys-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://{hostname}/api/v6
  description: The base URL of all API routes
  variables:
    hostname:
      default: metasys-server.example.com
      description: This is the name of your site director device
security:
- Bearer-Authentication: []
tags:
- name: Streaming
  description: 'Your Metasys system works continuously: sensors report current conditions,

    algorithms make adjustments, and alarms alert operators to potential issues. Streaming is how the Metasys API provides access to these _events_ using the

    HTML standard

    server-sent events

    (SSE). For further information, refer to

    Mozilla developer guide. In this document, _Streaming_ typically refers to the Metasys feature and

    _stream_ refers to the concept of the HTTP connection and the flow of data. Per the standard, a server-sent event usually contains three components,

    separated by newline, with the last component having a second newline to mark

    the end of the event. ```text

    id: \n

    event: \n

    data: \n\n

    ```


    | Line Prefix | Explanation |

    | ----------- | ------------------------------------------------------------------- |

    | `id` | ordering id to enable the "pick up where you left off" reconnection |

    | `event` | message type |

    | `data` | message payload as a JSON string |


    Example:


    ```text

    id: b6d184ee-e137-44aa-b9b1-14bc704cd25d:1\n

    event: hello\n

    data: b6d184ee-e137-44aa-b9b1-14bc704cd25d\n\n

    ```


    ## Getting Started


    To get started, you first need a client. There are SSE clients available in many

    languages. Begin by getting a stream. Only one stream is needed

    regardless of the number of subscriptions you later create. As explained in the

    documentation for getting a stream, the first event, `hello`, is a special event

    because the `data` field contains your _stream ID_. Some operations support the `METASYS-SUBSCRIBE` header which transforms them

    from being a single request/response operations into a streaming subscription. The value of the header is the _stream ID_ from the `data` field of the `hello`

    event described above. As an example, refer to the

    Get Activities operation for more details about this

    technique. This technique does not apply to every operation. See each

    operation''s description to understand its Streaming capability. Not all _event_ data is currently exposed by Streaming. Future versions of the

    API will add further Streaming capabilities. ## Streaming Connection Maintenance


    There are a few behaviors to be aware of if you want your stream to work beyond

    the lifetime of the access token used to

    get your stream. ### Keep Events Flowing After Initial Access Token Expiration


    Recall that your access token has an expiration time. To keep the stream longer

    than the lifetime of that access token, be sure to

    refresh your token just as you would when using

    non-Streaming portions of the API. Not only will you get a fresh token to use,

    but internally, your stream expirations are updated to match the expiration time

    of the new token. ### Reconnect and Using the Current Access Token in Reconnect Requests


    The server-sent events standard has a provision for reconnecting a lost

    connection. Call the same get a stream operation but

    also add the `Last-Event-Id` header with the `id` of the last event received. Most clients handle this for you. Metasys continues to buffer events for at

    least thirty seconds after the connection failure is detected, so you can resume

    streams that experienced brief outages. If Metasys has cleaned up your buffer or

    cannot find that `id` in the recently sent buffer, you will get a 204 response

    per the SSE specification. Because your existing stream is not resumable, your

    `Last-Event-Id` is no longer valid. The recovery path is to start anew by

    calling get a stream without the `Last-Event-Id` and

    subscribe again to data of interest. One critical aspect of reconnect is ensuring that the reconnect request is done

    with the current access token. As covered by

    get a stream, Streaming lets you specify the token in

    either the `Authorization` header or query string. This flexibility accommodates

    a variety of clients. For example, the web browser client, `EventSource`, does

    not provide access to request headers, so you have to use the query string.'
paths:
  /stream:
    get:
      summary: Get a stream
      description: Opens or reconnects a Server Sent Event stream which is a prerequisite for subscribing to any dynamic updates
      operationId: getStream
      security:
      - Bearer-Authentication: []
      - API-Key-Authentication: []
      parameters:
      - in: header
        name: Last-Event-Id
        schema:
          type: string
        example: b6d184ee-e137-44aa-b9b1-14bc704cd25d:5
        description: Providing the ID of the last event received enables a briefly broken stream to be resumed
      responses:
        '200':
          description: 'Stream connection successful. If this was a new connection, the first

            message has an _event_ type of `hello` and a special purpose. If this

            was a reconnect attempt, the first event will be subscribed data

            updates.


            **First event explanation**<br/> _id_ - Use in the `Last-Event-Id`

            header to attempt restoration of a briefly broken connection. In the

            case of web browsers, the EventSource automatically handles this for

            you.<br/> _event_ - Conveys the type of information in the _data_ field.

            Each feature and operation within that feature has a distinct

            _event_.<br/> _data_ - Your stream ID to provide in requests for dynamic

            update subscriptions.


            **First event example**


            ```

            id: b6d184ee-e137-44aa-b9b1-14bc704cd25d:\n

            event: hello\n

            data: b6d184ee-e137-44aa-b9b1-14bc704cd25d\n\n

            ```


            _For more information about Server Sent Events (SSE), please refer to

            the [HTML

            Specification](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events\)

            and [Mozilla

            pages](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events\)_

            '
        '204':
          description: Stream reconnect failed. Please open a new stream and recreate your subscriptions.
      tags:
      - Streaming
      x-codeSamples:
      - lang: shell
        label: Shell + Curl
        source: "# To set accessToken see the Shell + Curl example for \"authentication | Request access token\"\ncurl --request GET \\\n  --url https://metasys-server.example.com/api/v6/stream \\\n  --header \"Authorization: Bearer $accessToken\""
      - lang: csharp
        label: C# + Flurl
        source: "// See CSharp + Flurl example for \"authentication | Request access token\"\n// to see how to import Flurl and set `accessToken` variable\nvar response = await \"https://metasys-server.example.com/api/v6/stream\"\n    .WithHeader(\"Authorization\", $\"Bearer {accessToken}\")\n    .GetAsync();"
      - lang: text
        label: Powershell
        source: "# To set $accessToken see the Powershell example of \"authentication | Request a token\"\nInvoke-RestMethod \"https://metasys-server.example.com/api/v6/stream\" `\n  -Headers @{\n    Authorization = \"Bearer $accessToken\"\n  }"
      - lang: text
        label: PS Metasys Rest Client
        source: '# Login with Connect-MetasysAccount first.

          # See PS Metasys Rest Client example for "authentication | Request access token".

          Invoke-MetasysMethod /stream'
      - lang: javascript
        label: Node + Axios
        source: "// See Node + Axios example of \"authentication | Request access token\"\n// to see how to initialize the variables `axiosClient` and `accessToken`\n\nconst headers = {\n  'Authorization': `Bearer ${accessToken}`,\n};\n\nconst response = await axiosClient.get(\n  '/stream', {\n  headers\n});"
      - lang: python
        label: Python
        source: "# See Python example for \"authentication | Request access token\"\n# to see how to create conn object and set `access_token` variable\nurl = \"/api/v6/stream\"\nheaders = {\n    \"Authorization\": f\"Bearer {access_token}\"\n}\n\nconn.request(\"GET\", url, headers=headers)\n\nres = conn.getresponse()"
      - lang: java
        label: Java
        source: "// See Java example for \"authentication | Request access token\"\n// to see how to set `accessToken` variable\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://metasys-server.example.com/api/v6/stream\"))\n    .header(\"Authorization\", \"Bearer \" + accessToken)\n    .method(\"GET\", HttpRequest.BodyPublishers.noBody())\n    .build();\nHttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());"
    servers:
    - url: https://{hostname}/api/v6
      description: The base URL of all API routes
      variables:
        hostname:
          default: metasys-server.example.com
          description: This is the name of your site director device
components:
  securitySchemes:
    Bearer-Authentication:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Most of the calls in the API use bearer token authentication. What this

        means is that these requests require an `Authorization` header to be set to

        a value with the following format: `Bearer: {accessToken}`. Use the

        [`/login`](#operation/createToken) operation to request an `accessToken`. An

        example of the full header would look like the following:

        `Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1...`.


        **Note:** This example access token is truncated.


        The expiration time of the access token is based on the user''s Metasys

        profile.

        '
    API-Key-Authentication:
      type: apiKey
      in: query
      name: access_token
      description: 'The [Streaming operation](#operation/getStream) is the only operation to use

        API key authentication, because web browsers do not allow setting custom

        headers when initiating Server Sent Event connections.

        '
x-refined-from:
- metasys-api-v6-16.json
- johnson-controls-metasys-openapi.yml
x-servers:
  apps:
    url: https://{hostname}/apps
    description: The base url for accessing APIs of non-core applications
    variables:
      hostname:
        default: metasys-server.example.com
        description: This is the name of your site