{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://iploc.eu/api/lookup.schema.json",
  "title": "IP Geo Lookup Response",
  "description": "Normalized response schema for GET /api/lookup. All fields except ip are nullable when the underlying provider does not return them.",
  "type": "object",
  "required": ["ip", "_provider", "_cached", "_response_time_ms"],
  "properties": {
    "ip": {
      "type": "string",
      "description": "The queried IP address (IPv4 or IPv6).",
      "examples": ["8.8.8.8", "2001:4860:4860::8888"]
    },
    "city": {
      "type": ["string", "null"],
      "description": "City name in English."
    },
    "region": {
      "type": ["string", "null"],
      "description": "Region/state/province name in English."
    },
    "country_code": {
      "type": ["string", "null"],
      "description": "ISO 3166-1 alpha-2 country code, uppercase.",
      "examples": ["US", "NL", "DE"]
    },
    "country_name": {
      "type": ["string", "null"],
      "description": "Country name in English (may be null on tertiary providers)."
    },
    "lat": {
      "type": ["number", "null"],
      "minimum": -90,
      "maximum": 90,
      "description": "Latitude (WGS84). City-level accuracy."
    },
    "lon": {
      "type": ["number", "null"],
      "minimum": -180,
      "maximum": 180,
      "description": "Longitude (WGS84). City-level accuracy."
    },
    "timezone": {
      "type": ["string", "null"],
      "description": "IANA timezone identifier, e.g. America/Los_Angeles."
    },
    "asn": {
      "type": ["string", "null"],
      "description": "Autonomous System Number prefixed with 'AS', e.g. AS15169. May be null when only freeipapi.com responded.",
      "pattern": "^AS\\d+$"
    },
    "org": {
      "type": ["string", "null"],
      "description": "Organization or ISP name."
    },
    "postal": {
      "type": ["string", "null"],
      "description": "Postal/zip code (city-area, not building)."
    },
    "is_eu": {
      "type": "boolean",
      "description": "True if country_code is in the European Union (27 member states)."
    },
    "_provider": {
      "type": "string",
      "enum": ["ip-api.com", "ipwho.is", "ipinfo.io", "freeipapi.com"],
      "description": "Which upstream provider served this lookup. Provided for debugging and accuracy auditing."
    },
    "_cached": {
      "type": "boolean",
      "description": "True if this response was served from the in-memory cache."
    },
    "_response_time_ms": {
      "type": "integer",
      "minimum": 0,
      "description": "Time spent in the handler, including upstream calls (if uncached)."
    },
    "_caller_lookup": {
      "type": "boolean",
      "description": "True when no IP was supplied and we resolved the caller's IP via x-forwarded-for."
    }
  },
  "additionalProperties": false,
  "examples": [
    {
      "ip": "8.8.8.8",
      "city": "Mountain View",
      "region": "California",
      "country_code": "US",
      "country_name": "United States",
      "lat": 37.4056,
      "lon": -122.0775,
      "timezone": "America/Los_Angeles",
      "asn": "AS15169",
      "org": "Google LLC",
      "postal": "94043",
      "is_eu": false,
      "_provider": "ip-api.com",
      "_cached": false,
      "_response_time_ms": 47
    }
  ]
}
