Position History

Get a raw position history timeline for an aircraft by tail number or ICAO24 hex code — without requiring a prior search step. Unlike the flight track endpoint, position history is not bounded to a single flight and can span multiple flights in one window.

Choosing a path: For a single archived flight's gate-to-gate track, use registration → flight search → flight_id → track. For a raw timeline across multiple flights or when you do not know the flight boundaries, use registration → positions directly.

Plan tiers: Historical ADS-B hub.

Requirements

Auth
x-api-key on every request (direct subscription). Learn more →
Plan

Pro, Ultra, or Mega — use the path prefix that matches the window you need.

Learn more →

By ICAO24

Request

GEThttps://data.skylinkapi.com/v3.1/ultra/history/positions/{icao24}
ParameterTypeRequiredDefaultDescription
icao24stringYes-Aircraft ICAO24 hex (6 characters)
startstringNo24 h agoWindow start — ISO 8601
endstringNonowWindow end — ISO 8601
limitintegerNo1000Max position rows (max 5,000 on ULTRA path)

Query window cannot exceed 90 days on /ultra/history/....

MEGA path — by [ICAO24](https://en.wikipedia.org/wiki/ICAO_24-bit_address) (`/mega/history/...`)Expand section
GEThttps://data.skylinkapi.com/v3.1/mega/history/positions/{icao24}
ParameterTypeRequiredDefaultDescription
icao24stringYes-Aircraft ICAO24 hex
startstringNo24 h agoWindow start — ISO 8601 (max 365 days span on MEGA path)
endstringNonowWindow end
limitintegerNo1000Max positions (max 10,000 on MEGA path)

Requires Ultra or Mega plan. Same response shape as ULTRA.

By registration

Same response shape as by ICAO24 but accepts a registration tail number (e.g. N12345, G-XWBA) resolved to ICAO24 server-side. Returns 404 if the registration is not in the aircraft registry.

Request

GEThttps://data.skylinkapi.com/v3.1/ultra/history/positions/registration/{registration}
ParameterTypeRequiredDefaultDescription
registrationstringYes-Aircraft tail number
startstringNo24 h agoWindow start — ISO 8601
endstringNonowWindow end — ISO 8601
limitintegerNo1000Max position rows (max 5,000 on ULTRA path)
MEGA path — by registration (`/mega/history/...`)Expand section
GEThttps://data.skylinkapi.com/v3.1/mega/history/positions/registration/{registration}
ParameterTypeRequiredDefaultDescription
registrationstringYes-Tail number
startstringNo24 h agoWindow start — ISO 8601 (max 365 days span on MEGA path)
endstringNonowWindow end
limitintegerNo1000Max positions (max 10,000 on MEGA path)

Requires Ultra or Mega plan. Same response shape as ULTRA.

Response

{
  "icao24": "40621d",
  "count": 864,
  "positions": [
    {
      "timestamp": "2026-05-13T03:08:05Z",
      "icao24": "40621d",
      "latitude": 40.6413,
      "longitude": -73.7781,
      "altitude_baro": 0,
      "ground_speed": 12,
      "track": 90,
      "vertical_rate": 0,
      "callsign": "BAW178",
      "is_on_ground": true,
      "registration": "G-XWBA",
      "aircraft_type": "B77W",
      "gps_spoofed": false
    }
  ],
  "flights": [
    {
      "flight_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "callsign": "BAW178",
      "flight_number": "BAW178",
      "departure_airport_icao": "EGLL",
      "departure_airport_iata": "LHR",
      "departure_airport_name": "London Heathrow Airport",
      "arrival_airport_icao": "KJFK",
      "arrival_airport_iata": "JFK",
      "arrival_airport_name": "John F Kennedy International Airport",
      "takeoff_time": "2026-05-12T19:45:00Z",
      "landing_time": "2026-05-13T03:08:00Z",
      "flight_start": "2026-05-12T19:42:05Z",
      "flight_end": "2026-05-13T03:11:10Z",
      "flight_state": "ARCHIVED"
    }
  ]
}
FieldTypeRequiredNull?Description
icao24stringYesNeverQueried aircraft hex
countintegerYesNeverNumber of items in positions
positionsarrayYesNeverNewest-first position snapshots
flightsarrayYesNeverArchived flights overlapping the window

The registration endpoint adds a top-level registration field echoing the resolved tail number; icao24 is populated after server-side lookup.

Flight window (flights[])

FieldTypeRequiredNull?Description
flight_idstringYesNeverUUID for detail/track lookups
callsignstring | nullNoYesCallsign during that flight
flight_numberstring | nullNoYesNormalized flight number when resolved
departure_airport_icaostring | nullNoYesDeparture airport when resolved
departure_airport_iatastring | nullNoYesDeparture airport IATA
departure_airport_namestring | nullNoYesDeparture airport name
arrival_airport_icaostring | nullNoYesArrival airport when resolved
arrival_airport_iatastring | nullNoYesArrival airport IATA
arrival_airport_namestring | nullNoYesArrival airport name
takeoff_timestring | nullNoYesTakeoff time for that flight (ISO 8601)
landing_timestring | nullNoYesLanding time for that flight (ISO 8601)
flight_startstringYesNeverFirst archived position in that flight window
flight_endstringYesNeverLast archived position in that flight window
flight_statestring | nullNoYesArchive state (e.g. ARCHIVED)

Client types

"""Typed models for Historical ADS-B - matches historical-adsb.mdx field tables."""from __future__ import annotationsfrom dataclasses import dataclassfrom typing import Literal@dataclassclass HistoricalFlightSummary:    flight_id: str    icao24: str | None    callsign: str | None    flight_number: str | None    tail_number: str | None    departure_airport_icao: str | None    arrival_airport_icao: str | None    flight_start: str    flight_end: str    takeoff_time: str | None    landing_time: str | None    flight_duration_min: float | None    distance_nm: float | None@dataclassclass HistoricalPosition:    timestamp: str    icao24: str    latitude: float    longitude: float    altitude_baro: float | None    ground_speed: float | None    track: float | None    vertical_rate: float | None    is_on_ground: bool@dataclassclass HistoricalFlightWindow:    flight_id: str    callsign: str | None    departure_airport_icao: str | None    arrival_airport_icao: str | None    takeoff_time: str | None    landing_time: str | None    flight_start: str    flight_end: str    flight_state: str | None@dataclassclass AirportTrafficFlight:    flight_id: str    icao24: str | None    callsign: str | None    departure_airport_icao: str | None    arrival_airport_icao: str | None    takeoff_time: str | None    landing_time: str | None    flight_duration_min: float | None    distance_nm: float | None@dataclassclass AirportTrafficResponse:    icao: str    direction: Literal["dep", "arr", "both"]    count: int    flights: list[AirportTrafficFlight]

Integration

Build a playback track from an aircraft tail number. The example below fetches position history via registration, reverses positions into chronological order for map replay, and handles both the 404 (unknown tail) and 422 (window too wide) error cases. Extend to the /mega/history/... path when a 90-day lookback is insufficient.

import osfrom datetime import datetime, timedelta, timezoneimport requestsBASE = "https://data.skylinkapi.com/v3.1"HEADERS = {    "x-api-key": os.getenv("SKYLINK_API_KEY") or os.getenv("SKYLINK_API_KEY", "YOUR_API_KEY")}def fetch_positions(icao24: str, *, tier: str = "ultra", hours: int = 24) -> dict:    now = datetime.now(timezone.utc)    start = (now - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ")    end = now.strftime("%Y-%m-%dT%H:%M:%SZ")    r = requests.get(        f"{BASE}/{tier}/history/positions/{icao24.lower()}",        headers=HEADERS,        params={"start": start, "end": end, "limit": 100},        timeout=(10, 30),    )    r.raise_for_status()    return r.json()if __name__ == "__main__":    import json    # Resolve icao24 from a recent archived flight    r = requests.get(        f"{BASE}/ultra/history/flights",        headers=HEADERS,        params={"callsign": "BAW178", "limit": 1},        timeout=(10, 25),    )    r.raise_for_status()    flights = r.json().get("flights") or []    if not flights:        print("No flight found")    else:        icao24 = flights[0]["icao24"]        data = fetch_positions(icao24)        print(json.dumps({"icao24": data.get("icao24"), "count": data.get("count")}, indent=2))

Implementation notes

Registration vs hex. Prefer registration when your users know tail numbers; use icao24 when ingesting raw ADS-B feeds. The registration endpoints return 404 when the tail is unknown.

Important: Position history returns positions newest-first. Reverse chronologically for map replay.

Window sizing. At 5-second sampling, a single flight produces ~700–1,500 position rows. For multi-day requests raise limit (up to 5,000 on ULTRA, 10,000 on MEGA) or narrow the window and merge client-side.

Error responses

Plan-gate 401/403: Historical ADS-B hub. Endpoint-specific:

404 — registration not found

{
  "detail": "Registration 'N00000' not found"
}

Returned by /history/positions/registration/{registration} when the tail number is absent from the aircraft registry.

422 — window too wide

Returned when start/end span exceeds the path maximum — 90 days on /ultra/history/... or 365 days on /mega/history/...:

{
  "detail": "Query window exceeds maximum of 90 days for your plan on /ultra/history/..."
}
GET
/ultra/history/positions/{icao24}
x-api-key<token>

Your SkyLink licence key, for keys bought direct from skylinkapi.com.

In: header

Path Parameters

icao24*Icao24

Query Parameters

start?|

Start datetime ISO 8601. Defaults to 24 h ago.

end?|

End datetime ISO 8601. Defaults to now.

limit?Limit

Max position rows (default 1000, max 5000)

Default1000
Range1 <= value <= 5000

Response Body

application/json

application/json

curl -X GET "https://data.skylinkapi.com/v3.1/ultra/history/positions/a835af"
null
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string",
      "input": null,
      "ctx": {}
    }
  ]
}
GET
/ultra/history/positions/registration/{registration}
x-api-key<token>

