Basic communication with FLOW's REST API
See how to create basic requests and authenticate with FLOW's servers.
As introduced in the previous guide, FLOW features a REST API and data sinks that allow third-party applications to request outputs of any operators in various forms.
Any HTTPS agent is able to communicate with FLOW’s servers using its API, which conforms to the style and constraints of REST. The message bodies use the JSON syntax. This document describes the resources and methods that your applications can use. They will be expanded in the future.
In this document, parts of URIs that are in curly braces indicate a parameter that you need to replace with a valid value. For example in URI /cubes/{cube_id}/analytics
the cube_id
is a parameter that you need to replace with a valid cube ID, like /cubes/0/analytics
.
In case of an error in communication or processing, FLOW blocks always respond with the relevant HTTP status code and error object in the response’s body. See the error reference for details.
General prerequisites
All communication with the REST API uses the HTTPS.
All HTTP messages containing a JSON body must include the Content-Type: application/json
header.
API versioning
FLOW API uses versioning that is different from Insights and Block versions. API version defines what each party is able to communicate and receive. It has the structure of <major version>.<minor version>
, e.g. 3.17
.
All HTTP requests towards the block must include the Accept-Version
header with the API version number that the client supports. Example:
This version must be the same or higher than the block's version (but still within the same major version). If it's not, the block will respond with the api_version_mismatch
error to all requests except the block info requests. The purpose of this check is to warn all users of the API when there have been changes causing potential incompatibility with their current application.
Increasing the minor version number never introduces breaking changes to the API. Incrementing the major version number introduces changes to the API that cause agents with older versions to not be able to communicate properly. The API version is actually related to versions of other FLOW SW, it just doesn't increase as often. Here's an example of how version numbers might develop over time:
The change that has been done | SW version | API version |
---|---|---|
(The beginning) | 1.0 | 1.0 |
API functionality extension | 1.1 | 1.1 |
Changes irrelevant to the API | 1.2 | 1.1 |
Changes irrelevant to the API | 1.3 | 1.1 |
API functionality extension | 1.4 | 1.4 |
Changes irrelevant to the API | 1.5 | 1.4 |
"Breaking changes" in the API | 2.0 | 2.0 |
(SW versions actually have a third number, but its increase will never cause any change in API, so it's been omitted here.)
The block's current version can be obtained from the block info request below. This request doesn't need to contain the Accept-Version
header.
Obtaining the block information
The presence and contents of the Accept-Version
and Authorization
headers are not checked while processing this request.
Method: GET
URI: /block_info
Example response body:
{
"api_version": "1.9",
"block_host_device_type": "demokit",
"block_specialization": "traffic",
"block_version": "1.9.2",
"flow_serial_number": "Undefined",
"updater_available": false,
"updater_port": 8089
}
Comments:
flow_serial_number
,block_host_device_type
, andblock_specialization
are there for the specific needs of the FLOW team and users should have no interest in these values- The updater is currently available only on Jetson FLOW variants (
macro
andmicro
)
Authentication
Accessing most of FLOW's resources requires your authentication. Ask the block's administrator to create an account for you. You can then authenticate by following these steps:
- Send your username and password to the FLOW block with the HTTPS. (See below on how to do that.)
- The block replies with your access token(s)
- Remember the token(s)
- Include one of your access tokens as a bearer token in an
Authorization
header in all your HTTPS requests to FLOW API like this:
Authorization: Bearer dFfAwNcMtLrBqCfMmWhCsVsLk
wheredFfAwNcMtLrBqCfMmWhCsVsLk
is your access token.
The access token will mostly be the same for your account, but an administrator might manually change it at any time. In such a case, further requests with the old API key will return the 401 error code.
If you want to try it out on the demo live stream, launch the demo kit and start the demo live stream in FLOW Insights. Then you can use the HTTPS protocol to communicate with the block on the IP address 127.0.0.1
(localhost) and port 8080. Use the username demo_stream
and password demo_stream
as described in the next section.
If you're running the block on a smart camera, you need to use port 8088 instead of 8080. If you're running anything else than a demokit stream, you need to send requests to the IP address of the device that is running the FLOW block and use your real user credentials for authentication.
Retrieving the access tokens
Method: POST
URI: /users/auth
Example request body:
{
"username": "demo_stream",
"password": "demo_stream"
}
- Example response body:
{
"access_tokens": [
"dFfAwNcMtLrBqCfMmWhCsVsLk"
]
}
The access_tokens
array contains the tokens you need to use in all following communication to authenticate as the user demo_stream
.
It's also possible to find out your access token through FLOW Insights on the My account page.
Cubes
Cubes refer to FLOW cubes described in the architecture article.
Listing cubes
Method: GET
URI: /cubes
Example response body:
{
"cubes": [
{
"id": 0,
"name": "Square intersection"
},
{
"id": 1,
"name": "North street"
},
{
"id": 2,
"name": "South street"
},
{
"id": 6,
"name": "Roundabout"
}
]
}
Information about individual cubes
Method: GET
URI: /cubes/{cube_id}
Example response body:
{
"id": 0,
"name": "Square intersection",
"enabled": true,
"sequence_number": "31"
}
The sequence_number
is very important. You can look at it as the cube’s version—every time someone changes the cube, the number gets incremented. Such changes include adding, removing, or changing an analytic or a camera. A correct sequence number is required in requests to change the cube. That's how the server makes sure you know its current version. Note that the sequence number will always be a string.
Enabling and disabling a cube
Disabling a cube effectively disables all related analytics as if you disabled them through FLOW Insights.
Method: PATCH
URI: /cubes/{cube_id}
Example request body:
{
"enabled": true,
"sequence_number": "31"
}
Example response body:
{
"enabled": true,
"sequence_number": "32"
}
The sequence_number
is explained in the previous section. Send the same value that you would get from a GET /cubes/{cube_id}
request.
The response contains the cube's state after applying the requested changes.
Analytics
Analytics are technically processed by blocks, but analytics always work with data from only one cube. That’s why in this hierarchy they belong under individual cubes.
Listing analytics
Method: GET
URI: /cubes/{cube_id}/analytics
Example response body:
{
"analytics": [
{
"id": 0
},
{
"id": 1
}
]
}
Information about individual analytics
Method: GET
URI: /cubes/{cubeid}/analytics/{analytic_id}
Example response body:
{
"id": 0,
"name": "Demo stream",
"sequence_number": "3"
}
The sequence_number
here is tied to the analytic, not the cube, and thus may have a different value. It increments only when the analytic (or something it contains) changes. You need to know the analytic's current sequence number in requests like obtaining trajectory counts shown later.
Detailed information about individual analytics
Method: GET
URI: /cubes/{cubeid}/analytics/{analytic_id}/info
Example response body:
{
"timestamp": "1606885743329",
"sequence_number": "62",
"cache_capacity": 10000,
"cache_count": 10000,
"cache_start_timestamp": "1606870433235",
"first_cached_trajectory_timestamp": "1606870354422",
"georegistered": false,
"last_autosave_timestamp": "1607007671524",
"last_cached_trajectory_timestamp": "1606885743095",
"vms_stream_source_uuid":"8c86a7d5-22b9-423e-b87c-5e5545d55829/28dc44c3-079e-4c94-8ec9-60363451eb40",
"state": {
"processing_state": "processing",
"visibility_state":"good"
},
"camera_location": {
"name": "",
"latitude": 49.2234353,
"longitude": 16.5947053
},
"home_position" : {
"pan" : 0.5,
"tilt" : 0.5,
"zoom" : 0.5
},
"home_tolerance" : {
"pan" : 0.001,
"tilt" : 0.001,
"zoom" : 0.001
}
}
There is information about the trajectory cache. Cache size (cache_capacity
), current trajectory count (cache_count
) and timestamp in milliseconds from which all detected trajectories are cached (cache_start_timestamp
). Timestamps of first and last trajectories present in the cache are provided as well. Furthermore, features configured in analytics settings such as camera location and georegistration state are returned together with current analytics processing state: processing
or idle
, and its visibility state: good
, poor
, or unknown
.
timestamp
refers to the time of the last evaluation of the analytic. If e.g. the analytic would be disabled, this timestamp won't be updated.
If the analytic isn't tied to a PTZ camera, the home_position
and home_tolerance
will be hidden. If it is, the objects contain information about the position that must be reached by the camera in order for the analysis to take place. If the camera is out of this position, analytics will be paused.
vms_stream_source_uuid
will only be visible if the analytic is associated with a VMS interface. In that case, it refers to the UUID of the camera/stream within the VMS.
Camera information
Method: GET
URI: /cubes/{cube_id}/analytics/{analytic_id}/camera_info
Example response body:
{
"connection_string": "rtsp://username:[email protected]/fhd",
"source_state": "source_status_running",
"source_stabilisation_state": "off",
"source_size": {
"height": 1080,
"width": 2336
},
"detection_size": {
"height": 1080,
"width": 2336
},
"display_size": {
"height": 1080,
"width": 2336
},
"input_fps": 29.83099937438965,
"detector_fps": 29.83099937438965,
"tracker_fps": 30.23140525817871,
"movement_state": "idle",
"position_state": "home",
"ptz_position" : {
"pan" : 0.01,
"tilt" : 0.5,
"zoom" : 0.112
},
"onvif_connection_string" : "admin:[email protected]",
"supported_object_colours": [
"black", "blue", "silver", "orange", "red", "grey",
"white", "yellow", "undefined"
],
"supported_object_types": [
"bus", "pedestrian", "car", "heavy", "motorcycle",
"animal", "light", "van", "bicycle"
]
}
Comments:
connection_string
—contains the identifier of the camera image source. This is usually a URL of an RTSP stream. On a demokit it's also possible for it to be a path to a video and a.tlgx
file (contains trajectory info), separated by the character@
. The paths correspond to the machine running the FLOW block.source_state
—an enum string containing one of the following strings:source_status_idle
source_status_paused
—currently unusedsource_status_reconfiguring
—in the process of connecting to the camerasource_status_running
—camera data is being processedsource_status_error
—there's been a problem during the connection or disconnection from the camerasource_status_eos
—End Of Stream—the stream or played file has endedsource_status_timeout
—there has been no new image nor an error status for too longsource_status_removing
—the source is in the process of being removedsource_status_closed
—the last status before a source will have been deletedoffline
—the FLOW NODE has disconnected and is unreachablesource_state_unknwon
—(the typo corresponds to how the FLOW BLOCK will return the status) a wildcard status that you should never be able to see
source_stabilisation_state
—the current status of image stabilization. Stabilization is currently used only by the FLOW Aerial edition. It can have one of the following values:off
,on
,error
,unstable
source_size
contains the resolution of the input image,detection_size
contains the resolution of the detector,display_size
is the image resolution in which the rest of FLOW works with the inputinput_fps
—contains the FPS of the image input,detector_fps
contains the FPS that the detector is able to process ,tracker_fps
contains the FPS that the tracker is able to processmovement_state
—an enum string describing the status of the camera's current PTZ movement. It contains one of the following strings:unsupported
,idle
,moving
,error
position_state
—an enum string describing the status of the camera's current PTZ position. It contains one of the following strings:unset
,home
,out
ptz_position
andonvif_connection_string
—displayed only if the camera is a PTZ camerasupported_object_colours
andsupported_object_types
contain the colours and categories that the corresponding FLOW NODE is able to detect
Camera frame
Returns the current camera image for the corresponding analytic. Camera images are updated every 30 seconds.
Method: POST
URI: /cubes/{cube_id}/analytics/{analytic_id}/camera_frame
Example request body:
{
"last_image_timestamp" : "160103180000",
"requested_size" : {
"height": 720,
"width": 1280
}
}
Example response body:
{
"background_image": "dashufadsbpyhfgasfv2as8rv2a+w98v1f7as8", // ....
"timestamp": "1601032435620"
}
Comments:
last_image_timestamp
andrequested_size
are optional. At the minimum, the request must contain an empty JSON object, i.e.{ }
.- If the
last_image_timestamp
is more recent than the most recent snapshot the FLOW block has, then the value of thebackground_image
in the response will be an empty string. The purpose is to save bandwidth in case there isn't a more recent image than you already have. - The returned image will be scaled according to the
requested_size
. The original aspect ratio won't be preserved. timestamp
contains the timestamp of when the returned image originated.- If the value of
background_image
isn't empty, it contains a JPEG data encoded into a Base64 string.
Counts
It’s possible to receive trajectory counts sorted into traffic object categories for the whole scene. Include the analytic's current sequence number in your request.
Method: POST
URI: /cubes/{cube_id}/analytics/{analytic_id}/counts
Example request body:
{
"sequence_number": "42"
}
Example response body:
{
"cache_capacity": 10000,
"cache_count": 10000,
"cache_start_timestamp": "1597723207001",
"timestamp": "1583415920",
"root_outputs": [
{
"count": 0,
"type": "unknown"
},
{
"count": 11,
"type": "car"
},
{
"count": 1,
"type": "light"
},
{
"count": 0,
"type": "heavy"
},
{
"count": 0,
"type": "bus"
},
{
"count": 0,
"type": "motorcycle"
},
{
"count": 2,
"type": "bicycle"
},
{
"count": 4,
"type": "pedestrian"
}
]
}
Comments:
- See here for information about trajectory caching.
REST sinks
See how you can request outputs of existing REST sinks in the next article.
Not sure how to do it or have some questions? Contact us!
Updated over 1 year ago