Introduction
Welcome to the AirHub API! Our API powers the Business of Drones through the delivery of data and services to power and enrich your UAS applications.
The AirHub API is organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded or JSON request bodies, returns JSON-encoded responses and uses standard HTTP response codes, authentication, and verbs.
You can use the AirHub API in sandbox mode, which does not affect your live data or interact with production systems. The base URL you use to make requests determines whether the request is live mode or sandbox mode.
We have language examples in curl/Shell and JavaScript. You can view code examples in the dark area to the right, and switch the programming language with the tabs on the top right.
Request access to the API by sending an email to developers@airspacelink.com. We may wish to learn more about your use case before granting access.
Terms and Conditions
Non-commercial use of this API is governed by the Non-commercial AirHub for Business Terms & Conditions.
Support
Need help, or want to get in touch? You can contact support here.
Authentication
OAuth
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'x-api-key: <your-subscription-key>' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=<your-client-id>' \
--data-urlencode 'client_secret=<your-client-secret>' \
--data-urlencode 'scope=airhub-api/<your-requested-scope> airhub-api/<second-scope>'
const params = {
grant_type: "client_credentials",
client_id: "<your-client-id>",
client_secret: "<your-client-secret>",
scope: "airhub-api/<your-requested-scope> airhub-api/<second-scope>",
};
const query = Object.keys(params)
.map((key) => key + "=" + params[key])
.join("&");
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/oauth/token");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded", true);
xhr.setRequestHeader("x-api-key", "<your-subscription-key>", true);
xhr.send(query);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"status": 200,
"message": "success",
"data": {
"accessToken": "xyz123",
"expires": "2021-03-16T21:57:33.332Z",
"scope": "airhub-api/advisory.read airhub-api/token.create"
}
}
AirHub uses client credentials and an API key to authenticate and authorize requests. Successful authentication will return an Oauth2 accessToken
. AirHub expects the accessToken
and x-api-key
to be included in all subsequent API requests.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/oauth/token
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/x-www-form-urlencoded |
x-api-key |
<your-api-key> |
Form Encoded Parameters
Parameter | Description |
---|---|
grant_type |
client_credentials |
client_id |
Client id supplied to you by Airspace Link |
client_secret |
Client secret supplied to you by Airspace Link |
scope |
See available Oauth Scopes |
Scopes
In addition to the Client ID and Secret, you must also supply one or many oauth scopes. If you're unfamiliar with scopes, you can think of them as bundles of related API endpoints that are authorized for access by your client application. Each scope should be prefixed with airhub-api/
, for example, airhub-api/hazar.read
. Multiple scopes may be requested by separating each scope by a space.
Available Scopes
Scope | Description |
---|---|
advisory.read |
Grants read access to our available advisories. This includes local and federal flight advisories. |
advisory.create |
Grants create access to our available advisories. This only includes local flight advisories. |
advisory.update |
Grants update access to our available advisories. This only includes local flight advisories. |
advisory.delete |
Grants delete access to our available advisories. This only includes local flight advisories. |
aviation.read |
Grants read access to aviation facility map data. |
hazar.read |
hazar is short for "Hazards and Risks". Grants read access to our hazar data. |
operation.create |
Used for deep-linking applications. Allows the creation of a UAS operation that can be deep-linked into LAANC authorization app. |
route.create |
Allows the creation of UAS waypoints that navigate around ground based hazards and risks. |
token.create |
Used to generate a geo-token . A geo-token grants access to specific geographic specialized resources throughout the API. |
flight.read |
Grants read access to our anonymized or group flight data. |
token.generate |
DEPRECATED: Use token.create instead. |
Advisories
Advisories represent geographic areas where special consideration must be made before operating drones. Examples of advisories may range from restricted airspace - where it's illegal to operate a drone - to warnings where it's important for you to understand the context of where you're flying to maximize safety. Additional advisory types will be documented as they're added.
Get Advisories
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v2/advisory' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"geometry": {
"type": "Polygon",
"coordinates": [[
[-83.25923546832819,42.23958101718406],
[-83.38626488727355,42.23958101718406],
[-83.38626488727355,42.13782883968136],
[-83.25923546832819,42.13782883968136],
[-83.25923546832819,42.23958101718406]
]]
},
"category": "faa_107",
"published": true
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v2/advisory");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
geometry: {
type: "Polygon",
coordinates: [
[
[-83.25923546832819, 42.23958101718406],
[-83.38626488727355, 42.23958101718406],
[-83.38626488727355, 42.13782883968136],
[-83.25923546832819, 42.13782883968136],
[-83.25923546832819, 42.23958101718406],
],
],
},
category: "faa_107",
published: true
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this (dates and times are in UTC, and can be null):
{
"data":
[
{
"type": "Feature",
"geometry": {"type": "Polygon", "coordinates": [[...]]},
"properties": {
"title": "4th of July Parade",
"message": "Parade in downtown Springfield to celebrate ...",
"severity": "warning",
"advisorySource": "community",
"advisoryType": "admin",
"startDate": "2020-01-01", // UTC
"startTime": "10:10", // military time
"endDate": "2020-01-01", // UTC
"endTime": "20:00", // military time
"timezone": "America/New_York",
"effectiveDays": ["Mon","Tue","Fri"],
"friendlyDayPhrase": "Active until further notice",
"contactName": "John Doe",
"contactPhone": "+12345678910",
"contactEmail": "john@gov.gov",
"contactUrl": "http://myadvisory.com/1234",
"metadata": {
// <custom attributes that may vary depending on the advisory>
}
}
},
{...},
{...}
],
"message": "success",
"statusCode": 200
}
Find advisories that intersect the input geometry
.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v2/advisory
Scope: airhub-api/advisory.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
GeoJSON | GeoJSON formatted geometry. May be point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 30 nautical miles. |
category |
string | See rule category. This is the specified rule category under which you'll be flying. |
source |
string | See advisory source. This is the advisory source you wish to return. |
startTime |
string | Argument for filtering active advisories on or after timestamp. Send as an ISO 8601 timestamp. See below for more details on how to use. |
endTime |
string | Argument for filtering active advisories on or before timestamp. Send as an ISO 8601 timestamp. See below for more details on how to use. |
maxAltitude |
integer | The maximimum altitude anticipated for the operation. This helps to determine FAA restrictions. |
published |
boolean | Argument for filtering published/unpublished advsisories. Send true for published advisories, false for unpublished, or omit this value to return all. |
Filtering FAA Advisories using startTime
/endTime
Some of the FAA Advisory types (e.g. tfr
) can be filtered using startTime
/endTime
. This will limit the advisories to those which have a start time less than or equal to endTime
and have an end time greater than or equal to startTime
.
Filtering Community Advisories using startTime
/endTime
For Community Advisories, filtering by startTime
/endTime
applies a windowed filter. For example, specifying 2020-11-05T12:00Z
for startTime
will filter advisories that are active (a) on or after November 5th, 2020, and (b) active after 12:00 UTC each day. An advisory that occurs 2020-11-06T10:00Z
-2020-11-06T11:00Z
would not be included in the result set; November 6th is after November 5th, but the advisory isn't active after 12:00 UTC, it ends at 11:00 UTC. Vice versa is also true for endTime
.
If startTime
and endTime
are both specified, you can wrap the time window by specifying startTime
's time portion in the ISO 8601 timestamp to be greater than endTime
's timestamp. For example, setting 2020-11-05T23:00Z
as startTime
and 2020-11-07T01:00Z
as endTime
will capture anything within the following ranges:
- 2020 November 5th, 23:00-23:59
- 2020 November 6th, 00:00-01:00, 23:00-23:59
- 2020 November 7th, 00:00-01:00
Source
Represents the source of the advsiory or the authority that created the advisory. Additional sources will be made available in the future.
Source | Description |
---|---|
faa |
Federal (FAA) advisories |
community |
State & Local community advisories |
all |
All available advisories |
FAA Types
FAA advisories can have the following types as detailed below:
Type | Description |
---|---|
controlled_airspace |
Controlled Airspace Classification. |
uasfm_ceiling |
UAS Facility Management Flight Ceiling. |
sua_prohibited |
Prohibited Special Use Airspace. |
sua_restricted |
Restricted Special Use Airspace. |
washington_frz |
Washington DC Flight Restricted Zone. |
nsufr_pt |
Part Time National Security UAS Flight Restriction. |
nsufr_ft |
Full Time National Security UAS Flight Restriction. |
stadium |
Select stadiums containing temporary flight restriction. The stadium points are buffered by 3 nautical miles. |
class_e_weather |
Weather ceiling when flying in class E airspace. |
tfr |
Temporary Flight Restrictions imposed by the FAA to restrict aircraft operations within designated areas. |
Community Types
Community advisories can have the following types as detailed below:
Type | Description |
---|---|
admin |
Administrative advisory (e.g. city or utility infrastructure) |
emergency |
Emergency response area (e.g. accident cleanup area) |
recreation |
Recreational advisory (e.g. parks, events, public gatherings) |
Severity
Each advisory will return a severity
property. These severities are described as follows:
Type | Description |
---|---|
grounded |
Flying within the advisory should not be undertaken without an additional FAA flight waiver |
warning |
Flying within the advsiory area is not restricted, but discouraged for safety reasons |
information |
The advisory is informational |
Create Community Advisory
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v3/advisory' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"type": "Feature",
"properties": {
"title": "Test advisory: Market",
"type": "Admin",
"tags": ["City Event"],
"effectiveDays": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"startDate": "2020-12-29",
"endDate": "2021-01-25",
"startTime": "16:00",
"endTime": "18:00",
"timezoneName": "America/New_York",
"referenceNumber": "farm 5.4",
"published": true,
"contactEmail": "Example@test.com",
"contactPhone": "+12345678910"},
"geometry": {"type": "Polygon", "coordinates": [[...]]}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v3/advisory");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
type: "Feature",
properties: {
title: "Test advisory: Market",
type: "Admin",
tags: ["City Event"],
effectiveDays: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
startDate: "2020-12-29",
endDate: "2021-01-25",
startTime: "16:00",
endTime: "18:00",
timezoneName: "America/New_York",
referenceNumber: "farm 5.4",
published: true,
contactEmail: "Example@test.com",
contactPhone: "+12345678910"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-83.25923546832819, 42.23958101718406],
[-83.38626488727355, 42.23958101718406],
[-83.38626488727355, 42.13782883968136],
[-83.25923546832819, 42.13782883968136],
[-83.25923546832819, 42.23958101718406],
],
],
}
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": [{"id": <advisory-id>}],
"message": "success",
"statusCode": 200
}
Create an advisory to notify UAS pilots about Administrative, Emergency, or Recreational activities.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v3/advisory
Scope: airhub-api/advisory.create
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
The POST
body is expected to be a GeoJSON Feature. The feature's geometry must be a GeoJSON Polygon.
Parameter | Type | Description |
---|---|---|
type |
static string | Feature |
geometry |
object | GeoJSON Polygon |
properties |
object | See advisory properties |
Advisory Properties
Parameter | Type | Description |
---|---|---|
title |
string | Name of the advisory. |
type |
string | The type of the advisory. |
timezoneName |
string | Timezone of the advisory. |
startDate |
string | ISO 8601 compliant start date of the advisory. If timestamp is provided, it will be ignored. Defaults to be active until endDate . |
endDate |
string | ISO 8601 compliant end date of the advisory. If timestamp is provided, it will be ignored. Defaults to be active indefinitely. |
startTime |
string | Start time for each day that the advisory is active (in 24hr format "hh:mm"). If date is provided, it will be ignored. Defaults to start at "00:00". |
endTime |
string | End time for each day that the advisory is active (in 24hr format "hh:mm"). If date is provided, it will be ignored. Defaults to end at "23:59". |
effectiveDays |
string array | List of weekdays in which advisory is active. Valid option is a subset of ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] . Defaults to [] . |
tags |
string array | List of tags as metadata for the advisory. |
referenceNumber |
string | Optional reference number from external data systems. |
contactUrl |
string | Url with more information about the advisory. |
published |
boolean | If true , the advisory is considered published. Defaults to false . |
contactEmail |
string | Contact email address of the advisory source. |
contactPhone |
string | Contact phone number of the advisory source. contactPhone should be formatted with '+1' country code followed by 10-digit phone number (e.g. "+11234567890"). |
groupId |
string | A GUID supplied to your jurisdiction by Airspace Link. |
Edit Community Advisory
curl --location --request PATCH 'https://airhub-api-sandbox.airspacelink.com/v3/advisory/<your-advisory-id>' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"type": "Feature",
"properties": {
"title": "Test advisory: Market",
"type": "Admin",
"tags": ["City Event"],
"effectiveDays": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"startDate": "2020-12-29",
"endDate": "2021-01-25",
"startTime": "16:00",
"endTime": "18:00",
"timezoneName": "America/Denver",
"contactPhone": "+12445672910"
},
"geometry": {"type": "Polygon", "coordinates": [[...]]}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("PATCH", "https://airhub-api-sandbox.airspacelink.com/v3/advisory/<your-advisory-id>");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
type: "Feature",
properties: {
title: "Test advisory: Market",
type: "Admin",
tags: ["City Event"],
effectiveDays: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
startDate: "2020-12-29",
endDate: "2021-01-25",
startTime: "16:00",
endTime: "18:00",
timezoneName: "America/Denver",
contactPhone: "+12345678910"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-83.25923546832819, 42.23958101718406],
[-83.38626488727355, 42.23958101718406],
[-83.38626488727355, 42.13782883968136],
[-83.25923546832819, 42.13782883968136],
[-83.25923546832819, 42.23958101718406],
],
],
}
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": [{"id": <advisory-id>}],
"message": "success",
"statusCode": 200
}
Some or all of an advisory's properties may be updated.
HTTP Request
PATCH https://airhub-api-sandbox.airspacelink.com/v3/advisory/<id>
Scope: airhub-api/advisory.update
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON PATCH Body
The PATCH
body is expected to be a GeoJSON Feature. The feature's geometry must be a GeoJSON Polygon.
Parameter | Type | Description |
---|---|---|
type |
static string | Feature |
geometry |
object | GeoJSON Polygon. Set as null if update is not needed |
properties |
object | See advisory properties. Set as null or {} if update is not needed |
Advisory Properties
Parameter | Type | Description |
---|---|---|
title |
string | Name of the advisory. Not nullable. |
type |
string | The type of the advisory. Not nullable. |
timezoneName |
string | Timezone of the advisory. Not nullable. |
startDate |
string | ISO 8601 compliant start date of the advisory. If timestamp is provided, it will be ignored. Defaults to be active until endDate . Nullable, set to null to erase current value. |
endDate |
string | ISO 8601 compliant end date of the advisory. If timestamp is provided, it will be ignored. Defaults to be active indefinitely. Nullable, set to null to erase current value. |
startTime |
string | Start time for each day that the advisory is active (in 24hr format "hh:mm"). If date is provided, it will be ignored. Defaults to start at "00:00". Nullable, set to null to erase current value. |
endTime |
string | End time for each day that the advisory is active (in 24hr format "hh:mm"). If date is provided, it will be ignored. Defaults to end at "23:59". Nullable, set to null to erase current value. |
effectiveDays |
string array | List of weekdays in which advisory is active. Valid option is a subset of ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] . Defaults to [] . Nullable, set to null or [] to erase current value. |
tags |
string array | List of tags as metadata for the advisory. Nullable, set to null or [] to erase current value. |
referenceNumber |
string | Optional reference number from external data systems. Nullable, set to null to erase current value. |
contactUrl |
string | Url with more information about the advisory. Nullable, set to null to erase current value. |
published |
boolean | If true , the advisory is considered published. Not nullable. |
contactEmail |
string | Contact email address of the advisory source. Nullable, set to null to erase current value. |
contactPhone |
string | Contact phone number of the advisory source. contactPhone should be formatted with '+1' country code followed by 10-digit phone number (e.g. "+11234567890"). Nullable, set to null to erase current value. |
groupId |
string | A GUID supplied to your jurisdiction by Airspace Link. Nullable, set to null to erase current value. |
Delete Community Advisory
curl --location --request DELETE 'https://airhub-api-sandbox.airspacelink.com/v3/advisory/<your-advisory-id>' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("DELETE", "https://airhub-api-sandbox.airspacelink.com/v3/advisory/<your-advisory-id>");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(JSON.stringify({}));
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": [{"id": <advisory-id>}],
"message": "success",
"statusCode": 200
}
Allows deletion of an advisory. Use caution; this action cannot be undone.
HTTP Request
DELETE https://airhub-api-sandbox.airspacelink.com/v3/advisory/<id>
Scope: airhub-api/advisory.delete
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
Operations
Operation
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/operation' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"type": "Feature",
"properties": {"operationName": "test"},
"geometry": {"type": "Polygon", "coordinates": [[...]]}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/operation");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
type: "Feature",
properties: {
operationName: "Test Operation"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-83.25923546832819, 42.23958101718406],
[-83.38626488727355, 42.23958101718406],
[-83.38626488727355, 42.13782883968136],
[-83.25923546832819, 42.13782883968136],
[-83.25923546832819, 42.23958101718406],
],
],
}
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": {"uuid": "<uuid>"},
"message": "success",
"statusCode": 200
}
To support LAANC authorizations within 3rd-party applications, the API allows the creation of operations for deep-linking workflows. Each operation includes information such as pilot name and contact information, operation start time and duration, requested altitude, and the operation boundary (shape).
LAANC Deep Linking
Successfully creating an operation will return a uuid that may be used to retrieve the operation within the AirHub Launch LAANC application. Following is a sample deep-link url (used after the operation has been successfully generated):
https://launch.airspacelink.com?operation=<uuid returned by API>
Important: Operations created in the sandbox API must deeplink into the sandbox pilot environment.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/operation
Scope: airhub-api/operation.create
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
The POST
body is expected to be a GeoJSON Feature. The feature's geometry must be a GeoJSON Polygon.
Parameter | Type | Description |
---|---|---|
type |
static string | Feature |
geometry |
object | GeoJSON Polygon |
properties |
object | See operation properties |
Operation Properties
{
"operationId": "ABCDEF8G"
"authId": "ABCDEF8G2"
"authStatus": "APPROVED"
"authStatusDate": "2022-01-28T19:57:57.378Z"
}
Example response sent to the URL provided in the callbackUrl parameter.
Parameter | Type | Description |
---|---|---|
operationName |
string | Name of the operation. |
category |
string | Rule category. |
startTime |
string | ISO 8601 compliant start timestamp of the operation. |
timezoneName |
string | Operation timezone. |
duration |
integer | Duration of the operation from 1 - 720 minutes. |
maxAltitude |
integer | Maximum requested altitude of the operation from 5 - 400' Above Ground Level. |
fixedAltitude |
boolean | If false , the platform will adjust the altitude to remain below any applicable ceiling limits. This makes for easier FAA approvals, but may not meet the parameters of your operation. |
callbackUrl |
string | Postback URL to receive operation authorization status updates. |
Rule Category
Type | Description |
---|---|
faa_107 |
FAA Commercial Part 107 rules |
faa_44809 |
FAA Recreational Part 44809 rules |
Timezone
Type | Description |
---|---|
America/New_York |
Eastern Time (EDT, EST) |
America/Chicago |
Central Time (CDT, CST) |
America/Denver |
Mountain Time (MDT, MST) |
America/Phoenix |
Mountain Time - No Daylight Savings (MST) |
America/Los_Angeles |
Pacific Time (PDT, PST) |
America/Anchorage |
Alaska Time (AKDT, AKST) |
Pacific/Honolulu |
Hawaii Time (HST) |
America/Puerto_Rico |
Atlantic Time (AST) |
Pacific/Guam |
Chamorro Time (ChST) |
America/Adak |
Aleutian Time (HADT, HAST) |
Pacific/Pago_Pago |
Samoa Time (SST) |
Flights
Anonymized flight data
To get anonymized flight data, use this code:
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/flight' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
-d '{
"geoType": "place",
"geoID": "2622000",
"startTime": "2021-03-08T12:00Z",
"endTime": "2021-03-25T13:00Z"
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open(`POST`, `https://airhub-api-sandbox.airspacelink.com/v1/flight`);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"geoType": "place",
"geoID": "2622000",
"startTime": "2021-03-08T12:00Z",
"endTime": "2021-03-25T13:00Z"
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": {
"numberOfPilots": 15,
"flights": [
{
"approvedAuths": 0,
"operationID": "ZKPBDFY5",
"startTime": "2021-03-22T19:37:00.000Z",
"indices": [
"89298616d93ffff",
...
]
},
...
]
}
}
Flights are UAS operations within a given geographic boundary. The data is returned as hex addresses which represent a hexagonal shape corresponding to one area of the flight. Therefore, the data is anonymized such that the boundaries do not reflect the actual area of the flight.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/flight
Scope: airhub-api/flight.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geoType |
string | A geographic type |
geoID |
string | A string serial ID qualified from geoType |
startTime |
string | Filters flights on or after timestamp. Send as an ISO 8601 timestamp. |
endTime |
string | Filters flights on or before timestamp. Send as an ISO 8601 timestamp. |
Geographic Types
Type | Description |
---|---|
state |
A state identifier |
county |
A county identifier |
county_subdivision |
A county subdivision identifier |
place |
A place identifier |
region |
A region identifier |
campus |
A campus identifier |
Group flight data
To get flight data, use this code:
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/flight/group' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
-d '{
"startTime": "2021-03-08T12:00Z",
"endTime": "2021-03-25T13:00Z",
"includeGeometry": true
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open(`POST`, `https://airhub-api-sandbox.airspacelink.com/v1/flight/group`);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"startTime": "2021-03-08T12:00Z",
"endTime": "2021-03-25T13:00Z",
"includeGeometry": true
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"type": "Feature",
"geometry": {"type": "Polygon", "coordinates": [[...]]},
"properties": {
"id": "ABC123",
"operationName": "Operation Good Times",
"stateCode": "",
"submissionCategory": "faa_107",
"maxAltitude": 200,
"fixedAltitude": false,
"startTime": "2021-03-08T12:00Z",
"timezoneName": "America/New_York",
"duration": 60,
"pilotFirstName": "Johnny",
"pilotLastName": "Guy",
"contactNumber": "+15555555555",
"contactEmail": "johnny@guy.com",
"createdDate": "2021-03-08T12:00Z",
"canceledDate": "2021-03-08T12:00Z",
"closedDate": "2021-03-08T12:00Z",
"status": "approved",
"droneModel": "Aero",
"droneMake": "3D Robotics"
}
},
{...},
{...}
]
}
Get all flights created within your group.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/flight/group
Scope: airhub-api/flight.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer token generated by login to the web application |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
startTime |
string | Filters flights on or after timestamp. Must be within 30 days of endTime . Defaults to 30 days before endTime , if endTime is specified. Send as an ISO 8601 timestamp. |
endTime |
string | Filters flights on or before timestamp. Must be within 30 days of startTime . Defaults to 30 days after startTime , if startTime is specified. If startTime isn't specified, it will default to now. The latest time allowed is 30 days into the future. The final range must not exceed a span of 30 days as well. Send as an ISO 8601 timestamp. |
includeGeometry |
boolean | Flag to include the geometry of the GeoJSON in the payload. Defaults to true. |
Token
Geo-Token
curl --location --request GET 'https://airhub-api-sandbox.airspacelink.com/v1/token/geo-token' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--header 'referer: <your-application-referer>'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open(
"GET",
"https://airhub-api-sandbox.airspacelink.com/v1/token/geo-token"
);
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.setRequestHeader("referer", "<your-application-referer>");
xhr.send();
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": {
"token": "<geo-token>",
"expires": 1600382940719,
"ssl": true
},
"message": "success",
"statusCode": 200
}
Some datasets require additional authorization. We call the token required for these requests a geo-token
. Examples of these types of resources include tile mapping services or specialized data limited to specific groups of individuals. The documentation will indicate when this token is necessary. If required, the geo-token will be supplied in a request header using the x-geo-token
header.
HTTP Request
GET https://airhub-api-sandbox.airspacelink.com/v1/token/geo-token
Scope: airhub-api/token.create
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
URL Parameters
Parameter | Type | Description |
---|---|---|
useGroup |
boolean | If true , the geo-token will utilize the security group assigned to the authenticated user. This parameter should be excluded from the request under normal circumstances. |
Risk
Hazard and risk is an important part of the UAS ecosystem. The FAA publishes well established guidelines on how operations should behave with respect to population and other ground-based risk. This set of API resources will help developers quantify these hazards and their associated risk with a geographic boundary.
Hazard
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/hazard' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-83.33816528320312, 42.20156425714052],
[-83.2059860229492, 42.20156425714052],
[-83.2059860229492, 42.274514451885],
[-83.33816528320312, 42.274514451885],
[-83.33816528320312, 42.20156425714052]
]
]
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/hazard");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
geometry: {
type: "Polygon",
coordinates: [
[
[-83.33816528320312, 42.20156425714052],
[-83.2059860229492, 42.20156425714052],
[-83.2059860229492, 42.274514451885],
[-83.33816528320312, 42.274514451885],
[-83.33816528320312, 42.20156425714052],
],
],
},
})
);
The above command returns JSON like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"type": "Feature",
"properties": {
"Category": "Critical Infrastructure",
"CategoryType": "Child Care Center",
"Name": "RIVERSIDE ACADEMY EARLY CHILDHOOD CENTER",
"Risk": 1,
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-83.2320785522461, 42.33418438593939],
[-83.22624206542969, 42.33418438593939],
[-83.22624206542969, 42.33646849299472],
[-83.2320785522461, 42.33646849299472],
[-83.2320785522461, 42.33418438593939]
]
]
}
}
]
}
Find hazards that intersect the input geometry
.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/hazard
Scope: airhub-api/hazar.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
object | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 10 nautical miles. |
Ground Type
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/groundType' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"geometry": {
"type": "Point",
"coordinates": [
[-85.52521705627441, 41.7848170756551]
]
},
"resolution": 10
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/groundType");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
geometry: {
type: "Point",
coordinates: [[-85.52521705627441, 41.7848170756551]],
},
resolution: 10,
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"data": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-83.108219359342,42.385396234885185],
[-83.1091231948962,42.38517018839536],
[-83.10928346569173,42.38450374309799],
[-83.10853992433273,42.38406334748932],
[-83.10763610686435,42.38428938593143],
[-83.10747581266932,42.38495582802976],
[-83.108219359342,42.385396234885185]
]]
},
"properties": {
"density": "Urban",
"popPerSqMi": 3270.2970129961664,
}
},
...
],
"message": "success",
"statusCode": 200
}
Represents the population classification(s) for the input geometry. Returns an array of the population densities and their respective geometries over the input geometry.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/groundType
Scope: airhub-api/hazar.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
object | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon |
resolution | number | The resolution of the output surface. A larger number means finer granularity. |
Ground Risk
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/groundRisk' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"geometry": {
"type": "Polygon",
"coordinates": [[
[-83.33816528320312, 42.20156425714052],
[-83.2059860229492, 42.20156425714052],
[-83.2059860229492, 42.274514451885],
[-83.33816528320312, 42.274514451885],
[-83.33816528320312, 42.20156425714052]
]]
},
"maxAltitude": 100,
"uavWeight": "MICRO",
"uavType": "HELICOPTER",
"pilotControl": "SINGLE_PILOT",
"losType": "VLOS",
"resolution": 10
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/groundRisk");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
geometry: {
type: "Polygon",
coordinates: [[
[-83.12633514404297,42.36539333502107],
[-83.06419372558594,42.36539333502107],
[-83.06419372558594,42.38619069220356],
[-83.12633514404297,42.38619069220356],
[-83.12633514404297,42.36539333502107]
]]
},
maxAltitude: 100,
uavWeight: "MICRO",
uavType: "HELICOPTER",
pilotControl: "SINGLE_PILOT",
losType: "VLOS",
resolution: 10
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"status": 200,
"message": "success",
"data": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-83.108219359342,42.385396234885185],
[-83.1091231948962,42.38517018839536],
[-83.10928346569173,42.38450374309799],
[-83.10853992433273,42.38406334748932],
[-83.10763610686435,42.38428938593143],
[-83.10747581266932,42.38495582802976],
[-83.108219359342,42.385396234885185]
]]
},
"properties": {
"density": "Urban",
"infrastructureTypes": ["Right of Way"],
"popPerSqMi": 3270.2970129961664,
"score": 2.4
}
},
...
]
}
Ground Risk is modeled from a combination of ground-based hazards, altitude, and drone characteristics (e.g. weight, speed, etc).
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/groundRisk
Scope: airhub-api/hazar.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
object | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon. |
uavWeight |
string | Describes the weight of the drone. |
uavType |
string | Describes the wing type of the drone. |
pilotControl |
string | Describes how the drone will be piloted for the operation. |
losType |
string | Describes how the pilot will be observing the drone fly during the operation (if at all). |
maxAltitude |
number | An integer representing the altitude of the flight in feet. Must be at least 100 feet. |
resolution |
number | The resolution of the output surface. Must be an integer 8-10. A larger number means finer granularity. |
UAV Weight
Different classifications of drone weights, in pounds
Type | Description |
---|---|
micro |
A drone that weighs ≤ 0.55 pounds |
mini |
A drone that weighs more than micro and ≤ 4.4 pounds |
limited |
A drone that weighs more than mini and ≤ 20.9 pounds |
bantam |
A drone that weighs more than limited |
UAV Type
The type of UAV used in the operation
Type | Description |
---|---|
fixed_wing |
A drone using wings for flight |
helicopter |
A drone using a single rotor for flight |
multirotor |
A drone using more than one rotor for flight |
hybrid |
A combination of the other 3 categories listed |
Pilot Control
How the drone is to be flown during the operation
Type | Description |
---|---|
single_pilot |
One pilot will fly the drone for the duration of the operation |
multiple_pilot |
Multiple pilots will fly the drone for the duration of the operation |
automated_control |
The drone will be controlled without a pilot |
Drone Line of Sight
How the pilot(s) (if any) will observe the drone for the duration of the operation
Type | Description |
---|---|
vlos |
Visual line of sight: the pilot can see the drone throughout the entire operation |
evlos |
Extended visual line of sight: the drone has spotters relaying information to the pilot |
bvlos |
Beyond visual line of sight: the pilot may not see the drone at some point throughout the operation |
Meta routes
Metadata
The metadata route shows all the data sources available for usage.
curl --location --request GET 'https://airhub-api-sandbox.airspacelink.com/v1/metadata' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--header 'referer: <your-application-referer>'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://airhub-api-sandbox.airspacelink.com/v1/metadata");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.setRequestHeader("referer", "<your-application-referer>");
xhr.send();
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"name": "Airports",
"code": "airports",
"description": "Points designated for landing or takeoff"
}
]
}
HTTP Request
GET https://airhub-api-sandbox.airspacelink.com/v1/metadata
Scope: airhub-api/metadata.read
Required Headers
Parameter | Description |
---|---|
Authorization |
Authorization bearer access_token generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
referer |
The base URL of the client application that will consume the token. For example, https://yourdomain.com . |
Aviation
Aviation
Returns intersecting aviation data from the FAA.
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/aviation?buffer=4' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"type": ["sua", "stadium", "airports"],
"geometry": {
"type": "Point",
"coordinates": [-85.52521705627441, 41.7848170756551]
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/aviation?buffer=4");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
type: ["sua", "stadium", "airports"],
geometry: {
type: "Point",
coordinates: [-85.52521705627441, 41.7848170756551],
},
})
);
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"type": "Feature",
"properties": {
// ...metadata
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-83.2320785522461, 42.33418438593939],
[-83.22624206542969, 42.33418438593939],
[-83.22624206542969, 42.33646849299472],
[-83.2320785522461, 42.33646849299472],
[-83.2320785522461, 42.33418438593939]
]
]
}
}
]
}
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/aviation
Scope: airhub-api/aviation.read
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
URL Parameters
Parameter | Type | Description |
---|---|---|
buffer |
number | Note: only used when type includes airports . buffer specifies the buffer around the airport in nautical miles. If not specified, the default is 3 . |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
object | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 30 nautical miles. |
type |
string | An array of zero or more types from FAA types below. Specifying type will limit the results to only include the type s that you specify. If you specify no type then all types will be returned. |
startTime |
string | Filters TFRs on or after timestamp. Send as an ISO 8601 timestamp. Only TFR data will be filtered by this property. |
endTime |
string | Filters TFRs on or before timestamp. Send as an ISO 8601 timestamp. Only TFR data will be filtered by this property. |
FAA Types
Below are various FAA data types. Types will be represented by a constant string as detailed below.
Type | Description |
---|---|
controlled_airspace |
Controlled Airspace Classification. |
uasfm_ceiling |
UAS Facility Management Flight Ceiling. |
sua |
Both sua_prohibited and sua_restricted . |
washington_frz |
Washington DC Flight Restricted Zone. |
nsufr_pt |
Part Time National Security UAS Flight Restriction. |
nsufr_ft |
Full Time National Security UAS Flight Restriction. |
stadium |
Select stadiums containing temporary flight restriction. The stadium points are buffered by 3 nautical miles. |
airports |
Points designated for landing or takeoff. Returns all airports within 3 nautical miles of input geometry by default. |
airspace_schedule |
Controlled airspace schedule for select airports across the country (geometry has no bearing on the result). |
tfr |
Temporary Flight Restrictions imposed by the FAA to restrict aircraft operations within designated areas. |
Surface
Surface routes provide hexagonal surfaces that describe the terrain, and can be used to quantify risk via suitability surfaces.
Surface
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/surface' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"resolution": 9,
"noFill": true,
"index": false,
"features": {
"schools": {
"where": "CITY = '\''BATTLE CREEK'\''",
"fields": ["*"]
}
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.20858764648438, 42.37579287453795],
[ -85.10009765625, 42.37579287453795],
[ -85.10009765625, 42.45436780800864],
[-85.20858764648438, 42.45436780800864],
[-85.20858764648438, 42.37579287453795]
]]
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/surface");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"resolution": 9,
"noFill": true,
"index": false,
"features": {
"schools": {
"where": "CITY = 'BATTLE CREEK'",
"fields": ["ADDRESS", "CITY"]
}
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.20858764648438, 42.37579287453795],
[ -85.10009765625, 42.37579287453795],
[ -85.10009765625, 42.45436780800864],
[-85.20858764648438, 42.45436780800864],
[-85.20858764648438, 42.37579287453795]
]]
}
})
);
The above command returns JSON like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.15551950378466, 42.40390655703839 ],
[-85.15743139843995, 42.40275510469299 ],
[-85.15693125519239, 42.40099262351432 ],
[ -85.1545193727733, 42.40038155809197 ],
[ -85.1526074934986, 42.401532929461865],
[-85.15310748125742, 42.403295447227336],
[-85.15551950378466, 42.40390655703839 ]
]]
},
"properties": {
"index": "89274822373ffff",
"schools": {
"ADDRESS": ["7422 POORMAN RD"],
"CITY": ["BATTLE CREEK"]
}
}
},
...
]
}
Generate a surface with any data sources you request.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/surface
Scope: airhub-api/surface.generate
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
geojson | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 10 nautical miles. |
features |
object | Key-value pairs with the key being a metadata source and the value being an object of parameters to the source. |
resolution |
number | The resolution of the output surface. A larger number means finer granularity. |
noFill |
bool | If there are no features in a particular hex, don't return it to reduce network latency. |
index |
bool | Instead of returning GeoJSON, return the indices of the hexagons. |
Parameters object
Parameter | Type | Description |
---|---|---|
fields |
string[] | The fields of the metadata source you'd like to return. |
where |
string | The where clause to apply to the metadata source. |
weight |
float | When computing risk, multiply the final risk score by this number if the feature is present. |
Suitability surface
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/suitability' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"resolution": 9,
"noFill": true,
"index": false,
"maxAltitude": 150,
"uavWeight": "MICRO",
"uavType": "FIXED_WING",
"pilotControl": "SINGLE_PILOT",
"losType": "VLOS",
"features": {
"streams": {
"where": "FTYPE = 'Artificial Path'",
"fields": ["*"]
}
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.20858764648438, 42.37579287453795],
[ -85.10009765625, 42.37579287453795],
[ -85.10009765625, 42.45436780800864],
[-85.20858764648438, 42.45436780800864],
[-85.20858764648438, 42.37579287453795]
]]
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/suitability");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"resolution": 9,
"noFill": true,
"index": false,
"maxAltitude": 150,
"uavWeight": "MICRO",
"uavType": "FIXED_WING",
"pilotControl": "SINGLE_PILOT",
"losType": "VLOS",
"features": {
"streams": {
"where": "FTYPE = 'Artificial Path'",
"fields": ["*"]
}
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.20858764648438, 42.37579287453795],
[ -85.10009765625, 42.37579287453795],
[ -85.10009765625, 42.45436780800864],
[-85.20858764648438, 42.45436780800864],
[-85.20858764648438, 42.37579287453795]
]]
}
})
);
The above command returns JSON like this:
{
"statusCode": 200,
"message": "success",
"data": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-85.18484270344246, 42.444050316443914],
[-85.18675542682136, 42.4428978045579 ],
[-85.18625375256725, 42.44113470334944 ],
[-85.18383951060697, 42.44052407732911 ],
[-85.18192680245832, 42.44167650818921 ],
[-85.18242832103469, 42.44343964609331 ],
[-85.18484270344246, 42.444050316443914]
]]
},
"properties": {
"density": "Rural",
"infrastructureTypes": [],
"popPerSqMi": 49.17739869167168,
"score": 1.7,
"suitableFeatures": ["streams"]
}
},
...
]
}
Generate a suitability surface with any data sources you request. Suitability surfaces are similar to computing risk, but allow you to inject features into the risk computation that are consistent with your concept of operations.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/suitability
Scope: airhub-api/suitability.generate
Why POST
and not GET
?
GeoJSON strings can often become quite long depending on the complexity of the coordinates.
We use a POST
to overcome any browser url length limitations when using this API in the browser.
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
geojson | GeoJSON formatted geometry. Available geometries may be a point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 10 nautical miles. |
uavWeight |
string | Describes the weight of the drone. |
uavType |
string | Describes the wing type of the drone. |
pilotControl |
string | Describes how the drone will be piloted for the operation. |
losType |
string | Describes how the pilot will be observing the drone fly during the operation (if at all). |
maxAltitude |
number | An integer representing the altitude of the flight in feet. Must be at least 100 feet. |
features |
object | Key-value pairs with the key being a metadata source and the value being an object of parameters to the source. |
resolution |
number | The resolution of the output surface. A larger number means finer granularity. |
index |
bool | Instead of returning GeoJSON, return the indices of the hexagons. |
Route
Route
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/route' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"losType": "BVLOS",
"maxAltitude": 100,
"pilotControl": "SINGLE_PILOT",
"resolution": 9,
"returnCorridor": true,
"returnNetwork": true,
"returnSurface": true,
"uavType": "HYBRID",
"uavWeight": "LIMITED",
"geometry": {
"coordinates": [
[
-83.237915,
42.316416
],
[
-83.205643,
42.304991
]
],
"type": "MultiPoint"
},
"features": {
"streams": {
"weight": 0.5
}
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/route");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"losType": "BVLOS",
"maxAltitude": 100,
"pilotControl": "SINGLE_PILOT",
"resolution": 9,
"returnCorridor": true,
"returnNetwork": true,
"returnSurface": true,
"uavType": "HYBRID",
"uavWeight": "LIMITED",
"geometry": {
"coordinates": [
[
-83.237915,
42.316416
],
[
-83.205643,
42.304991
]
],
"type": "MultiPoint"
},
"features": {
"streams": {
"weight": 0.5
}
}
})
)
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": {
"corridor": [
"892ab2cdcafffff",
"892ab2cdddbffff",
"892ab2cddc3ffff",
"892ab2cddd7ffff",
"892ab2cdd9bffff",
"892ab2cdd83ffff",
"892ab2cdd87ffff",
"892ab2cce4bffff",
"892ab2cce43ffff",
"892ab2cce47ffff",
"892ab2cce73ffff"
],
"network": {
"type": "MultiLineString",
"coordinates": [
[
[-83.22132621971751,42.306309536604154],
[-83.20827680443215,42.30771086507444]
],
...
]
},
"route": {
"type": "LineString",
"coordinates": [
[-83.237915,42.316416],
[-83.23412143346106,42.313110874461174],
[-83.22695599604445,42.31115564289149],
[-83.22456763561581,42.31050380530632],
[-83.21262672407333,42.30724391460332],
[-83.21023871992755,42.30659179593648],
[-83.205643,42.304991]
]
},
"surface": {
"892ab2cc267ffff": {
"density": "Suburban",
"infrastructureTypes": [],
"popPerSqMi": 418.00788887920925,
"score": 1,
"suitableFeatures": [
"streams"
]
},
...
}
}
}
Returns a GeoJSON LineString representing a straight line optimizing risk and distance.
The MultiPoint input object will be used as the origin and destination for the route.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/route
Scope: airhub-api/route.create
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
The POST
body's geometry
property is expected to be a GeoJSON MultiPoint. If more than 100 points are supplied, the API will reject the request.
Parameter | Type | Description |
---|---|---|
geometry |
GeoJSON MultiPoint | An ordered list of points for the route. |
uavWeight |
string | Describes the weight of the drone. |
uavType |
string | Describes the wing type of the drone. |
pilotControl |
string | Describes how the drone will be piloted for the operation. |
losType |
string | Describes how the pilot will be observing the drone fly during the operation (if at all). |
maxAltitude |
number | An integer representing the altitude of the flight in feet. Must be at least 100 feet. |
features |
object | Key-value pairs with the key being a metadata source and the value being an object of parameters representing suitable/unsuitable features. |
resolution |
number | The resolution of the output surface. A larger number means finer granularity. |
returnCorridor |
boolean | If true , return the hex corridor taken by the algorithm. |
returnNetwork |
boolean | If true , return the network considered by the algorithm. |
returnSurface |
boolean | If true , return the suitability surface considered by the algorithm. |
Elevation
Elevation
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v1/elevation' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'Authorization: Bearer <your-access-token>' \
--header 'x-api-key: <your-api-key>' \
--data-raw '{
"zUnits": "ft",
"inVDatum": "ellipsoid",
"geometry": {
"type": "Point",
"coordinates":
[
-83.69,
42.67,
1300
]
}
}'
const xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE && this.status === 200) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://airhub-api-sandbox.airspacelink.com/v1/elevation");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", "Bearer <your-access-token>");
xhr.setRequestHeader("x-api-key", "<your-api-key>");
xhr.send(
JSON.stringify({
"zUnits": "ft",
"inVDatum": "ellipsoid",
"geometry": {
"type": "Point",
"coordinates":
[
-83.69,
42.67,
1300
]
}
})
)
Make sure to replace
<your-xxx>
with your applicable values.The above command returns JSON structured like this:
{
"statusCode": 200,
"message": "success",
"data": {
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"properties": {
"AGL": 302.0,
"geoidHeight": -110.0,
"terrainNAVD88": 1108,
"terrainWGS84": 998.0,
"units": "ft",
"zNAVD88": 1410.0,
"zWGS84": 1300.0
},
"geometry": {
"type": "Point",
"coordinates": [
-83.69,
42.67
]
}
}
]
}
}
Elevation, altitude, and other "z" measurements from different sources (ex. GPS, digital elevation models) can be measured with different vertical datum (reference point), resulting in incompatible measurements. UAS regulation uses "Above Ground Level" as its height measurement, which requires establishing ground level. This data service converts elevation and altitude measurements between common vertical datum: ellipsoidal (WGS84/common GPS) and orthometric (US only - NAVD88/measurement above geoid). Above Ground Level (AGL) is calculated based on the difference between input z value and surface elevation in compatible datum. GEOID12B and US Geological Survey 1/3 arcsec DEM are used as sources. Returns a GeoJSON feature collection with Above Ground Level, surface/terrain elevation, converted z altitude, and geoid height.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v1/elevation
Scope: airhub-api/elevation
Required Headers
Parameter | Description |
---|---|
Content-Type |
application/json;charset=UTF-8 |
Authorization |
Authorization bearer accessToken generated in Authentication step |
x-api-key |
API key supplied to you by Airspace Link |
JSON POST Body
Parameter | Type | Description |
---|---|---|
geometry |
geojson | GeoJSON formatted geometry. Available geometries may be a point, multipoint, or line in [longitude, latitude, z] . |
zUnits |
string | Units for vertical measurements input and output. Use ft or m . |
inVDatum |
string | Vertical datum system for input z values. ellipsoid for WGS84 or orthometric for NAVD88. |
Errors
The AirHub API uses the following error codes:
Error Code | Meaning |
---|---|
400 |
Bad Request: Your request is invalid. |
401 |
Unauthorized: Your API key is wrong or your accessToken is malformed. |
403 |
Forbidden: The resource requested is not available to your user or your request headers/parameters are malformed. |
404 |
Not Found: The specified resource could not be found. |
405 |
Method Not Allowed: You tried to access a resource with an invalid method. |
406 |
Not Acceptable: You requested a format that isn't json. |
410 |
Gone: The resource has been removed from our servers. |
422 |
Unprocessable: The inputs could not be processed. |
500 |
Internal Server Error: We had a problem with our server. Try again later or adjust your request. |
503 |
Service Unavailable: We're temporarily offline for maintenance. Please try again later. |