Your SkyLink licence key, for keys bought direct from skylinkapi.com.

In: header

Path Parameters

registration*Registration

Query Parameters

start?|

Start datetime ISO 8601. Defaults to 24 h ago.

end?|

End datetime ISO 8601. Defaults to now.

limit?Limit

Max position rows (default 1000, max 5000)

Default1000
Range1 <= value <= 5000

Response Body

application/json

application/json

curl -X GET "https://data.skylinkapi.com/v3.1/ultra/history/positions/registration/N12345"
null
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string",
      "input": null,
      "ctx": {}
    }
  ]
}
GET
/mega/history/positions/{icao24}
x-api-key<token>

Your SkyLink licence key, for keys bought direct from skylinkapi.com.

In: header

Path Parameters

icao24*Icao24

Query Parameters

start?|

Start datetime ISO 8601. Defaults to 24 h ago.

end?|

End datetime ISO 8601. Defaults to now.

limit?Limit

Max position rows (default 1000, max 10000)

Default1000
Range1 <= value <= 10000

Response Body

application/json

application/json

curl -X GET "https://data.skylinkapi.com/v3.1/mega/history/positions/a835af"
null
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string",
      "input": null,
      "ctx": {}
    }
  ]
}
GET
/mega/history/positions/registration/{registration}
x-api-key<token>

Your SkyLink licence key, for keys bought direct from skylinkapi.com.

In: header

Path Parameters

registration*Registration

Query Parameters

start?|

Start datetime ISO 8601. Defaults to 24 h ago.

end?|

End datetime ISO 8601. Defaults to now.

limit?Limit

Max position rows (default 1000, max 10000)

Default1000
Range1 <= value <= 10000

Response Body

application/json

application/json

curl -X GET "https://data.skylinkapi.com/v3.1/mega/history/positions/registration/N12345"
null
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string",
      "input": null,
      "ctx": {}
    }
  ]
}