Aircraft Registration History API

Retrieve the registration states Grizzly Bulls observed in accepted FAA source snapshots, plus bounded privacy-safe change events and source provenance.
Observed history, not a reconstructed legal ownership ledger

The endpoint is GET https://api.grizzlybulls.com/v1/aircraft/{nNumber}/history. It returns retained public versions and change events from snapshots Grizzly Bulls actually accepted. Observation timestamps describe when the source snapshot was retrieved; they do not prove the exact legal or real-world effective time of a change.

How the temporal contract works

History is deliberately split into state intervals and events so callers can distinguish what was observed from what changed between accepted snapshots.

Observed versions

A version contains the normalized public state retained for an N-number. Its observedFrom.retrievedAt and observedThrough.retrievedAtboundaries identify the first and last accepted source snapshots where that version was observed. Unchanged state extends the observation interval instead of inventing a new version every day.

PII-free change events

Events use a bounded vocabulary such as status_changed, aircraft_assignment_changed, registrant_changed, and registrant_pii_withheld. Their changedFields list exposes reviewed public field groups, not old and new owner names or addresses.

Two independent pages

Versions and events paginate independently. Each side returns its own limit, offset, total, and hasMore, so an application can advance one stream without discarding the other.

Sanitized example: what an observed change means

This is an illustrative timeline, not a live aircraft record. The example uses only non-personal fields to show how versions and events relate.

1. Version observed

N123AB is observed with source status V in accepted snapshots retrieved September 20 through September 22. Those retrieval timestamps bracket the observation interval; they are not a legal registration period.

2. Change observed

The September 23 snapshot produces status_changed with changedFields: ["registration_status"]. Its observedAt is the snapshot retrieval time. A sourceEffectiveDate may be null and is never inferred from observedAt.

3. New version begins

A new retained version records source status A beginning with the September 23 observation. Later identical accepted snapshots extend observedThrough until another retained field changes.

Request bounded history from your server

Use the same Bearer API key across the Aircraft API. Browser CORS is not enabled, so these examples are intended for server-side use. Replace N_NUMBER with an accepted U.S. N-number.

cURL
curl --fail-with-body \  -H "Authorization: Bearer $GRIZZLY_BULLS_API_KEY" \  "https://api.grizzlybulls.com/v1/aircraft/N_NUMBER/history?versionsLimit=10&versionsOffset=0&eventsLimit=10&eventsOffset=0"
Python 3 · standard library
import json
import os
import urllib.parse
import urllib.request

query = urllib.parse.urlencode({
    "versionsLimit": 10,
    "versionsOffset": 0,
    "eventsLimit": 10,
    "eventsOffset": 0,
})
request = urllib.request.Request(
    "https://api.grizzlybulls.com/v1/aircraft/N_NUMBER/history?" + query,
    headers={"Authorization": f"Bearer {os.environ['GRIZZLY_BULLS_API_KEY']}"},
)

with urllib.request.urlopen(request) as response:
    history = json.load(response)

print(history["data"]["nNumber"])
print(history["pagination"]["versions"])
for event in history["data"]["events"]:
    print(event["observedAt"], event["eventType"], event["changedFields"])
JavaScript · Node.js 18+
const params = new URLSearchParams({
  versionsLimit: "10",
  versionsOffset: "0",
  eventsLimit: "10",
  eventsOffset: "0",
});

const response = await fetch(
  "https://api.grizzlybulls.com/v1/aircraft/N_NUMBER/history?" + params,
  {
    headers: {
      Authorization: "Bearer " + process.env.GRIZZLY_BULLS_API_KEY,
    },
  },
);

if (!response.ok) {
  throw new Error("Aircraft history request failed: " + response.status);
}

const history = await response.json();
console.log(history.data.nNumber, history.pagination);
console.log(history.data.events);

Pagination is explicit and bounded

Versions

  • versionsLimit defaults to 50 and accepts 1 through 100.
  • versionsOffset defaults to 0 and is bounded at 10,000.
  • pagination.versions.total and hasMore describe only versions.
  • Versions are returned newest observation interval first.

Events

  • eventsLimit defaults to 50 and accepts 1 through 100.
  • eventsOffset defaults to 0 and is bounded at 10,000.
  • pagination.events.total and hasMore describe only events.
  • Events are returned newest observation first.

Invalid N-number or pagination input returns 400 invalid_request before history usage is reserved. Once valid input reaches access control, the history_lookup operation is metered before the repository read.

What comes back

The public history contract is aircraft-public-v1. The OpenAPI contract remains the machine-readable authority for required fields, nullability, and enums.

Version fields

Each version includes the N-number and registration fields, the historical aircraft subset retained at that observation, currently releasable registrant fields, sourceProvider, and provenance at both observedFrom and observedThrough.

Event fields

Events include eventType, bounded changedFields, old and new source registration status where applicable, nullable sourceEffectiveDate, observedAt, previousObservedAt, and source provenance.

Not silently backfilled

Historical versions expose the fields actually retained for that observation. Grizzly Bulls does not join today's aircraft or engine reference descriptions onto old versions and present them as historical evidence.

Observation time versus effective date

What the API can establish

observedAt, observedFrom.retrievedAt, and observedThrough.retrievedAt come from accepted source-snapshot retrievals. They establish when Grizzly Bulls observed a public state or change in its source pipeline.

What the API does not infer

sourceEffectiveDate is nullable. Grizzly Bulls does not synthesize it from a retrieval timestamp, certificate date, last-activity date, or another nearby field. A daily snapshot can show that a state changed between observations without proving the exact legal instant that change took effect.

Current FAA releasability governs historical PII

Withholding scrubs retained personal fields

If the current public FAA source stops releasing registrant PII for an aircraft, Grizzly Bulls suppresses matching retained names, street addresses, locations, postal data, and aliases from public history. Historical retention is never used to bypass a current withholding decision.

Suppression is not undone retroactively

The history store treats that scrub as irreversible for older retained values. If the FAA later releases public registrant information again, a newer observation may contain newly released fields, but previously scrubbed historical values are not restored. A registrant_pii_withheld event can describe the transition without exposing the removed PII.

Aircraft registration data is not proof of beneficial economic ownership. History reflects public registry observations subject to the current publication and privacy boundary.

Errors, quotas & retries

400 invalid_request

Fix the N-number or bounded pagination parameters before retrying.

401 unauthenticated

The Bearer API key is missing or invalid.

404 not_found

No retained versions or events were found for that valid N-number.

429 rate_limited

Respect Retry-After and the X-Aircraft-Quota-* headers when a rate or monthly quota is reached.

503 service_unavailable

Retry temporary authority or read-model failures with bounded exponential backoff.

500 internal_error

A server failure is returned without exposing provider or database internals.

What daily registry snapshots can prove

Go deeper on observation time, effective-date uncertainty, compact versions, PII-free events, and the limits of registry evidence.

Read the history evidence guide →

How the source becomes a maintained API

See how daily validation, atomic publication, provenance, and privacy-aware history fit together before a snapshot becomes public.

Read the production pipeline guide →

Start with a free key

Free includes 1,000 requests per month and 30 requests per minute. Current lookup, bounded discovery, and retained registration history use the same key.