Schemas · API reference
Body_upload_flight_v1_flights_post
| Name | Type | Description |
file required | string (binary) | IGC, GPX or FIT file, byte for byte as recorded; the format is detected from the content |
external_pilot_hash required | string | HMAC-SHA256 of the client's pilot id, 64 hex characters; the HMAC key stays with the client ^[0-9a-fA-F]{64}$
|
consent_version required | integer | Version of the consent text the pilot accepted 0 ≤ x ≤ 32767
|
source required | "kunduzo" | Uploading platform |
external_ref | string | null | Client's own flight reference 1–200 chars
|
sport | Sport | Sport of the flight (optional, default paragliding); stored with a new flight. Shared layers count only paragliding flights for nowdefault "paragliding" |
ConsentReceipt
What the request changed. No pilot identity is returned.
| Name | Type | Description |
event required | "withdrawn" | "granted" | |
scope required | "pilot" | "flights" | |
recorded required | boolean | A new consent event was written; false: it was already in effect (repeated request), nothing changed |
flights_in_scope required | integer | Flights the request covers (deleted ones aside); 0 for a pilot-wide withdrawal, which only covers later uploads |
flights_affected required | integer | Withdrawal by list: flights that counted towards the shared layers and no longer do; 0 for a pilot-wide withdrawal. Grant: flights not in the layers now that are checked again (consent and quality) |
received_at required | string (date-time) | Time the request was recorded (UTC) |
layers_updated_by required | string (date-time) | null | Withdrawal by list: the layers no longer contain these flights by this time (received_at + 24 h); null for a pilot-wide withdrawal (no flight leaves the layers) and for a grant |
ConsentRequest
Pilot-wide (no flight_ids) or for the listed flights of that pilot.
| Name | Type | Description |
external_pilot_hash required | string | HMAC-SHA256 of the client's pilot id, 64 hex characters; the same value as external_pilot_hash of the uploads^[0-9a-fA-F]{64}$
|
consent_version required | integer | Version of the consent text the pilot acted on 0 ≤ x ≤ 32767
|
source required | "kunduzo" | Platform the pilot gave or withdrew it on |
flight_ids | array<string (uuid)> | null | Updraft flight ids (flight_id of the upload response) of this pilot. Omitted: pilot-wide; a pilot-wide withdrawal covers the flights uploaded from now on (earlier flights stay in the anonymous aggregates), a pilot-wide grant every flight1–1000 items
|
DeletionReceiptOut
What the request recorded. No pilot identity and no flight id is returned.
| Name | Type | Description |
deletion_id required | string (uuid) | null | The deletion request covering this one (GET /v1/deletions/{id}): new when recorded, else the earlier request that already covers it; null when there is nothing to delete (pilot unknown to Updraft or already erased) |
scope required | "pilot" | "flights" | |
recorded required | boolean | A new deletion was recorded; false: everything asked was already deleted or being deleted (repeated request), nothing changed |
flights_in_scope required | integer | With flight_ids: the listed flights; pilot-wide: the flights of the covering request |
status required | "pending" | "completed" | completed: raw files, fix files and thermal events are gone |
received_at required | string (date-time) | When the covering request was received (UTC) |
layers_updated_by required | string (date-time) | The published layers no longer contain these flights by this time (received_at + 24 h) |
DeletionRequestBody
Pilot-wide (no flight_ids) or the listed flights of that pilot.
| Name | Type | Description |
external_pilot_hash required | string | HMAC-SHA256 of the client's pilot id, 64 hex characters; the same value as external_pilot_hash of the uploads^[0-9a-fA-F]{64}$
|
source required | "kunduzo" | Platform the pilot asked on |
flight_ids | array<string (uuid)> | null | Updraft flight ids (flight_id of the upload response) of this pilot. Omitted: pilot-wide, every flight of the pilot and the pilot's link to the client's pilot id1–1000 items
|
DeletionStatusOut
Progress of one deletion request. No pilot identity and no flight id.
| Name | Type | Description |
deletion_id required | string (uuid) | |
scope required | "pilot" | "flights" | |
status required | "pending" | "completed" | |
flights required | integer | Flights the request deletes |
flights_completed required | integer | Of these, flights whose files are gone |
received_at required | string (date-time) | |
completed_at required | string (date-time) | null | Every flight done (pilot-wide: also the pilot's masks and link); null while pending |
layers_updated_by required | string (date-time) | received_at + 24 h |
ErrorBody
| Name | Type | Description |
code required | string | |
detail required | string | |
errors | array<object> | null | |
FlightReceipt
The stored flight. Pilot identity, track and altitude are never returned.
| Name | Type | Description |
flight_id required | string (uuid) | uuid5 of the file's SHA-256; same bytes, same id |
status required | "accepted" | "duplicate" | accepted (202): new flight, queued; duplicate (200): already stored |
igc_sha256 required | string | SHA-256 of the uploaded bytes (IGC, GPX or FIT), lower case hex |
flown_on required | string (date) | Local (Europe/Istanbul) date of the first valid fix |
consent_version required | integer | Consent text version stored with the flight |
sport required | Sport | Sport stored with the flight; a duplicate keeps the sport of the first upload. Shared layers count only paragliding flights for now |
processing required | "pending" | "processed" | "failed" | |
usable_for_layers required | boolean | Counts towards shared layers (consent and quality); false until processed |
received_at required | string (date-time) | Time this upload was received (UTC) |
ForecastCell
| Name | Type | Description |
lat required | number | Latitude of the 0.25° cell centre the forecast is for |
lon required | number | Longitude of the cell centre |
ForecastInfo
| Name | Type | Description |
source required | string | null | Forecast service (open-meteo); null when off |
model required | string | null | Weather model (icon_eu); null when off |
cell required | ForecastCell | |
fetched_at required | string (date-time) | null | When our forecast server produced this forecast (UTC); the model run is at most about 9 hours older. Null without a forecast |
attribution required | string | Required data attribution (CC BY 4.0) |
Health
| Name | Type | Description |
status required | "ok" | |
version required | string | |
IncidentRegion
| Name | Type | Description |
id required | string (uuid) | |
slug required | string | |
name required | string | |
IncidentType
docs/02 features; the same list as migration 0013 (a test compares).
"collision_obstacle" | "takeoff_problem" | "landing_problem" | "rotor_turbulence" | "power_line" | "airspace" | "other"
MultiPolygonGeometry
| Name | Type | Description |
type required | "MultiPolygon" | |
coordinates required | array<array<array<[number, number]>>> | Polygons → rings → [longitude, latitude] (WGS 84), simplified |
NoticeText
| Name | Type | Description |
tr required | string | |
en required | string | |
OpenDataAttribution
| Name | Type | Description |
tr required | string | |
en required | string | |
OpenDataFileInfo
| Name | Type | Description |
name required | string | File name, e.g. sites.geojson |
layer required | string | null | thermals_r7, thermals_r9, sites, hazards, skyways; null for README.md and LICENSE.txt |
format required | string | geoparquet (GeoParquet 1.1), geojson, markdown (README), text (LICENSE) |
rows required | integer | null | Features in the layer; null for documents |
size_bytes required | integer | |
sha256 required | string | SHA-256 of the file, 64 lowercase hex characters |
OpenDataReleaseInfo
| Name | Type | Description |
year required | integer | Release year (the content is the build day's cumulative state) |
generated_on required | string (date) | UTC day the package was built |
open_data_version required | integer | Package format version |
license_id required | string | CC-BY-4.0 |
license_url required | string | |
attribution required | OpenDataAttribution | Required credit line (docs/29 §2) |
thresholds required | OpenDataThresholds | Privacy thresholds at build time |
files required | array<OpenDataFileInfo> | Package files (manifest.json not listed) |
OpenDataThresholds
| Name | Type | Description |
min_pilots_grid required | integer | Distinct pilots behind every thermal cell |
min_pilots_features required | integer | Distinct pilots behind every site and hazard |
min_pilots_skyways required | integer | Distinct pilots behind every skyway |
PackFileInfo
One PMTiles file; a MapLibre source of the same name reads it as pmtiles://.
| Name | Type | Description |
kind required | "base" | "contours" | "terrain" | "hillshade" | "power" | Base map source the file replaces offline (docs/02 §6) |
file required | string | File name, {kind}.pmtiles |
url required | string | Time-limited GET URL (until expires_at); supports HTTP range requests |
size_bytes required | integer | |
sha256 required | string | SHA-256 of the file, 64 lowercase hex characters |
tile_type required | "mvt" | "webp" | |
tile_compression required | "gzip" | "none" | |
min_zoom required | integer | |
max_zoom required | integer | Highest zoom in the file; MapLibre over-zooms beyond it |
tile_count required | integer | |
source_build_id required | string | Base map build the file was cut from |
attribution required | string | Attribution of the source (may hold HTML links) |
PackInfo
| Name | Type | Description |
region required | string | |
name required | string | null | Region name when cut from regions |
pack_version required | string | YYYYMMDD[-n]; a larger value is a newer pack. Compare it with the downloaded one to decide whether to download again |
created_at required | string (date-time) | |
bbox required | [number, number, number, number] | [west, south, east, north] degrees, WGS 84: every tile meeting it is in 4–4 items
|
size_bytes required | integer | Sum of the files |
max_zoom required | integer | |
zoom_trimmed required | boolean | True when zoom levels were dropped to stay under the size limit |
files required | array<PackFileInfo> | |
attribution required | string | Credit line to show with the offline map |
expires_at required | string (date-time) | The file URLs stop working at this time (UTC) |
PilotMaskCreate
home: a circle (center, radius_m optional). custom: a circle (center +
radius_m) or a polygon.
| Name | Type | Description |
external_pilot_hash required | string | HMAC-SHA256 of the client's pilot id, 64 hex characters; the same value as external_pilot_hash of the uploads^[0-9a-fA-F]{64}$
|
source required | "kunduzo" | Platform the pilot set the mask on |
kind required | "home" | "custom" | home: the pilot's home (at most one per pilot); custom: another place |
center | PilotMaskPoint | null | Centre of a circle |
radius_m | integer | null | Circle radius in metres. home: at least the home mask default (privacy settings, 2000) and the default when omitted; custom: 200-10000, required with center1 ≤ x ≤ 10000
|
polygon | PilotMaskPolygonIn | null | custom only, instead of a circle; area between a 200 m and a 10000 m circle's |
PilotMaskList
| Name | Type | Description |
items required | array<PilotMaskOut> | The pilot's masks, oldest first |
max_masks required | integer | Masks a pilot may have |
PilotMaskOut
One mask of the pilot, with its geometry (for the client's own pilot only).
| Name | Type | Description |
id required | string (uuid) | |
kind required | "home" | "custom" | |
center required | PilotMaskPoint | null | home: the circle centre; custom: null |
radius_m required | integer | null | home: the circle radius; custom: null |
polygon required | PilotMaskPolygon | |
area_km2 required | number | Area of the stored geometry, 3 decimals |
created_at required | string (date-time) | |
PilotMaskPoint
| Name | Type | Description |
lat required | number | Latitude (WGS84, degrees) -90 ≤ x ≤ 90
|
lon required | number | Longitude (WGS84, degrees) -180 ≤ x ≤ 180
|
PilotMaskPolygon
| Name | Type | Description |
type required | "Polygon" | |
coordinates required | array<array<array<number>>> | The stored geometry, [lon, lat] with 6 decimals (a circle as its polygon) |
PilotMaskPolygonIn
GeoJSON Polygon with one ring (no holes), positions [lon, lat].
| Name | Type | Description |
type required | "Polygon" | |
coordinates required | array<array<[number, number]>> | One closed ring of 4-500 [lon, lat] positions (last = first); a valid, non self-intersecting polygon1–1 items
|
PilotMaskReceipt
What the change recorded. No pilot identity is returned.
| Name | Type | Description |
mask required | PilotMaskOut | null | The new mask; null after a removal |
removed_id required | string (uuid) | null | The removed mask; null after an addition |
flights_affected required | integer | The pilot's flights that are processed again with the changed masks |
received_at required | string (date-time) | Time the change was recorded (UTC) |
layers_updated_by required | string (date-time) | The published layers follow the change by this time (received_at + 24 h) |
PointGeometry
| Name | Type | Description |
type required | "Point" | |
coordinates required | [number, number] | [longitude, latitude], WGS 84 2–2 items
|
PublicIncident
| Name | Type | Description |
id required | string (uuid) | Incident id (stable while the record exists) |
type required | IncidentType | Kind of incident (fixed list, docs/02 features) |
period_from required | string | Start of the period: YYYY or YYYY-MM (never a day)^[0-9]{4}(-(0[1-9]|1[0-2]))?$
|
period_to required | string | End of the period: YYYY or YYYY-MM^[0-9]{4}(-(0[1-9]|1[0-2]))?$
|
precaution required | string | What to do or avoid here (moderator's note) 0–280 chars
|
lon required | number | Longitude, WGS 84, 5 decimals -180 ≤ x ≤ 180
|
lat required | number | Latitude, WGS 84, 5 decimals -90 ≤ x ≤ 90
|
PublicReplay
A shared flight for the 3D replay. No pilot identity, no flight id, no clock time,
no maximum altitude field; masked stretches are gaps between parts.
| Name | Type | Description |
id required | string | The share's public_id |
summary required | PublicReplaySummary | |
parts required | array<PublicReplayPart> | Time ordered; a masked stretch between two parts is not returned |
thermals required | array<PublicReplayThermal> | Thermal events starting inside a part; empty when none |
max_points required | integer | |
PublicReplayPart
One unmasked stretch of the flight as parallel arrays (one entry per point).
| Name | Type | Description |
t required | array<number> | Seconds since the first returned fix (0.1 s) |
lon required | array<number> | |
lat required | array<number> | |
alt_gps required | array<integer | null> | GNSS altitude, m |
alt_baro required | array<integer | null> | Pressure altitude, m; null without sensor |
vario required | array<number | null> | Vertical speed, m/s; null when unknown |
PublicReplaySummary
| Name | Type | Description |
flown_on required | string (date) | Day of the flight (no time of day) |
duration_s required | integer | null | |
distance_m required | integer | null | |
takeoff_name required | string | null | Nearest public (approved) take-off site within 500 m, if any |
landing_name required | string | null | Nearest public (approved) landing site within 500 m |
fix_count required | integer | Visible (unmasked, usable) fixes before thinning |
point_count required | integer | Points returned |
PublicReplayThermal
| Name | Type | Description |
lon required | number | Core of the thermal |
lat required | number | |
start_s required | number | Start, seconds on the same clock as the parts |
duration_s required | integer | |
gain_m required | integer | Height gained, m |
avg_climb_ms required | number | Mean climb rate, m/s |
RegionCollection
| Name | Type | Description |
type required | "FeatureCollection" | |
features required | array<RegionFeature> | |
RegionFeature
| Name | Type | Description |
type required | "Feature" | |
id required | string (uuid) | |
bbox required | [number, number, number, number] | [west, south, east, north] of the full boundary, degrees 4–4 items
|
geometry required | MultiPolygonGeometry | |
properties required | RegionListProperties | |
RegionHourClimb
| Name | Type | Description |
hour_bucket required | integer | Local 2-hour bucket (Europe/Istanbul), 0 = 00:00-02:00 0 ≤ x ≤ 11
|
avg_climb_ms required | number | Mean climb of the thermals in the region, m/s |
RegionIncidentsResponse
| Name | Type | Description |
region required | IncidentRegion | |
incidents required | array<PublicIncident> | Approved incidents of the region, by period, newest first (no ranking) |
RegionListProperties
| Name | Type | Description |
slug required | string | Short name (regions.slug), used in Atlas addresses |
name required | string | |
updated_at required | string (date-time) | Last change of the region (UTC) |
summary required | RegionSummary | null | Null when the profile is not computed yet or withheld after a threshold increase (as GET /v1/regions/{region}/profile) |
RegionMonth
| Name | Type | Description |
month required | integer | Local calendar month 1 ≤ x ≤ 12
|
flyable_days required | integer | Local dates in this month, over all years, on which at least one flight from the region lasted longer than 15 minutes 0 ≤ x
|
years required | integer | Years with flights in this month (divide for a mean) 1 ≤ x
|
RegionProfile
regions.profile (docs/02 regions); values below the thresholds are absent.
| Name | Type | Description |
version required | 1 | Profile rules and shape version |
processing_version required | integer | Fix pipeline version of the inputs 1 ≤ x
|
thresholds required | RegionThresholds | |
support required | RegionSupport | null | Band of pilots behind the region's flights; null below the threshold |
takeoffs required | array<RegionTakeoff> | Approved take-offs in the region |
months required | array<RegionMonth> | Months passing the threshold, in order |
wind required | RegionWind | |
avg_flight_duration_min required | integer | null | Mean airborne time of the region's flights, minutes 0 ≤ x
|
hours required | array<RegionHourClimb> | Hour buckets passing the threshold, in order |
best_hour_bucket required | integer | null | Hour bucket with the highest mean climb 0 ≤ x ≤ 11
|
RegionProfileResponse
| Name | Type | Description |
id required | string (uuid) | |
slug required | string | |
name required | string | |
updated_at required | string (date-time) | Last change of the region (UTC) |
profile required | RegionProfile | null | Null when not computed yet, or withheld after a threshold increase until the next nightly run |
RegionSummary
Headline values of the region profile; every one is absent below the thresholds.
| Name | Type | Description |
support required | RegionSupport | null | Band of pilots behind the region's flights; null below the threshold |
months required | array<integer> | Months (1-12) passing the threshold, in order; a missing month means 'not enough data', not 'not flown' |
dominant_sector required | integer | null | Dominant 850 hPa wind sector (0 = north, 45° steps) 0 ≤ x ≤ 7
|
best_hour_bucket required | integer | null | Local 2-hour bucket with the highest mean climb 0 ≤ x ≤ 11
|
avg_flight_duration_min required | integer | null | Mean airborne time of the region's flights, minutes 0 ≤ x
|
takeoffs required | integer | Approved take-offs in the region (profile list) 0 ≤ x
|
RegionSupport
| Name | Type | Description |
confidence required | "low" | "medium" | "high" | Pilots behind the region's flights: low (3 to 4), medium (5 to 9), high (10 or more) |
min_pilots required | integer | null | At least this many different pilots, floored to 3, 5, 10, 20, 50, 100; the exact count is never returned |
RegionTakeoff
| Name | Type | Description |
id required | string (uuid) | Site id (GET /v1/sites) |
name required | string | null | Name given by a moderator; null if none yet |
lon required | number | Longitude, WGS 84, 6 decimals -180 ≤ x ≤ 180
|
lat required | number | Latitude, WGS 84, 6 decimals -90 ≤ x ≤ 90
|
headings required | array<integer> | null | Launch directions (degrees, 45° sectors) |
elevation_m required | integer | null | Ground elevation in metres (DEM) |
confidence required | "low" | "medium" | "high" | |
min_pilots required | integer | null | |
RegionThresholds
| Name | Type | Description |
min_pilots required | integer | min_pilots_regions used for this profile1 ≤ x
|
min_flights required | integer | min_flights_regions used for this profile1 ≤ x
|
RegionWind
| Name | Type | Description |
dominant_sector required | integer | null | Sector with the most flights when its share is at least 0.3 0 ≤ x ≤ 7
|
sectors required | array<RegionWindSector> | |
RegionWindSector
| Name | Type | Description |
sector required | integer | 850 hPa wind the air came from, 45° sectors, 0 = north 0 ≤ x ≤ 7
|
share required | number | Share of the flights with a known sector 0 ≤ x ≤ 1
|
RouteGraphInfo
| Name | Type | Description |
built_at required | string (date-time) | Last change of the region's precomputed graph |
rule_version required | integer | |
RouteLanding
| Name | Type | Description |
id required | string (uuid) | Public landing (GET /v1/sites) |
name required | string | null | |
lat required | number | |
lon required | number | |
RouteOption
| Name | Type | Description |
id required | string | Stable within the answer: the direction code |
direction required | "n" | "ne" | "e" | "se" | "s" | "sw" | "w" | "nw" | General direction from the take-off |
waypoints required | array<RouteWaypoint> | |
reasons required | array<string> | i18n keys routes.reason.<code> (docs/10 §20) |
RoutesResponse
| Name | Type | Description |
takeoff required | RouteTakeoff | |
date required | string (date) | Local date (Europe/Istanbul) |
hour required | integer | Local hour (Europe/Istanbul) 0 ≤ x ≤ 23
|
timezone required | "Europe/Istanbul" | |
wind required | RouteWind | |
options required | array<RouteOption> | A few options in compass order (clockwise from north); not ranked |
empty required | string | null | i18n key routes.empty.<code> when there is no option; else null |
forecast required | ForecastInfo | |
graph required | RouteGraphInfo | |
notice required | "routes.notice.preflight_only" | i18n key of the fixed notice (docs/04 §3) |
notice_text required | NoticeText | The notice itself: pre-flight planning only; the pilot decides; airspace and legal limits are checked separately |
RouteTakeoff
| Name | Type | Description |
id required | string (uuid) | |
name required | string | null | |
lat required | number | |
lon required | number | |
RouteWaypoint
| Name | Type | Description |
lat required | number | Centre of the thermal cell (H3 r9, about 0.1 km²) |
lon required | number | |
support required | "high" | "medium" | Support band of the cell over all months (high from 10 pilots, medium from 5; never an exact count) |
conditions required | "hour_and_wind" | "wind" | "hour" | "general" | Which breakdown weighted the cell: the day's hour and wind sector, the sector only, the hour only, or the general pattern |
along_skyway required | boolean | The leg arriving here follows a public skyway |
landings required | array<RouteLanding> | Landing alternatives within reach of this waypoint, nearest first |
RouteWind
| Name | Type | Description |
sector required | integer | null | 850 hPa wind sector used for weighting (0 = from the north, 45° slices clockwise); null without a forecast 0 ≤ x ≤ 7
|
direction_deg required | integer | null | 850 hPa wind, from 0 ≤ x ≤ 360
|
speed_ms required | number | null | 850 hPa wind speed, m/s 0 ≤ x
|
ShareOut
The flight's active share. No pilot identity, no flight data.
| Name | Type | Description |
public_id required | string | Unguessable link id: 22 characters of 0-9A-Za-z (about 131 random bits), not derived from the flight |
url_path required | string | Path of the Atlas page, /flights/{public_id}; the client joins it to the Atlas origin |
created_at required | string (date-time) | When this share was opened (UTC) |
ShareRequestBody
The pilot who acts and the consent text version they acted on.
| Name | Type | Description |
external_pilot_hash required | string | HMAC-SHA256 of the client's pilot id, 64 hex characters; the same value as external_pilot_hash of the upload. The flight must be this pilot's^[0-9a-fA-F]{64}$
|
consent_version required | integer | Version of the consent text the pilot shared (or stopped sharing) under; stored with the public_replay consent event0 ≤ x ≤ 32767
|
source required | "kunduzo" | Platform the pilot acted on |
Site
| Name | Type | Description |
type required | "Feature" | |
id required | string (uuid) | |
geometry required | PointGeometry | |
properties required | SiteProperties | Public attributes of a site. Never: pilot identity, flights, exact pilot count. |
SiteCollection
| Name | Type | Description |
type required | "FeatureCollection" | |
features required | array<Site> | |
next_cursor required | string | null | Pass as cursor for the next page; null on the last page |
SiteProperties
Public attributes of a site. Never: pilot identity, flights, exact pilot count.
| Name | Type | Description |
kind required | "takeoff" | "landing" | |
name required | string | null | Name given by a moderator; null if none yet |
headings required | array<integer> | null | Takeoff: launch directions (downhill azimuth, degrees, 45° sectors); null when not derived (no DEM yet) or for landings |
slope_deg required | integer | null | Takeoff: slope in degrees (DEM) |
elevation_m required | integer | null | Takeoff: ground elevation in metres (DEM) |
area_m2 required | integer | null | Landing: area of the landing points' hull, m² |
confidence required | "low" | "medium" | "high" | Support from flight data: low (3 to 4 pilots), medium (5 to 9), high (10 or more). Moderator or OSM sites below 3 pilots are low |
min_pilots required | integer | null | At least this many different pilots used the site, floored to 3, 5, 10, 20, 50, 100; null for moderator or OSM sites under 3. The exact count is never returned |
version required | integer | Increments on every change of the site |
updated_at required | string (date-time) | Last change (UTC) |
SlopeConditions
| Name | Type | Description |
date required | string (date) | Local date (Europe/Istanbul) |
timezone required | "Europe/Istanbul" | |
cell required | ForecastCell | Centre of the 0.25° cell the answer is for |
hours required | array<SlopeHour> | Local hours 05-21 |
forecast_state required | "available" | "out_of_range" | "unavailable" | available; out_of_range (date outside today..today + 4, sun only); unavailable (forecast server off or failed, sun only) |
forecast required | ForecastInfo | |
method_version required | integer | Version of the slope rule (docs/07 §9b) |
notice required | "slopes.notice.preflight_only" | i18n key of the fixed notice: pre-flight planning only; the pilot decides |
SlopeHour
| Name | Type | Description |
time required | string (date-time) | UTC hour; values are instantaneous |
local_hour required | integer | Hour in Europe/Istanbul 0 ≤ x ≤ 23
|
sun required | Sun | Sun at the cell centre (style state sun_azimuth/altitude) |
wind_10m required | Wind | null | 10 m forecast wind; null without a forecast |
wind_850hpa required | Wind | null | 850 hPa forecast wind (about 1,500 m); null without a forecast |
Sport
flights.sport (migration 0016, SPORT-001). Layers count only PARAGLIDING for now.
"paragliding" | "hang_gliding" | "sailplane" | "paramotor" | "hike_and_fly" | "other"
SuitabilityHour
| Name | Type | Description |
time required | string (date-time) | UTC hour; forecast values are instantaneous |
level required | "green" | "yellow" | "red" | "unknown" | |
reasons required | array<string> | i18n keys suitability.reason.<code> |
wind_10m required | Wind | null | 10 m wind; null without a forecast |
wind_850hpa required | Wind | null | 850 hPa wind (about 1,500 m) |
heading_offset_deg required | integer | null | Angle of the 10 m wind to the nearest launch heading (0 = straight in); null for light wind, unknown headings or no forecast |
SuitabilityResponse
| Name | Type | Description |
site_id required | string (uuid) | |
date required | string (date) | Local date (Europe/Istanbul) |
timezone required | "Europe/Istanbul" | |
headings required | array<integer> | null | Launch directions used (downhill azimuth, degrees); null when not derived |
slots required | array<SuitabilitySlot> | |
forecast required | ForecastInfo | |
rule_version required | integer | Version of the rating rule |
notice required | "suitability.notice.preflight_only" | i18n key of the fixed notice: pre-flight planning only, not for in-flight use; the pilot decides (docs/04 §3) |
SuitabilitySlot
| Name | Type | Description |
start required | string (date-time) | Local start (Europe/Istanbul, with offset) |
end required | string (date-time) | Local end (exclusive) |
level required | "green" | "yellow" | "red" | "unknown" | green looks suitable, yellow caution, red looks unsuitable, unknown no forecast; the worst of the slot's hours |
reasons required | array<string> | i18n keys suitability.reason.<code> (docs/10 §14) |
hours required | array<SuitabilityHour> | |
Sun
| Name | Type | Description |
azimuth_deg required | number | Clockwise from north, one decimal 0 ≤ x < 360
|
altitude_deg required | number | Above the horizon, one decimal; negative = night -90 ≤ x ≤ 90
|
ValidationError
| Name | Type | Description |
loc required | array<string | integer> | |
msg required | string | |
type required | string | |
input | any | |
ctx | object | |
Aspect ratio in the URL and the object key; both are 1080p.
"16x9" | "9x16"
VideoInfo
A video of a shared flight. No pilot, no flight id: the share's public_id only.
| Name | Type | Description |
public_id required | string | |
format required | "16:9" | "9:16" | |
length_s required | 15 | 30 | Longest video, seconds: 15 (default; about 3.5 minutes to make) or 30 (about 7 minutes). A flight is shown at least 10x faster, so a short flight gives a shorter video |
status required | "queued" | "rendering" | "ready" | "failed" | queued → rendering → ready; failed after every retry failed |
status_path required | string | Path of the status route of this video |
url required | string | null | Time-limited download URL (MP4, H.264) when ready, else null |
expires_at required | string (date-time) | null | url stops working at this time (UTC) |
width required | integer | |
height required | integer | |
fps required | integer | null | 30 when ready |
duration_s required | number | null | Length of the video, seconds, when ready |
size_bytes required | integer | null | |
sha256 required | string | null | SHA-256 of the MP4 when ready |
error required | "replay_gone" | "render_failed" | null | Why it failed: render_failed (asking again retries), replay_gone |
VideoLength
Longest video, seconds: what a request asks for (Q-023). The worker's
UPDRAFT_RENDER_MAX_SECONDS (default 30) caps it.
15 | 30
VideoRequest
| Name | Type | Description |
format required | "16:9" | "9:16" | Aspect ratio: 16:9 landscape or 9:16 portrait (stories, reels) |
resolution | "1080p" | Only 1080p (1920x1080 / 1080x1920) default "1080p" |
length_s | 15 | 30 | Longest video, seconds: 15 (default; about 3.5 minutes to make) or 30 (about 7 minutes). A flight is shown at least 10x faster, so a short flight gives a shorter videodefault 15 |
Wind
| Name | Type | Description |
direction_deg required | integer | Where the wind comes from, degrees 0 ≤ x ≤ 360
|
speed_ms required | number | Speed in m/s, one decimal 0 ≤ x
|