openapi: "3.1.0"
info:
  title: ipdex API
  version: "1.0.0"
  description: "The open index of the IP world. Free, no key, CORS *. /v1 is frozen — additions only. Live visitor data (/v1/me) is computed per request and never stored."
  contact:
    name: ipdex
    url: https://ipdex.io/developers/
  license:
    name: "Data: IPinfo Lite (CC BY-SA), PeeringDB, DB-IP"
    url: https://ipdex.io/sources/
servers:
  - url: https://api.ipdex.io
paths:
  /v1/me:
    get:
      summary: "Full self-lookup from the edge (request.cf). Never stored."
      operationId: getMe
      responses:
        "200":
          description: Visitor snapshot + data version
          headers:
            x-data-version:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiMeResponse"
  /v1/me/ip:
    get:
      summary: Bare client IP as text/plain.
      operationId: getMeIp
      responses:
        "200":
          description: The IP address
          content:
            text/plain:
              schema:
                type: string
  "/v1/lookup/{ip}":
    get:
      summary: "Resolve an IP to ASN, org and country from the index."
      operationId: lookupIp
      parameters:
        - name: ip
          in: path
          required: true
          schema:
            type: string
          example: "8.8.8.8"
      responses:
        "200":
          description: "Lookup result (asn/org/country null when unrouted/unknown)"
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiLookupResponse"
        "400":
          description: Invalid IP
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiError"
  "/v1/asn/{asn}":
    get:
      summary: ASN summary.
      operationId: getAsn
      parameters:
        - name: asn
          in: path
          required: true
          schema:
            type: string
          example: AS15169
      responses:
        "200":
          description: ASN record
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiAsnResponse"
        "400":
          description: Invalid ASN
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiError"
        "404":
          description: Unknown ASN
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiError"
components:
  schemas:
    VisitorSnapshot:
      type: object
      required:
        - ip
        - ipVersion
        - isEUCountry
        - isTor
      properties:
        ip:
          type: string
        ipVersion:
          type: integer
          enum:
            - 4
            - 6
        asn:
          type:
            - integer
            - "null"
        asOrganization:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        region:
          type:
            - string
            - "null"
        regionCode:
          type:
            - string
            - "null"
        postalCode:
          type:
            - string
            - "null"
        continent:
          type:
            - string
            - "null"
        latitude:
          type:
            - string
            - "null"
        longitude:
          type:
            - string
            - "null"
        timezone:
          type:
            - string
            - "null"
        colo:
          type:
            - string
            - "null"
        isEUCountry:
          type: boolean
        httpProtocol:
          type:
            - string
            - "null"
        tlsVersion:
          type:
            - string
            - "null"
        tlsCipher:
          type:
            - string
            - "null"
        clientTcpRtt:
          type:
            - number
            - "null"
        isTor:
          type: boolean
        coloDistanceKm:
          type:
            - number
            - "null"
    ApiMeResponse:
      allOf:
        - "$ref": "#/components/schemas/VisitorSnapshot"
        - type: object
          required:
            - dataVersion
          properties:
            dataVersion:
              type: string
    ApiLookupResponse:
      type: object
      required:
        - ip
        - version
        - asn
        - asnType
        - org
        - orgSlug
        - country
        - source
        - lastUpdated
      properties:
        ip:
          type: string
        version:
          type: integer
          enum:
            - 4
            - 6
        asn:
          type:
            - integer
            - "null"
        asnType:
          oneOf:
            - type: string
              enum:
                - isp
                - content
                - hosting
                - education
                - enterprise
                - government
                - unknown
            - type: "null"
        org:
          type:
            - string
            - "null"
        orgSlug:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        source:
          type: string
          enum:
            - ipinfo-lite
            - peeringdb
            - bgp-apnic
            - rir-delegated
            - rdap
            - db-ip
            - iplocate
            - derived
            - seed
        lastUpdated:
          type:
            - string
            - "null"
    ApiAsnResponse:
      type: object
      required:
        - asn
        - org
        - orgSlug
        - country
        - type
        - domain
        - allocatedDate
        - prefixCountV4
        - prefixCountV6
        - source
        - lastUpdated
      properties:
        asn:
          type: integer
          minimum: 1
        org:
          type: string
        orgSlug:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        type:
          type: string
          enum:
            - isp
            - content
            - hosting
            - education
            - enterprise
            - government
            - unknown
        domain:
          type:
            - string
            - "null"
        allocatedDate:
          type:
            - string
            - "null"
        prefixCountV4:
          type: integer
          minimum: 0
        prefixCountV6:
          type: integer
          minimum: 0
        source:
          type: string
          enum:
            - ipinfo-lite
            - peeringdb
            - bgp-apnic
            - rir-delegated
            - rdap
            - db-ip
            - iplocate
            - derived
            - seed
        lastUpdated:
          type:
            - string
            - "null"
    ApiError:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string