Introduction

WindBorne balloons are capable of totally flexible altitude control between surface and stratosphere. In general, the flight profiles can be decomposed into periods of ascent and descent, typically at speeds of 1-3 m/s, and periods of mostly level flight. An example altitude profile is shown in the image below.

The standard measurement set recorded during flight consists of GPS wind, barometric pressure, ambient temperature, and relative humidity, along with GPS position and geopotential height. Downlinked sensor data undergoes quality control on the ground to eliminate erroneous or excessively noisy data.

Measurements are recorded at 10 second intervals during flight, and downlinked in packets at a configurable period, typically <= 7 minutes. Sensor quality control takes a further 5 mins (average) to 15 mins (worst case) after receipt of the packet. All other steps in the data delivery process take under 1 minute cumulatively, resulting in an average latency of approx. 10 mins and a worst case of approx. 25 mins between measurement and delivery of quality-controlled observations being made available in the API.

The WindBorne API is designed to be predictable, performant, and easy to use.

Need access?

Email data@windbornesystems.com

Just trying to view Skew-T plots?

Skip down to data viewer documentation
Base URL
Example flight profile

Data Viewer

WindBorne provides a data viewer in addition to its API. This data viewer shows allows selecting which data to view, then plotting the data on a skew-t plot, the ground track on a map, and the flight profile on a graph.

You can select a mission by clicking on a line on the map (which will also select a sounding time), or clicking the edit icon next to the mission name. Once a mission is selected, you can set the sounding time by (a) using the input at the top (b) clicking on the altitude graph (c) clicking a point on a line on the map or (d) using the arrow keys to go to the previous / next sounding.

You can also set a variety of overlays, such as satellite data, via clicking on the gear icon on the map.

If you need access, email data@windbornesystems.com

A screenshot of WindBorne's sounding viewer
A screenshot of WindBorne's sounding viewer

Authentication

WindBorne uses API keys to authenticate API requests. If an API request is not properly authenticated, it will fail. To get an API key, email data@windbornesystems.com.

You should have an API key and a client id. Conceptually, you can think of your client id as a username and your API key as your password. You should make sure to keep your API key safe and secure.

To authenticate, pass HTTP basic auth headers in the GET request with username YOUR_CLIENT_ID and password YOUR_API_KEY. This follows RFC 7617; ie, as is standard, the credentials are colon-separated then base-64 encoded; many HTTP libraries will do this for you.

Using JWTs from a key server

Example

Observations

The observations endpoint allows fetching data via an authenticated GET request. It accepts the following query string parameters:

NameTypeDescription
sincenumericA unix timestamp (seconds since unix epoch) for when to start fetching data from. The API will return data that is either new or has been updated since this timestamp. We recommend using this for pagination.
min_timenumericA unix timestamp (seconds since unix epoch) for filtering data. If provided, will only return observations taken at a timestamp greater than or equal to this value. In contrast to since, which is used for pagination, this is used for filtering.
max_timenumericA unix timestamp (seconds since unix epoch) for filtering data. If provided, will only return observations taken at a timestamp less than or equal to this value.
include_idsbooleanIf true, will include the id of the observation and the mission that collected it.
include_mission_namebooleanIf true, will include the human name of the mission that collected the observation.
include_updated_atbooleanIf true, will include when the observation was last updated in the database (eg from a re-processing of sensor data).
mission_idstringIf set, will filter to only missions with this ID. IDs can be found via the flying missions route.
min_latitudenumericIf provided, will only return observations with a latitude greater than or equal to this value.
max_latitudenumericIf provided, will only return observations with a latitude less than or equal to this value.
min_longitudenumericIf provided, will only return observations with a longitude greater than or equal to this value.
max_longitudenumericIf provided, will only return observations with a longitude less than or equal to this value.

Observations are added when new data comes out. Additionally though, they can be updated if we ever reprocess data. This can happen if, for example, we notice that our quality-control pipeline was too aggressive about filtering out data and tune the thresholds on it. This is a relatively rare occurrence, but does sometimes happen. This is also why the since parameter and the min_time parameter are different: the since parameter says "give me all changes since __, be it new data or updates to existing data", whereas the min_time parameter restricts that to observations taken at or after that timestamp.

It returns the following:

NameTypeDescription
has_next_pagebooleanIndicates where or not there is a subsequent page of data.
next_pagestringThe url for the next page of data. If there is no subsequent page (ie, has_next_page is false), this will be null.
next_sincenumericA unix timestamp that can be used in the since query string parameter when fetching subsequent pages, indicating where the data for the next page starts. This is still provided even when there is no next page so that the client may poll the endpoint without concern for missing new data.
observationsArray<Observation>An array of data points; see below for description of data point structure. In some limited cases, this may have zero elements.

Observation data points are of the form:

