{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/thinair-co/json-schema/thinair-co-autocomplete-response-schema.json",
  "title": "AutocompleteResponse",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/geo-thinair-co-openapi.json#/components/schemas/AutocompleteResponse",
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/AutocompleteItem"
      }
    },
    "meta": {
      "type": "object",
      "properties": {
        "query": {
          "type": "string"
        },
        "upstream_ms": {
          "type": "number"
        },
        "item_count": {
          "type": "number"
        },
        "cacheHit": {
          "type": "boolean"
        },
        "cacheHitKind": {
          "type": "string",
          "enum": [
            "v3_hit",
            "legacy_dual_read"
          ],
          "description": "AC_L1_V3 only: `v3_hit` when the coarse `ac:v3` key served the answer; `legacy_dual_read` when a warm `ac:v2` entry was served via the dual-read fallback. Omitted when the flag is OFF or the answer was not a positive-cache HIT."
        },
        "source": {
          "type": "string",
          "description": "Where the answer came from: `engine` (live upstream), `cache` (edge prefix cache), `prefilled_cache` (curated/prewarmed entry), or `edge_hotset` (the L(-1) in-isolate runtime hot-set for 1-2 char input). Absent on the degraded/empty paths: below-floor short inputs, negative-cache hits, and timeout-degraded responses."
        },
        "cacheTier": {
          "type": "string",
          "enum": [
            "l0",
            "kv",
            "edge"
          ],
          "description": "Present only on a hit from the L(-1) runtime hot-set (`edge`) — drives `X-Cache: HIT-EDGE`. Omitted on every other response."
        }
      },
      "required": [
        "query",
        "upstream_ms",
        "item_count"
      ]
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Soft signals: `min_length` (input below the engine floor — 3 chars global, 2 chars when scoped by focus/bounds/country; engine skipped), `focus_distance_filtered` (far results dropped), `no_results_near_focus` (nothing within ~500 km of focus; honest unfiltered set returned), `country_filtered` (a result outside `boundary_country` was dropped by the hard-filter backstop), `bounds_filtered` (a result outside `bounds` was dropped by the rect backstop), `no_focus_ambiguous` (no focus/bounds/country given and the top result's country differs from the caller's geo-IP country), `short_final_token_dropped` (a 1-char final token was stripped from the engine query; the full text is still echoed in `meta.query`), `negative_cached` (served from the short-TTL timeout/empty negative cache), `upstream_degraded` (that negative entry recorded a recent engine timeout), `autocomplete_more_context_required` (2-char input without focus/bounds/country — add one to enable suggestions at this length), `autocomplete_cache_only` (1-char input — served from the prefilled cache only, never the engine), `autocomplete_timeout` (engine exceeded the per-call ceiling; degraded to an empty 200)."
    }
  },
  "required": [
    "items",
    "meta"
  ],
  "$defs": {
    "AutocompleteItem": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Stable public ThinAir id (`ta_place_<key>` / `ta_intersection_<key>`). Resolvable via `GET /v1/place`."
        },
        "name": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "layer": {
          "type": "string"
        },
        "confidence": {
          "type": "number"
        },
        "lat": {
          "type": "number"
        },
        "lon": {
          "type": "number"
        },
        "country_code": {
          "type": "string"
        },
        "locality": {
          "type": "string"
        },
        "region": {
          "type": "string"
        },
        "distance_km": {
          "type": "number"
        }
      },
      "required": [
        "lat",
        "lon"
      ]
    }
  }
}