{
  "openapi": "3.0.3",
  "info": {
    "title": "ipasn — IP Intel API",
    "description": "Given an IP address, returns the owning ASN and network prefix, a coarse geolocation, and a datacenter-vs-residential usage verdict with the evidence behind it. All data is downloaded once and processed locally, so every request is answered fully offline. IPv4 and IPv6 are both supported.",
    "version": "1.0.0",
    "license": {
      "name": "Data: DB-IP CC-BY 4.0 / iptoasn.com Public Domain",
      "url": "https://creativecommons.org/licenses/by/4.0/"
    }
  },
  "servers": [
    { "url": "https://ip.benjamin-dreier.de", "description": "Production" }
  ],
  "paths": {
    "/v1/lookup": {
      "get": {
        "summary": "Look up an IP via query parameter",
        "operationId": "lookupQuery",
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": true,
            "description": "The IPv4 or IPv6 address to look up.",
            "schema": { "type": "string" },
            "example": "8.8.8.8"
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result. Unresolvable fields are returned as null.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/LookupResponse" },
                "example": {
                  "ip": "8.8.8.8",
                  "network": "8.8.8.0/24",
                  "asn": { "number": 15169, "name": "GOOGLE", "country": "US" },
                  "location": {
                    "country": "United States",
                    "country_code": "US",
                    "city": "Mountain View",
                    "latitude": 37.422,
                    "longitude": -122.085,
                    "source": "db-ip-lite"
                  },
                  "usage_type": {
                    "classification": "datacenter",
                    "is_datacenter": true,
                    "confidence": "medium",
                    "matched_by": "hosting-asn-list",
                    "evidence": ["AS15169 in hosting-ASN list"]
                  },
                  "data_versions": {
                    "asn": "fetched:2026-06-28T12:10:04Z",
                    "geo": "dbip-city-lite-2026-06",
                    "datacenter": "fetched:2026-06-28T12:10:09Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid IP address.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": { "error": "invalid IP address: nope" }
              }
            }
          },
          "503": {
            "description": "Datasets are still loading.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/v1/ip/{ip}": {
      "get": {
        "summary": "Look up an IP via path parameter",
        "description": "Equivalent to /v1/lookup?ip=<ip>.",
        "operationId": "lookupPath",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "The IPv4 or IPv6 address to look up.",
            "schema": { "type": "string" },
            "example": "1.1.1.1"
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result. Unresolvable fields are returned as null.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/LookupResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid IP address.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "503": {
            "description": "Datasets are still loading.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "summary": "Service health, record counts, dataset versions and attribution",
        "operationId": "health",
        "responses": {
          "200": { "description": "Service ready." },
          "503": { "description": "Datasets are still loading." }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "LookupResponse": {
        "type": "object",
        "required": ["ip", "network", "asn", "location", "usage_type", "data_versions"],
        "properties": {
          "ip": { "type": "string", "example": "8.8.8.8" },
          "network": {
            "type": "string",
            "nullable": true,
            "description": "Covering network prefix, or null if the ASN is unknown.",
            "example": "8.8.8.0/24"
          },
          "asn": {
            "nullable": true,
            "allOf": [{ "$ref": "#/components/schemas/ASN" }]
          },
          "location": {
            "nullable": true,
            "allOf": [{ "$ref": "#/components/schemas/Location" }]
          },
          "usage_type": { "$ref": "#/components/schemas/UsageType" },
          "data_versions": { "$ref": "#/components/schemas/DataVersions" }
        }
      },
      "ASN": {
        "type": "object",
        "properties": {
          "number": { "type": "integer", "example": 15169 },
          "name": { "type": "string", "example": "GOOGLE" },
          "country": { "type": "string", "example": "US" }
        }
      },
      "Location": {
        "type": "object",
        "properties": {
          "country": { "type": "string", "example": "United States" },
          "country_code": { "type": "string", "example": "US" },
          "city": { "type": "string", "example": "Mountain View" },
          "latitude": { "type": "number", "format": "float", "example": 37.422 },
          "longitude": { "type": "number", "format": "float", "example": -122.085 },
          "source": { "type": "string", "example": "db-ip-lite" }
        }
      },
      "UsageType": {
        "type": "object",
        "description": "Datacenter-vs-residential verdict. This is a layered heuristic with a non-trivial error rate; treat low confidence accordingly.",
        "properties": {
          "classification": {
            "type": "string",
            "enum": ["datacenter", "residential", "unknown"],
            "example": "datacenter"
          },
          "is_datacenter": { "type": "boolean", "example": true },
          "confidence": {
            "type": "string",
            "enum": ["high", "medium", "low"],
            "example": "medium"
          },
          "matched_by": { "type": "string", "example": "hosting-asn-list" },
          "evidence": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["AS15169 in hosting-ASN list"]
          }
        }
      },
      "DataVersions": {
        "type": "object",
        "properties": {
          "asn": { "type": "string", "example": "fetched:2026-06-28T12:10:04Z" },
          "geo": { "type": "string", "example": "dbip-city-lite-2026-06" },
          "datacenter": { "type": "string", "example": "fetched:2026-06-28T12:10:09Z" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "invalid IP address: nope" }
        }
      }
    }
  }
}
