{
  "schemaVersion": 1,
  "generatedBy": "AeroDue",
  "canonical": "https://www.aerodue.com/widgets.json",
  "widgets": [
    {
      "id": "upcoming-disruptions",
      "name": "Upcoming disruptions",
      "delivery": "iframe",
      "url": "https://www.aerodue.com/embed/upcoming-disruptions/",
      "parameters": {
        "lang": "Locale code or public AeroDue locale path, for example en-GB, pt-PT or fr.",
        "country": "Optional ISO 3166-1 alpha-2 country code.",
        "mode": "One of air, rail, airport-access or all. Default: air.",
        "limit": "Integer from 1 to 8. Default: 5."
      },
      "example": "<iframe src=\"https://www.aerodue.com/embed/upcoming-disruptions/?lang=en-GB&mode=air&limit=5\" title=\"AeroDue upcoming disruptions\" loading=\"lazy\" referrerpolicy=\"strict-origin-when-cross-origin\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\" style=\"width:100%;height:520px;border:0\"></iframe>",
      "branding": {
        "required": true,
        "label": "Powered by AeroDue",
        "backlink": true
      },
      "dataBoundary": "Displays only AeroDue-normalized source-backed notices: event title, date, market, mode and status, with a canonical AeroDue backlink. Raw upstream payloads, passenger counts and inferred flight impact are not exposed.",
      "requestModel": "Loads the disruption widget feed once per iframe load through a Cloudflare rate-limited same-origin route. The underlying static dataset is CDN-cached; there is no client-side polling.",
      "deliveryControls": {
        "rateLimit": "120 widget data requests per 60 seconds per hashed network actor at each Cloudflare location.",
        "cache": "Canonical disruption dataset is served from Cloudflare static assets and the widget response advertises 300s cache with 900s stale-while-revalidate.",
        "polling": false
      },
      "fieldPolicy": {
        "exposed": [
          "title",
          "starts_at",
          "ends_at",
          "countries",
          "transport_modes",
          "kind",
          "status",
          "canonical_url"
        ],
        "withheld": [
          "raw_upstream_payload",
          "affected_passenger_count",
          "flight_count_inference",
          "compensation_entitlement"
        ],
        "provenance": "AeroDue-normalized public disruption records with canonical source-backed event pages."
      }
    },
    {
      "id": "airport-health",
      "name": "Airport Health",
      "delivery": "iframe",
      "url": "https://www.aerodue.com/embed/airport-health/",
      "parameters": {
        "icao": "Required 4-character ICAO airport code.",
        "lang": "Locale code or public AeroDue locale path, for example en-GB, pt-PT or fr."
      },
      "example": "<iframe src=\"https://www.aerodue.com/embed/airport-health/?lang=en-GB&icao=LPPT\" title=\"AeroDue Airport Health\" loading=\"lazy\" referrerpolicy=\"strict-origin-when-cross-origin\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\" style=\"width:100%;height:390px;border:0\"></iframe>",
      "branding": {
        "required": true,
        "label": "Powered by AeroDue",
        "backlink": true
      },
      "dataBoundary": "Shows the AeroDue-derived airport pressure state, source-backed headline, observed aviation-weather category and bounded notice counts. Raw EUROCONTROL performance fields, cancellation counts, live flight status, airport-open status, delay probability and safety ratings are not exposed by the widget.",
      "requestModel": "Makes one same-origin Airport Health request per iframe load through a Cloudflare rate limiter. Complete Airport Health snapshots use 60s edge caching; the widget does not poll.",
      "deliveryControls": {
        "rateLimit": "120 widget data requests per 60 seconds per hashed network actor at each Cloudflare location.",
        "cache": "Complete Airport Health snapshots are edge-cached for 60 seconds; degraded snapshots are not cached.",
        "polling": false
      },
      "fieldPolicy": {
        "exposed": [
          "airport_identity",
          "pressure_level",
          "source_backed_headline",
          "weather_flight_category",
          "airport_notice_count",
          "country_context_count"
        ],
        "withheld": [
          "raw_eurocontrol_metrics",
          "cancellation_count",
          "live_flight_status",
          "airport_open_status",
          "delay_probability",
          "safety_rating"
        ],
        "provenance": "AeroDue-derived Airport Health output from AeroDue disruption intelligence, official aviation weather and bounded network performance inputs."
      }
    }
  ],
  "previews": [
    {
      "id": "flight-disruption",
      "name": "Individual flight disruption",
      "url": "https://www.aerodue.com/embed/flight-disruption/",
      "delivery": "iframe",
      "publication": "first-party-only",
      "publisherEmbedding": false,
      "parameters": {
        "flight": "Required commercial IATA flight number.",
        "date": "Optional scheduled departure date in UTC (YYYY-MM-DD); defaults to today's UTC date.",
        "lang": "AeroDue public locale code."
      },
      "example": "<iframe src=\"https://www.aerodue.com/embed/flight-disruption/?flight=TP442&lang=pt-PT\" title=\"AeroDue flight disruption\" loading=\"lazy\" referrerpolicy=\"strict-origin-when-cross-origin\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\" style=\"width:100%;height:350px;border:0\"></iframe>",
      "branding": {
        "required": true,
        "label": "Powered by AeroDue",
        "backlink": true
      },
      "policy": "https://www.aerodue.com/flight-widget-policy.json",
      "boundary": "Only the AeroDue first-party preview is enabled. Publisher framing is blocked pending permitted distribution and real production iframe acceptance."
    }
  ],
  "distributionPolicy": {
    "freeTier": "Branded iframe distribution with AeroDue attribution and backlink.",
    "framing": "HTTPS publisher origins only; widget pages are noindex and isolated from AeroDue's global frame-deny policy.",
    "dataUse": "Widgets expose only the field allowlists declared per widget. Raw upstream payloads and commercially unaudited fields remain withheld.",
    "rateLimiting": "Dynamic widget data routes are protected by Cloudflare's Rate Limiting API; static source datasets remain CDN-cached."
  },
  "businessTier": {
    "status": "not-offered",
    "reason": "White-label, higher-limit and commercial API distribution remain blocked until field-by-field commercial licensing review."
  }
}
