openapi: 3.1.0
info:
  title: IP Geolocation API
  description: |-
    A high-performance IP geolocation and timezone lookup API.

    Provides:
    - IP address to geographic location mapping
    - Coordinate-based timezone lookups
    - Country metadata (currency, languages, calling codes)

    All responses are cached for 2 weeks (Cache-Control: public, max-age=1209600).
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: 1.0.0
servers:
- url: https://geoip.vpetersson.com
paths:
  /:
    get:
      tags:
      - IP Geolocation
      summary: Get geolocation for client's IP
      description: |-
        Returns geolocation data for the requesting client's IP address.
        Automatically detects the client IP from CF-Connecting-IP, X-Real-IP,
        X-Forwarded-For headers, or the direct connection.
        Supports content negotiation: use Accept: application/x-protobuf for protobuf response.
      operationId: root_handler
      responses:
        '200':
          description: Successful geolocation lookup
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IpGeoResponse'
  /health:
    get:
      tags:
      - Health
      summary: Health check endpoint
      description: Returns OK if the service is running.
      operationId: health_handler
      responses:
        '200':
          description: Service is healthy
          content:
            text/plain:
              schema:
                type: string
              example: OK
  /ipgeo:
    get:
      tags:
      - IP Geolocation
      summary: Get geolocation for an IP address (simple format)
      description: |-
        Returns basic geographic location data for a given IP address.
        Use the `fields` parameter with "*" or "location" for full format response.
        Supports content negotiation: use Accept: application/x-protobuf for protobuf response.
      operationId: ipgeo_handler
      parameters:
      - name: apiKey
        in: query
        description: API key (accepted but not validated)
        required: false
        schema:
          type: string
      - name: ip
        in: query
        description: IP address to lookup (IPv4 or IPv6)
        required: true
        schema:
          type: string
        example: 8.8.8.8
      - name: fields
        in: query
        description: Fields to include (optional, use "*" or "location" for full format)
        required: false
        schema:
          type: string
      responses:
        '200':
          description: Successful geolocation lookup
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IpGeoResponse'
        '400':
          description: Invalid IP address
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
  /timezone:
    get:
      tags:
      - Timezone
      summary: Get timezone for coordinates (simple format)
      description: |-
        Returns timezone name for given geographic coordinates.
        Supports content negotiation: use Accept: application/x-protobuf for protobuf response.
      operationId: timezone_handler
      parameters:
      - name: apiKey
        in: query
        description: API key (accepted but not validated)
        required: false
        schema:
          type: string
      - name: lat
        in: query
        description: Latitude coordinate (-90 to 90)
        required: true
        schema:
          type: number
          format: double
          maximum: 90
          minimum: -90
        example: 59.329504
      - name: long
        in: query
        description: Longitude coordinate (-180 to 180)
        required: true
        schema:
          type: number
          format: double
          maximum: 180
          minimum: -180
        example: 18.069532
      responses:
        '200':
          description: Successful timezone lookup
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimezoneResponse'
        '400':
          description: Invalid coordinates
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
  /v1/ipgeo:
    get:
      tags:
      - IP Geolocation
      summary: Get geolocation for an IP address (full format)
      description: |-
        Returns comprehensive location data with extended fields including
        continent, country metadata, currency, and detailed timezone information.
        Supports content negotiation: use Accept: application/x-protobuf for protobuf response.
      operationId: ipgeo_full_handler
      parameters:
      - name: apiKey
        in: query
        description: API key (accepted but not validated)
        required: false
        schema:
          type: string
      - name: ip
        in: query
        description: IP address to lookup (IPv4 or IPv6)
        required: true
        schema:
          type: string
        example: 8.8.8.8
      - name: fields
        in: query
        description: Fields to include (optional, use "*" or "location" for full format)
        required: false
        schema:
          type: string
      responses:
        '200':
          description: Successful geolocation lookup
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IpGeoResponseFull'
        '400':
          description: Invalid IP address
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
  /v1/timezone:
    get:
      tags:
      - Timezone
      summary: Get timezone for coordinates (full format)
      description: |-
        Returns comprehensive timezone details including current time,
        UTC offset, and daylight saving time information.
        Supports content negotiation: use Accept: application/x-protobuf for protobuf response.
      operationId: timezone_full_handler
      parameters:
      - name: apiKey
        in: query
        description: API key (accepted but not validated)
        required: false
        schema:
          type: string
      - name: lat
        in: query
        description: Latitude coordinate (-90 to 90)
        required: true
        schema:
          type: number
          format: double
          maximum: 90
          minimum: -90
        example: 59.329504
      - name: long
        in: query
        description: Longitude coordinate (-180 to 180)
        required: true
        schema:
          type: number
          format: double
          maximum: 180
          minimum: -180
        example: 18.069532
      responses:
        '200':
          description: Successful timezone lookup
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimezoneResponseFull'
        '400':
          description: Invalid coordinates
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
components:
  schemas:
    ApiErrorResponse:
      type: object
      description: API error response
      required:
      - error
      - code
      properties:
        code:
          type: string
          description: Machine-readable error code (INVALID_IP, INVALID_LATITUDE, INVALID_LONGITUDE)
        error:
          type: string
          description: Human-readable error message
      example:
        code: INVALID_IP
        error: 'Invalid IP address: not-an-ip'
    CountryMetadataInfo:
      type: object
      description: Country metadata including calling code, TLD, and languages
      properties:
        calling_code:
          type:
          - string
          - 'null'
          description: International calling code (e.g., "+1")
        languages:
          type:
          - array
          - 'null'
          items:
            type: string
          description: List of language codes spoken in the country
        tld:
          type:
          - string
          - 'null'
          description: Country top-level domain (e.g., ".us")
      example:
        calling_code: '+1'
        languages:
        - en-US
        - es-US
        tld: .us
    CurrencyInfo:
      type: object
      description: Currency information for the country
      properties:
        code:
          type:
          - string
          - 'null'
          description: ISO 4217 currency code (e.g., "USD")
        name:
          type:
          - string
          - 'null'
          description: Currency name (e.g., "US Dollar")
        symbol:
          type:
          - string
          - 'null'
          description: Currency symbol (e.g., "$")
      example:
        code: USD
        name: US Dollar
        symbol: $
    IpGeoResponse:
      type: object
      description: Simple IP geolocation response with basic location data
      required:
      - city
      - country_name
      - time_zone
      - languages
      properties:
        city:
          type: string
          description: City name (empty string if unknown)
        country_name:
          type: string
          description: Country name (empty string if unknown)
        languages:
          type: string
          description: Comma-separated language codes for the country
        latitude:
          type:
          - number
          - 'null'
          format: double
          description: Latitude of the location
        longitude:
          type:
          - number
          - 'null'
          format: double
          description: Longitude of the location
        time_zone:
          $ref: '#/components/schemas/TimeZoneInfo'
          description: Timezone information
      example:
        city: Mountain View
        country_name: United States
        languages: en-US,en
        latitude: 37.751
        longitude: -97.822
        time_zone:
          name: America/Chicago
    IpGeoResponseFull:
      type: object
      description: Full IP geolocation response with extended location, currency, and timezone data
      properties:
        country_metadata:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/CountryMetadataInfo'
            description: Country metadata (calling code, TLD, languages)
        currency:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/CurrencyInfo'
            description: Currency information for the country
        ip:
          type:
          - string
          - 'null'
          description: The queried IP address
        location:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/LocationInfo'
            description: Detailed location information
        time_zone:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/TimeZoneInfoFull'
            description: Detailed timezone information
      example:
        currency:
          code: USD
          name: US Dollar
          symbol: $
        ip: 8.8.8.8
        location:
          city: Mountain View
          continent_code: NA
          country_code2: US
          country_name: United States
        time_zone:
          name: America/Los_Angeles
          offset: -8
    LocationInfo:
      type: object
      description: Detailed location information including continent, country, and city data
      properties:
        city:
          type:
          - string
          - 'null'
          description: City name
        continent_code:
          type:
          - string
          - 'null'
          description: Two-letter continent code (e.g., "NA", "EU")
        continent_name:
          type:
          - string
          - 'null'
          description: Full continent name
        country_capital:
          type:
          - string
          - 'null'
          description: Capital city of the country
        country_code2:
          type:
          - string
          - 'null'
          description: ISO 3166-1 alpha-2 country code
        country_code3:
          type:
          - string
          - 'null'
          description: ISO 3166-1 alpha-3 country code
        country_emoji:
          type:
          - string
          - 'null'
          description: Country flag emoji
        country_flag:
          type:
          - string
          - 'null'
          description: Path to country flag SVG (e.g., "/static/flags/us.svg")
        country_name:
          type:
          - string
          - 'null'
          description: Common country name
        country_name_official:
          type:
          - string
          - 'null'
          description: Official country name
        district:
          type:
          - string
          - 'null'
          description: District or subdivision
        geoname_id:
          type:
          - string
          - 'null'
          description: GeoNames ID for the location
        is_eu:
          type:
          - boolean
          - 'null'
          description: Whether the country is in the European Union
        latitude:
          type:
          - string
          - 'null'
          description: Latitude as string with 5 decimal places
        longitude:
          type:
          - string
          - 'null'
          description: Longitude as string with 5 decimal places
        state_code:
          type:
          - string
          - 'null'
          description: State code with country prefix (e.g., "US-CA")
        state_prov:
          type:
          - string
          - 'null'
          description: State or province name
        zipcode:
          type:
          - string
          - 'null'
          description: Postal/ZIP code
      example:
        city: Mountain View
        continent_code: NA
        continent_name: North America
        country_capital: Washington, D.C.
        country_code2: US
        country_code3: USA
        country_emoji: 🇺🇸
        country_flag: /static/flags/us.svg
        country_name: United States
        country_name_official: United States of America
        geoname_id: '5375480'
        is_eu: false
        latitude: '37.75100'
        longitude: '-97.82200'
        state_code: US-CA
        state_prov: California
        zipcode: '94043'
    TimeZoneInfo:
      type: object
      description: Simple timezone information with just the timezone name
      required:
      - name
      properties:
        name:
          type: string
          description: IANA timezone name (e.g., "America/New_York")
      example:
        name: America/New_York
    TimeZoneInfoFull:
      type: object
      description: Detailed timezone information including DST data
      properties:
        current_time:
          type:
          - string
          - 'null'
          description: Current local time in the timezone
        current_time_unix:
          type:
          - number
          - 'null'
          format: double
          description: Current time as Unix timestamp
        dst_exists:
          type:
          - boolean
          - 'null'
          description: Whether DST is observed in this timezone
        dst_savings:
          type:
          - integer
          - 'null'
          format: int32
          description: DST offset in hours (typically 1)
        is_dst:
          type:
          - boolean
          - 'null'
          description: Whether daylight saving time is currently active
        name:
          type:
          - string
          - 'null'
          description: IANA timezone name (e.g., "America/Los_Angeles")
        offset:
          type:
          - integer
          - 'null'
          format: int32
          description: UTC offset in hours (without DST)
        offset_with_dst:
          type:
          - integer
          - 'null'
          format: int32
          description: UTC offset in hours (with DST if active)
      example:
        current_time: 2024-01-15 14:30:00.123-0800
        current_time_unix: 1705355400.123
        dst_exists: true
        dst_savings: 1
        is_dst: false
        name: America/Los_Angeles
        offset: -8
        offset_with_dst: -7
    TimezoneResponse:
      type: object
      description: Simple timezone response with just the timezone name
      required:
      - timezone
      properties:
        timezone:
          type: string
          description: IANA timezone name
      example:
        timezone: Europe/Stockholm
    TimezoneResponseFull:
      type: object
      description: Extended timezone response with offset and DST information
      required:
      - timezone
      properties:
        current_time:
          type:
          - string
          - 'null'
          description: Current local time in the timezone
        current_time_unix:
          type:
          - number
          - 'null'
          format: double
          description: Current time as Unix timestamp
        dst_exists:
          type:
          - boolean
          - 'null'
          description: Whether DST is observed in this timezone
        is_dst:
          type:
          - boolean
          - 'null'
          description: Whether daylight saving time is currently active
        offset:
          type:
          - integer
          - 'null'
          format: int32
          description: UTC offset in hours (without DST)
        offset_with_dst:
          type:
          - integer
          - 'null'
          format: int32
          description: UTC offset in hours (with DST if active)
        timezone:
          type: string
          description: IANA timezone name
      example:
        current_time: 2024-01-15 23:30:00.123+0100
        current_time_unix: 1705355400.123
        dst_exists: true
        is_dst: false
        offset: 1
        offset_with_dst: 2
        timezone: Europe/Stockholm
