Surveillance API
Overview
The Surveillance API provides a mechanism for you to 'push' aircraft surveillance data directly to Altitude Angel, which is then standardised and correlated with other information sources in our network. These position reports along with data from other sources provides a comprehensive picture of the airspace in real-time which is used by our other services such as airspace alerts and conflict resolution. Position reports are accepted from sensors which have been pre-registered and can authenticate with the API to validate their identity.
Who is this service intended for use by?
Our surveillance infrastructure is used by:
- Drone Detection sensors
- ATM sensors, such as RADAR
- Software developers who wish to provide data from one, or more, connected/observed vehicles
What are the benefits of this service?
Transmission of surveillance data to the Altitude Angel platform has numerous benefits, including the ability to then consume our other services, such as the tactical conflict resolution service, by incorporating your own data. Behind-the-scenes, we 'fuse' all data received into a common pipeline, and correlate it with other sources to provide a rich, real-time data view of the sky.
Getting started
Follow the instructions in this guide to get up and running.
You'll need a developer account in order to use this service
Register for a Developer Account at https://developers.altitudeangel.com.
Once you've got your developer account setup, decide which implementation pathway you're going to follow.
The API supports both data ingest from individual sensors, and bulk data ingest from aggregated feeds. Depending on which category you fall into, there is a slightly different authentication requirement (reflecting the type of hardware used).
-
For a single sensor or multiple sensors (individually or via an application proxy) where your sensor client application is 'intelligent' (it can make OAuth requests), you'll need to pre-register your
sensor_id
with us before you begin. Open a support ticket and we'll do this quickly. -
If you have a 'headless' sensor device (one that does not have a UI where you can log in), go to https://surveillance.altitudeangel.com/ in order to pair it.
Minimum Requirements and API Characteristics
To help you start right, please observe the following important details:
The minimium supported TLS version is 1.2
Attempting to establish a connection using TLS Version 1.0 or 1.1 will fail, and the connection will be rejected for security reasons.
Base URI
The Base URI for all services quoted here is
https://surveillance-api.altitudeangel.com
URIs referenced in this document are relative
The URIs referenced in this documentation are relative to the base of
https://surveillance-api.altitudeangel.com
, and you must use DNS to locate the service, and respect the TTL of the record. Never store the IP address returned through resolution of the DNS query. We deliver the service via multiple datacentre locations and across a range of IP addresses, and regularly rotate clusters for security and performance reasons. Always resolve the location of the service by making a fresh DNS query (respecting the TTL of the record).
Taken note of the above? Great! Let's get started...
Authentication
Before you can use this API, you must authenticate.
To successfully authenticate, you'll need to:
- Pre-register your sensor device(s), by contacting our support team
- Obtain device token(s) using one of the two methods/flows described below
- Follow the appropriate authentication flow based on your sensor device
Information on each of these steps is shown below.
Sensor Pre-Registration
All sensors must be pre-registered on our network. Once you've given us your sensors' locally unique identifiers and your own client identifier, we'll enable them so you can authorize with our API. Please contact our support team with your sensor ID and client ID for us to pre-register your sensor.
Contact our support team to pre-register your sensors
You can do this via our support portal at https://customerportal.altitudeangel.com.
Need to register a lot of sensors?
We do support bulk pre-registration, so if you have a large number of sensors you wish to use with this service, just let our friendly team know.
Device Token
A device token
is an authorization token which permits access to the Surveillance API from your sensor or system.
We support two methods of obtaining a device token:
-
For intelligent clients such as a phone application or proxy application, device tokens can be obtained by making an OAuth2
client_credentials
request to our servers including your sensor ID -
For headless sensors with no way of provisioning a
client_id
andclient_secret
for an OAuth2 request, we support pairing.
Pairing allows for the delivery of a device token to a device via a simple HTTPS call using the sensor's local unique identifier e.g. an IMEI number or serial number (all sensors are assigned a globally-unique identifier by our network).
Use the Pairing Portal to initiate pairing for devices that can't follow the OAuth2 flow
To initiate pairing for unintelligent clients, head to the Pairing Portal at https://surveillance.altitudeangel.com.
Choosing an appropriate local identifier for your sensor(s)
You'll need to give each of your sensors their own locally-unique identifier (this should be the unique identifier of the sensor within your system). This can be any alphanumeric string
up to 255 characters in length.
During pre-registration, we will generate a globally unique ID from your locally unique one that ensures the sensor ID is unique within our network. The public APIs documented here require the globally unique ID to be passed.
The globally unique ID will be contained in your device tokens.
Headless devices will need to go through the Pairing Flow while regular devices will authenticate via our Primary Authentication Flow, detailed here.
Primary authentication flow for surveillance systems
The diagram below outlines the flow by which intelligent sensors or systems will authenticate and post position reports.
Pairing flow for individual surveillance sensors
The diagram below outlines the pairing flow to be used for headless sensors to obtain a device token in order to provide position reports.
Obtaining a device token for a regular sensor device
Users must have pre-registered their local unique sensor IDs by creating a support ticket.
See the general Auth docs, follow the instructions under Simple User Provisioning and Authentication
and request a token with the following parameters:
Parameter Name | Value |
---|---|
client_id | ID of your Client set up for device flow |
client_secret | Secret for the above Client |
grant_type | "client_credentials" |
scope | "surveillance_api" |
token_format | "jwt" |
device_id | The local unique sensor id you want to create a token for |
This will return a standard OAuth v2 response with an access_token
and refresh_token
. The access_token
is the token you must use to communicate with the Surveillance API.
Pairing a headless sensor device
- Go to
https://surveillance.altitudeangel.com/pairing/start
- Find the device you'd like to pair, and click the Pair button
- Within 60 seconds, the device to be paired must POST to
/v1/pairing-tokens/consume-token
with its local sensor ID
Consuming Tokens
POST https://surveillance-api.altitudeangel.com/v1/pairing-tokens/consume-token?clientUniqueId=<sensor id here>
Content-Type: application/json
This endpoint does not require authentication.
clientUniqueId
must be a unique string within the context of your account, i.e. the sensor's locally unique ID, and is sent via a query string parameter.
Therefore you may theoretically use very simple IDs such as "1"
, although in practice we'd recommend you use a string that more easily identifies your device, such as the
IMEI number of the mobile data module, MAC address, or similar.
https://surveillance.altitudeangel.com/v1/pairing-tokens/consume-token
Responses
https://surveillance.altitudeangel.com/v1/pairing-tokens/consume-token
ResponsesResponse Code | Reason |
---|---|
200 OK | Successfully consumed the pairing token. See below for data structure containing your JWT Device token. |
404 Not Found | A pairing request for the specified clientUniqueId could not be found. |
503 Service Unavailable | The request could not be processed. |
Example response:
{
"id": "8615ace9bf1f47e78e7c8363f1688a27",
"sensorId": "urn:aa:device:MAyOLl4t_hIzov_qwHNhtnOwP1rPp20ZqRf_gNEh0:abc123",
"clientUniqueId": "abc123",
"accessToken": "eyJ0 [...] iJ9.eyJ1bmlxdWVfbmFtZSI6IlVzZXIgQVBJIFBsYW4gLSBmM2VlYTFlMWFjYTc0NTU4OWNlODMxMGQ2YzBhMzFlZCIsInVybjphYTp0b2tlbl90eXBlIjoiZGV2aWNlIiwidXJuOmFhOmRldmljZV9pZCI6InVybjphYTpkZXZpY2U6TUF5T0xsNHRfaEl6b3ZfcXdITmh0bk93UDFyUHAyMFpxUmZfZ05FaDA6QXV0b1Rlc3RVc2VyRGV2aWNlMSIsImlzcyI6IkFBLkF1dGgiLCJhdWQiOiJBQSBTZXJ2aWNlcyIsImV4cCI6MTU4NDE4MTMzMCwibmJmIjoxNTg0MDk0OTMwfQ.
rPTq [ ... ] 57CA",
"refreshToken": "[...]",
"expiresAt": "2020-03-14T10:22:09.3766782+00:00"
}
PairingToken
PairingToken
Parameter Name | Datatype | Description |
---|---|---|
id | string | Unique ID of the pairing request |
sensorId | string | ClientUniqueId turned into a globally unique ID |
clientUniqueId | string | Your sensor ID |
accessToken | string | A JWT token that you can use to connect to the position-reports endpoint |
refreshToken | string | Refresh token that can be used to obtain a new accessToken |
expiresAt | DateTimeOffset | Time when the access token expires |
Sending Position reports
POST https://surveillance-api.altitudeangel.com/v1/position-reports
Authorization: Bearer <token>
Content-Type: application/json
The API receives position reports which are processed asynchronously.
A position report consists of the following key pieces of data:
sensor
metadata identifying the sensor for which data is submitted- One (or more)
positions
, which specify information about objects known, or visible, to the sensor
Refer to the property definition below to determine which parameters are mandatory and which are optional.
Ensure that your HTTP request is authorized. To learn how to authorize your request, see
Authentication
section below.
Construct the payload of your HTTP request as a JSON document using UTF-8 encoding as follows:
Minimal Example
In order for the report to be processed for map view, it needs to have the following data:
{
"positions": [
{
"id": "654321",
"sourceTimeStamp": "2021-10-18T15:42:52.481Z",
"position": {
"lat": 52.07096461036907,
"lon": -0.6322133544584766
},
"target": {
"ids": [
{
"id": "123456",
"type": "SerialNumber"
}
]
},
"altitudes": [
{
"height": 123,
"datum": "msl"
}
],
"groundVelocity": {
"x": 0,
"y": 0,
"z": 0
}
}
]
}
Comprehensive position report example
A more complete example looks like:
{
"sensor": {
"id": "123456789",
"pressure": 1013.00,
"sensorPosition": {},
"additionalInfo": {}
},
"positions": [
{
"id": "3456789",
"sourceTimeStamp": "2020-01-01T12:00:00.111Z",
"target": {
"sourceId": "12345",
"type": "aa:target:aircraft",
"confidence": 100,
"ids": [{
"id": "UAV1111",
"type": "icao"
}],
"additionalInfo": {}
},
"position": {
"lat": 0.1111,
"lon": 51.111,
"accuracy": 4,
"source": "gps",
"age": 5
},
"altitudes": [{
"height": 1234.456,
"datum": "msl",
"accuracy": 20,
"source": "",
"age": 5
}],
"onGround": true,
"groundVelocity": {
"x": 12.3,
"y": 10.2,
"z": 0,
"horizontalAccuracy": 1,
"verticalAccuracy": 1,
"source": "",
"age": 5
},
"trueAirspeed": {
"x": 13.1,
"y": 12.1,
"z": 1,
"horizontalAccuracy": 1,
"verticalAccuracy": 1,
"source": "",
"age": 5
},
"acceleration": {
"x": 1.1,
"y": -0.9,
"z": 0,
"horizontalAccuracy": 0.1,
"verticalAccuracy": 0.1,
"source": "",
"age": 5
},
"heading": 90.1,
"additionalInfo": {}
}
]
}
Data Models
An explanation of the properties in the above JSON document is provided below. Required properties are marked with an asterisk *.
PositionReport
PositionReport
Parameter Name | Datatype | Description |
---|---|---|
sensor | SensorState | Metadata about the sensor device providing positions |
positions* | PositionData[] | Collection of positions. Must not be empty |
PositionData
PositionData
Parameter Name | Datatype | Description |
---|---|---|
id* | string | Uniquely identifies this specific position report by the sender |
sourceTimeStamp* | dateTime | Indicates when the position report was sent, according to the sensor clock, in UTC. (IAT should be accounted for by the sensor) |
target | Target | Contains identification details of the detected object |
position* | GeographicPosition | Contains the position of the detected object |
altitudes | Altitude[] | Contains one or more detected altitudes for the object |
groundVelocity | GeographicVector | Contains data for the speed (in m/s) and track of the object. |
trueAirspeed | GeographicVector | Contains information about the true airspeed (TAS) of the object |
onGround | bool | True if the sensor considers the object to be on the ground |
acceleration | GeographicVector | Contains acceleration information for the object |
heading | double | Object heading in degrees |
additionalInfo | JSON | Provides any additional sensor-specific information |
GeographicPosition
GeographicPosition
Parameter Name | Datatype | Description |
---|---|---|
lat* | double | the latitude in decimal degrees |
lon* | double | the longitude in decimal degrees |
accuracy | double | Accuracy of the position in meters. If not specified, accuracy is assumed to be the accuracy of the lat/long provided |
source | string | Indicates the source of the position data (e.g GPS) |
age | double | The age in seconds since this data was acquired |
SensorState
SensorState
Parameter Name | Datatype | Description |
---|---|---|
id* | string | The locally unique identifier of the sensor providing the positions |
pressure | double | Current pressure in mb at the sensor's location |
sensorPosition | SensorPosition | Provides up to date sensor position information if the sensor can move/rotate/etc. |
additionalInfo | JSON | Provides any additional information about the current state of the sensor |
SensorPosition
SensorPosition
Parameter Name | Datatype | Description |
---|---|---|
geographicPosition | GeographicPosition | The position of the sensor providing the positions |
altitude | Altitude | The altitude of the sensor. For ground-based sensors, altitude datum should be MSL |
heading | double | For directed sensors, the direction it is facing in degrees from north |
angle | double | For directed sensors, the angle of the device in degrees from horizontal |
GeographicVector
GeographicVector
Parameter Name | Datatype | Description |
---|---|---|
x | double | East-West part of the vector |
y | double | North-South part of the vector |
z | double | Up-Down part of the vector |
horizontalAccuracy | double | Accuracy of the x/y parts |
verticalAccuracy | double | Accuracy of the z part |
source | double | The source of the vector information |
age | double | The age in seconds since this data was acquired |
Height
Height
Parameter Name | Datatype | Description |
---|---|---|
height* | double | The height in meters according to the specified datum |
datum* | string | The height datum. One of “wgs84”, “agl”, “bar”, “msl” |
accuracy | double | Accuracy of the height in meters |
source | string | The source of the height data |
age | double | The age in seconds since this data was acquired |
Target
Target
Parameter Name | Datatype | Description |
---|---|---|
sourceId | string | The sensor's unique id for this target |
type | string | The type of target detected in a urn format. One of "aa:target:aircraft" or "aa:target:drone" |
confidence | int | The percentage confidence that the type has been identified correctly (1-100) |
ids | Identifier[] | Collection of known identifiers for this target |
additionalInfo | JSON | Additional information about the target, e.g. make, model |
Identifier
Identifier
Parameter Name | Datatype | Description |
---|---|---|
id* | string | The id value |
type | string | Text string describing the type of identifier, (e.g. ICAO, IMEI, SerialNumber) |
Validation
- All required (*) fields must be present
- The
positions
collection may not be empty sensor.id
must be the same as the sensor ID that was used to generate your device token if specified- Altitude datums must be one of the accepted values
A successful response is indicated by a 202 HTTP status code with an empty body.
Responses
Response Code | Reason |
---|---|
202 Accepted | Successfully posted position report. Will be processed asynchronously. |
400 Bad Request | Request body was invalid. |
401 Unauthorized | A valid authorization token was not present on the request. |
403 Forbidden | The authorization token's sensor ID did not match the sensor ID in the request body; surveillance_api scope is missing from the token |
503 Service Unavailable | The request could not be processed. |
Surveillance Out
Authentication
The Surveillance Out endpoints retrieve device and position report data against a known Altitude Angel user. As such it requires a bearer token. The required scope for the Surveillance Out endpoints is
surveillance_api
. Learn more about authentication.
The user interface for surveillance where devices can be viewed and modified is found here.
Surveillance User Interface
The user interface for surveillance gives an overview of the devices associated with your user. If you don't have any devices then please contact our support desk to add devices and get started. From the devices table there are a number of actions that can be selected ranging from: setting relay details, pairing a device and enabling/disabling storing position reports.
Position reports by default will be stored in short term storage that will allow you to view them by selecting the "View recent reports" action on the devices table. If this is not desired then this can be disabled through the "actions" menu.
Relaying Position Reports
Assigning a relay URL to a device will enable the relaying functionality. Whilst being processed by our API, your position report will also be sent to the relay given that it has been successfully set up and is in an active state.
Setting Relay Details
Updating the relay details can be completed through the surveillance UI where the relay URL will be validated. This validation will check that the URL is HTTPS, reachable and is able to return a validation code that is sent as part of a POST call. If the validation fails then the reason why will be displayed to assist the set up process.
Upon a successful validation process, received position reports for the device will begin to be relayed to the given URL. The payload model containing the position report is documented below.
{
"name": "validate",
"version": "1.0",
"validationCode": "some-GUID"
}
{
"name": "position_report",
"version": "1.0",
"positionReport": {...}
}
Endpoints
Get Recent Position Reports For Device
This endpoint will return a list of Position Reports (see Data Models) that have been received in the current metric window (the duration can be seen in the surveillance UI).
GET: https://surveillance.altitudeangel.com/v1/devices/{deviceId}/recent
Authorization: Bearer <token>
{
"data": [
{
"receivedTimeStamp": "2022-05-19T00:00:00.00Z",
"sensor": {...},
"positions": [...],
"tags": [...]
}
]
}
Get All Devices
This endpoint returns a full list of all devices for your user.
GET: https://surveillance.altitudeangel.com/v1/devices
Authorization: Bearer <token>
{
"data": [
{
"deviceId": "",
"deviceCreationTimestamp": "",
"deviceName": "",
"positionReportMetrics": [],
"relayDetails": {
"url": "",
"state": "Active",
"failureDescription": null
},
"shouldStorePositionReportMetrics": true
}
]
}
Get Device By URN
Gets a device by its URN (uniform resource name).
GET: https://surveillance.altitudeangel.com/v1/devices/{deviceUrn}
Authorization: Bearer <token>
{
"deviceId": "",
"deviceCreationTimestamp": "",
"deviceName": "",
"positionReportMetrics": [],
"relayDetails": {
"url": "",
"state": "Active",
"failureDescription": null
},
"shouldStorePositionReportMetrics": true
}
Toggle Storing Position Reports
Toggles whether position reports should be stored. These position reports will be stored for the duration of the current metric window (the duration can be seen in the surveillance UI).
POST: https://surveillance.altitudeangel.com/v1/devices/{deviceUrn}/toggle-storing-position-reports
Authorization: Bearer <token>
Boolean value based on whether it has toggled to true or false.
Set Relay Details For Device
Updates the relay details of the device.
POST: https://surveillance.altitudeangel.com/v1/devices/{deviceId}/relay
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "",
"state": 1 = Active, 2 = Inactive, 3 = Failed
}
{
"deviceId": "",
"deviceCreationTimestamp": "",
"deviceName": "",
"positionReportMetrics": null,
"relayDetails": {
"url": "",
"state": "Inactive",
"failureDescription": null
},
"shouldStorePositionReportMetrics": true
}
Updated about 2 years ago
Sign up for a developer account, then create a support ticket to pre-register your devices. Pre-registration is not required for prior-authorised surveillance partners.