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. |
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 linking applications. Allows the creation of a UAS operation that can be linked into LAANC authorization app. |
route.create |
Allows the creation of UAS waypoints that navigate around ground based hazards and risks. |
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"
}'
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",
})
);
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",
"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 | Filters advisories that are active at the same time as, or after startTime . Send as YYYY-MM-DDThh:mmZ . |
endTime |
string | Filters advisories that are active at the same time as, or before endTime . Send as YYYY-MM-DDThh:mmZ |
maxAltitude |
integer | The maximimum altitude anticipated for the operation. This helps to determine FAA restrictions. |
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 |
Get Advisories v4
curl --location --request POST 'https://airhub-api-sandbox.airspacelink.com/v4/advisory/query' \
--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": [-84.48662507347596, 34.03243481512578]
},
"altitudeUpper": 500,
"altitudeLower": -100,
"startTime": "2022-06-01T23:39:00Z",
"endTime": "2022-06-30T23:39:00Z",
"geoIDs": ["1300021", "13"]
}'
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/v4/advisory/query");
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: [-84.48662507347596, 34.03243481512578]
},
altitudeUpper: 500,
altitudeLower: -100,
startTime: "2022-06-01T23:39:00Z",
endTime: "2022-06-30T23:39:00Z",
geoIDs: ["1300021", "13"]
})
);
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):
{
"statusCode": 200,
"message": "success",
"data": {
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-84.48662507347596, 34.03243481512578],
[-84.48662507347596, 33.973213117475744],
[-84.38990872353155, 33.973213117475744],
[-84.38990872353155, 34.03243481512578],
[-84.48662507347596, 34.03243481512578]
]]
},
"properties": {
"advisoryCategory": "emergency",
"altitudeLower": 0,
"altitudeUpper": 400,
"contactEmail": null,
"contactPhone": null,
"countryGeoID": "1000",
"createdBy": "auth0|60147bba7fc91400699b745f",
"endTime": "2022-06-30T23:39:00Z",
"geoID": "1300021",
"id": "79c5620f-81d2-43ad-af38-91bb8deaf7b8",
"lastEditedBy": "auth0|61b78959f995f80069dd0d51",
"name": "Test MPH",
"ovn": null,
"published": true,
"referenceNumber": null,
"startTime": "2022-06-05T23:39:00Z",
"tags": [],
"timezoneName": "America/New_York",
"url": null,
"version": 0
}
}
],
"type": "FeatureCollection"
}
}
Find advisories that intersect the input geometry
.
HTTP Request
POST https://airhub-api-sandbox.airspacelink.com/v4/advisory/query
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. Must be a point, line, or polygon. The resulting bounding box of the geometry can't have a side length greater than 100 miles. |
altitudeUpper |
number | Filter advisories that are flying at or below the specified altitude. |
altitudeLower |
number | Filter advisories that are flying at or above the specified altitude. |
startTime |
string | Filters advisories that are active at the same time as, or after startTime . Send as YYYY-MM-DDThh:mmZ . |
endTime |
string | Filters advisories that are active at the same time as, or before endTime . Send as YYYY-MM-DDThh:mmZ . |
geoIDs |
string[] | Filter advisories that are present in the following geo-IDs. |
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 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 Linking
Successfully creating an operation will return a uuid that may be used to retrieve the operation within the AirHub Launch LAANC application. The following is a sample 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 link 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) |
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. |
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. |
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. |