NameTypeDescription
altitudenumericAltitude in meters
humiditynumericRelative humidity, in percent
specific_humiditynumericSpecific humidity, in mg/kg
latitudenumericLatitude. Note that this is reported at lower frequency (once per downlink packet), then broadcast to the other measurements, and thus will be the same for multiple observations in a row.
longitudenumericLongitude. Note that this is reported at lower frequency (once per downlink packet), then broadcast to the other measurements, and thus will be the same for multiple observations in a row.
pressurenumericPressure in hectopascals
speed_unumericWind speed in direction of increasing longitude in meters per second. Note: for compatibility reasons, this is additionally provided as speed_y.
speed_vnumericWind speed in direction of increasing latitude in meters per second. Note: for compatibility reasons, this is additionally provided as speed_x.
temperaturenumericTemperature in degrees celsius.
timestampnumericA unix timestamp (seconds since unix epoch) for when the measurement was taken
idnumeric, optionalThe unique id of this specific observation. Only present when include_ids is set to true.
mission_idstring, optionalThe unique id of the mission that collected this observation. Only present when include_ids is set to true.
mission_namestring, optionalThe human name of the mission that collected this observation. Only present when include_mission_name is set to true.
updated_atnumeric, optionalA unix timestamp (seconds since unix epoch) for when the observation was last updated in the database (eg from a re-processing of sensor data). Only present when include_updated_at is set to true.

Endpoints
Sample Response

Observations polling example

Frequently you will need to fetch data continuously, rather than only requesting a specific page. We recommend doing so as follows:

  1. Fetch a page of data, storing next_since
  2. If has_next_page is false, sleep for your polling interval (we recommend a polling interval of one minute). Otherwise, proceed immediately.
  3. Set the since query string parameter of the following request to next_since.
  4. Repeat!
Example

Super observations

WindBorne observations are high-frequency, at once every ten seconds, but as our balloons are comparatively slow-moving (relative to the distances at which weather changes), this may be excessive for some applications. Indeed, previous data assimilation experiments have suggested that reducing the resolution of the dataset helps with impact. "Superobbing" averages observations in a smart way to reduce effective resolution while preserving key data attributes.

Our current algorithm for superobbing the data is straightforward, having two parameters corresponding to maximum “bucket” size in altitude (a max of 100m) and in time (a max of 30 minutes). The algorithm accumulates observations sequentially until an observation doesn’t satisfy either threshold; usually the altitude threshold is triggered, but when flying in a stable-altitude mode (where the balloon might not deviate by more than tens of meters over the course of many hours) the time condition might apply. When that happens, the previous observations get averaged into a single “superobbed” observation, and a new bucket starts.

Whenever a new observation comes out for a mission, it checks whether it fits into the last superobservation bucket (ie, is less than half an hour from the start and is no more than 100m different in altitude). If the observation does fit into that superobservation bucket, it updates the superobservation. If it doesn't, it creates a new superobservation. As such, superobservations are regularly updated. Given this, we strongly recommend passing include_ids and merging based on the ID.

The super observations endpoint is identical in behavior to the normal observations endpoint, and allows fetching data via an authenticated GET request. It accepts the following query string parameters:

NameTypeDescription
sincenumericA unix timestamp (seconds since unix epoch) for when to start fetching data from. The API will not return data from before this timestamp.
min_timenumericA unix timestamp (seconds since unix epoch) for filtering data. If provided, will only return observations taken at a timestamp greater than or equal to this value. In contrast to since, which is used for pagination, this is used for filtering.
max_timenumericA unix timestamp (seconds since unix epoch) for filtering data. If provided, will only return observations taken at a timestamp less than or equal to this value.
mission_idstringIf set, will filter to only missions with this ID. IDs can be found via the flying missions route.
include_idsbooleanIf true, will include the id of the super observation and the mission that collected it.
include_mission_namebooleanIf true, will include the human name of the mission that collected the observation.
include_updated_atbooleanIf true, will include when the observation was last updated in the database.

It returns the following:

NameTypeDescription
has_next_pagebooleanIndicates where or not there is a subsequent page of data.
next_pagestringThe url for the next page of data. If there is no subsequent page (ie, has_next_page is false), this will be null.
next_sincenumericA unix timestamp that can be used in the since query string parameter when fetching subsequent pages, indicating where the data for the next page starts. This is still provided even when there is no next page so that the client may poll the endpoint without concern for missing new data.
observationsArray<SuperObservation>An array of data points; see below for description of data point structure. In some limited cases, this may have zero elements.

Super observation data points are of the form:

NameTypeDescription
altitudenumericAltitude in meters
humiditynumericRelative humidity, in percent
specific_humiditynumericSpecific humidity, in mg/kg
latitudenumericLatitude. Note that this is reported at lower frequency (once per downlink packet), then broadcast to the other measurements, and thus will be the same for multiple observations in a row.
longitudenumericLongitude. Note that this is reported at lower frequency (once per downlink packet), then broadcast to the other measurements, and thus will be the same for multiple observations in a row.
pressurenumericPressure in hectopascals
speed_unumericWind speed in direction of increasing longitude in meters per second. Note: for compatibility reasons, this is additionally provided as speed_y.
speed_vnumericWind speed in direction of increasing latitude in meters per second. Note: for compatibility reasons, this is additionally provided as speed_x.
temperaturenumericTemperature in degrees celsius.
timestampnumericA unix timestamp (seconds since unix epoch) for when the measurement was taken
idnumeric, optionalThe unique id of this specific observation. Only present when include_ids is set to true.
mission_idstring, optionalThe unique id of the mission that collected this observation. Only present when include_ids is set to true.
mission_namestring, optionalThe human name of the mission that collected this observation. Only present when include_mission_name is set to true.
updated_atnumeric, optionalA unix timestamp (seconds since unix epoch) for when the observation was last updated in the database (eg from a re-processing of sensor data). Only present when include_updated_at is set to true.

Endpoints
Sample Response

Utilities

JSON acts as a flexible format to transfer data without making assumptions about how it will be used. However, end applications may prefer to receive data in a different format; to that end, WindBorne has developed several internal utilities for re-processing JSON data. Upon request, we can package those utilities to be used on systems outside our own. Potential utilities we could package include:

Superobbing

WindBorne provides an endpoint for superobbed data. However, our superobbing algorithm is subject to two parameters, the max time and the max altitude range that should be averaged in a given bucket. To that end, we could package a superobbing utility if desired to allow for customization.

Conversion to NetCDF

We generate NetCDF4 files based on a template provided to us by NOAA. These expose the various observations in the @ObsValue group, standard deviations in @ObsError, and assorted other variables (such as height, latitude, longitude, date, timestamp, flight number) in @MetaData.

Conversion to PrepBUFR

We’re also able to generate PrepBUFR files that have been used to assimilate data into GFS by way of GSI. It uses codes 120 and 130, corresponding to rawinsondes. However, since our balloons are drifting in space, rather than doing a single profile up and down, we generate a “profile” for each observation, and so it doesn’t quite look like a traditional rawinsonde PrepBUFR file.

A second thing to note is that PrepBUFR implicitly uses pressure as the coordinate axis, and to the best of our understanding, height doesn’t get assimilated. As WindBorne data prior to a hardware revision does not have barometric data above 11-12 km, we therefore recommend assimilating with height as the coordinate axis so that stratospheric points are included. Geometric/geopotential height is always available.

Need to use these utilities?

These utilities are distributed upon request. Please email data@windbornesystems.com.

Flying missions

This endpoint allows listing the balloons that are currently flying. It accepts no query parameters.

It returns the following:

NameTypeDescription
missions[Mission]An array of balloon information

A mission is of the form:

NameTypeDescription
idstringA UUID that uniquely identifies the mission
namestringThe name of the mission, of the form W-Number (SerialNumber LaunchSite)
numbernumericThe number of the mission
launch_timestringThe ISO8601 timestamp of when the balloon was launched
landing_timenullnull, as this route returns only flying balloons. This is property is provided for consistency with other APIs.

Endpoints
Sample Response

Mission launch site

You can get the mission that collected a given observation by passing in include_ids. This endpoint allows finding the site from which that mission was launched. It accepts no query parameters, but requires a mission id to be passed into the url. For example, to query the launch site for mission 494f8cb2-5fed-4c81-b3c4-5eacaa2ba4e0, you would make a request to /api/v1/missions/494f8cb2-5fed-4c81-b3c4-5eacaa2ba4e0/launch_site.json.

It returns the following:

NameTypeDescription
launch_siteLaunchSiteThe launch site from which the mission was launched

A launch site is of the form:

NameTypeDescription
idstringA UUID that uniquely identifies the launch site
latitudenumericLatitude from which the mission was launched
longitudenumericLongitude from which the mission was launched

Endpoints
Sample Response

Predicted flight path

This endpoint allows getting the predicted flight path for a given mission. It accepts no query parameters, but requires a mission id to be passed into the url. For example, to query the launch site for mission 494f8cb2-5fed-4c81-b3c4-5eacaa2ba4e0, you would make a request to /api/v1/missions/494f8cb2-5fed-4c81-b3c4-5eacaa2ba4e0/prediction.json.

This prediction will start at the balloon's current location; the first point represents where the balloon is right now. It will extend three days into the future. Note also that there is variation in the exact altitudes the balloon will fly at as well as how winds at those altitudes compared to forecasted winds. As such, the prediction has inherent uncertainty.

It returns the following:

NameTypeDescription
prediction[Point]An array of points along the predicted flight path

A prediction point is of the form:

NameTypeDescription
timestringAn ISO 8601 timestamp of when the balloon will be at this location
latitudenumericLatitude of where the balloon will be for this point
longitudenumericLongitude of where the balloon will be for this point
altitudenumericAltitude in meters of where the balloon will be for this point

Endpoints
Sample Response