{
  "openapi": "3.1.0",
  "info": {
    "title": "WorldTimeAPI-compatible API by timezone.io",
    "version": "1.0.0",
    "summary": "A free, keyless drop-in for worldtimeapi.org: the same paths and fields, over HTTP or HTTPS.",
    "description": "worldtimeapi.org shut down in 2026. This host answers its paths with the same 15 fields, in JSON or `.txt`, with no API key. Requests are limited to 60 a minute per IP address. Migration guide: https://www.timezone.io/docs/worldtimeapi",
    "termsOfService": "https://www.timezone.io/legal/terms",
    "contact": {
      "name": "timezone.io",
      "url": "https://www.timezone.io/contact"
    }
  },
  "externalDocs": {
    "description": "Migration guide",
    "url": "https://www.timezone.io/docs/worldtimeapi"
  },
  "servers": [
    {
      "url": "https://worldtime.timezone.io"
    },
    {
      "url": "http://worldtime.timezone.io",
      "description": "Plain HTTP, for devices that can't do TLS."
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "Time zones",
      "description": "Zone lists and the current time in a zone."
    },
    {
      "name": "IP address",
      "description": "The current time where an IP address is."
    }
  ],
  "paths": {
    "/api/timezone": {
      "get": {
        "operationId": "listTimezones",
        "tags": [
          "Time zones"
        ],
        "summary": "List every time zone",
        "description": "Every IANA zone name. Append `.json` for the same JSON.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/List"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/timezone.txt": {
      "get": {
        "operationId": "listTimezonesText",
        "tags": [
          "Time zones"
        ],
        "summary": "List every time zone (text)",
        "description": "Every IANA zone name. Append `.json` for the same JSON. Plain text, one name per line.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/ListText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        }
      }
    },
    "/api/timezone/{area}": {
      "get": {
        "operationId": "getArea",
        "tags": [
          "Time zones"
        ],
        "summary": "List an area's zones, or the time in a one-word zone",
        "description": "An area (`Europe`) lists its zones; a one-word zone (`UTC`) answers the time. Names match in any letter case.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/AreaOrTime"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "Europe"
          }
        ]
      }
    },
    "/api/timezone/{area}.txt": {
      "get": {
        "operationId": "getAreaText",
        "tags": [
          "Time zones"
        ],
        "summary": "List an area's zones, or the time in a one-word zone (text)",
        "description": "An area (`Europe`) lists its zones, one per line; a one-word zone (`UTC`) answers the time as `key: value` lines. Plain text, one name per line.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/AreaOrTimeText"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "Europe"
          }
        ]
      }
    },
    "/api/timezone/{area}/{location}": {
      "get": {
        "operationId": "getTime",
        "tags": [
          "Time zones"
        ],
        "summary": "The time in a zone",
        "description": "The current time in a zone such as `Europe/London`, in WorldTimeAPI's 15 fields.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Time"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "Europe"
          },
          {
            "name": "location",
            "in": "path",
            "required": true,
            "description": "Location, the second part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "London"
          }
        ]
      }
    },
    "/api/timezone/{area}/{location}.txt": {
      "get": {
        "operationId": "getTimeText",
        "tags": [
          "Time zones"
        ],
        "summary": "The time in a zone (text)",
        "description": "The current time in a zone such as `Europe/London`, in WorldTimeAPI's 15 fields. Plain text, one `key: value` line per field in alphabetical order.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/TimeText"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "Europe"
          },
          {
            "name": "location",
            "in": "path",
            "required": true,
            "description": "Location, the second part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "London"
          }
        ]
      }
    },
    "/api/timezone/{area}/{location}/{region}": {
      "get": {
        "operationId": "getTimeInRegion",
        "tags": [
          "Time zones"
        ],
        "summary": "The time in a three-part zone",
        "description": "The current time in a zone such as `America/Argentina/Salta`.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Time"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "America"
          },
          {
            "name": "location",
            "in": "path",
            "required": true,
            "description": "Location, the second part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "Argentina"
          },
          {
            "name": "region",
            "in": "path",
            "required": true,
            "description": "Region, the third part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "Salta"
          }
        ]
      }
    },
    "/api/timezone/{area}/{location}/{region}.txt": {
      "get": {
        "operationId": "getTimeInRegionText",
        "tags": [
          "Time zones"
        ],
        "summary": "The time in a three-part zone (text)",
        "description": "The current time in a zone such as `America/Argentina/Salta`. Plain text, one `key: value` line per field in alphabetical order.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/TimeText"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        },
        "parameters": [
          {
            "name": "area",
            "in": "path",
            "required": true,
            "description": "Area, the first part of a zone name, or a one-word zone such as `UTC`.",
            "schema": {
              "type": "string"
            },
            "example": "America"
          },
          {
            "name": "location",
            "in": "path",
            "required": true,
            "description": "Location, the second part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "Argentina"
          },
          {
            "name": "region",
            "in": "path",
            "required": true,
            "description": "Region, the third part of a zone name.",
            "schema": {
              "type": "string"
            },
            "example": "Salta"
          }
        ]
      }
    },
    "/api/ip": {
      "get": {
        "operationId": "getTimeForCaller",
        "tags": [
          "IP address"
        ],
        "summary": "The time where the caller is",
        "description": "The current time in the caller's time zone, located from their IP address.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Time"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/ip.txt": {
      "get": {
        "operationId": "getTimeForCallerText",
        "tags": [
          "IP address"
        ],
        "summary": "The time where the caller is (text)",
        "description": "The current time in the caller's time zone, located from their IP address. Plain text, one `key: value` line per field in alphabetical order.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/TimeText"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        }
      }
    },
    "/api/ip/{ip}": {
      "get": {
        "operationId": "getTimeForIp",
        "tags": [
          "IP address"
        ],
        "summary": "The time where an IP address is",
        "description": "The current time in the time zone an IP address is located in. `client_ip` stays the caller's address, as on WorldTimeAPI.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Time"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "An IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    },
    "/api/ip/{ip}.txt": {
      "get": {
        "operationId": "getTimeForIpText",
        "tags": [
          "IP address"
        ],
        "summary": "The time where an IP address is (text)",
        "description": "The current time in the time zone an IP address is located in. `client_ip` stays the caller's address, as on WorldTimeAPI. Plain text, one `key: value` line per field in alphabetical order.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/TimeText"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundText"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsText"
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "An IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    }
  },
  "components": {
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Requests allowed per minute.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left this minute.",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "List": {
        "description": "Zone names.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ZoneList"
            }
          }
        }
      },
      "ListText": {
        "description": "Zone names, one per line.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Africa/Abidjan\nAfrica/Accra"
          }
        }
      },
      "Time": {
        "description": "The current time in the zone.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DateTime"
            }
          }
        }
      },
      "TimeText": {
        "description": "The current time, one `key: value` line per field in alphabetical order.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "abbreviation: BST\nclient_ip: 203.0.113.7\ndatetime: 2026-09-26T05:21:59.563515+01:00"
          }
        }
      },
      "AreaOrTime": {
        "description": "An area's zone names, or the time in a one-word zone.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/ZoneList"
                },
                {
                  "$ref": "#/components/schemas/DateTime"
                }
              ]
            }
          }
        }
      },
      "AreaOrTimeText": {
        "description": "An area's zone names one per line, or the time as `key: value` lines.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown zone or area, a malformed IP address, or an address that can't be located.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "unknown location Europe/Lodnon"
            }
          }
        }
      },
      "NotFoundText": {
        "description": "Unknown zone or area, a malformed IP address, or an address that can't be located.",
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Error: unknown location"
          }
        }
      },
      "TooManyRequests": {
        "description": "More than 60 requests in a minute from one IP address.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "too many requests"
            }
          }
        }
      },
      "TooManyRequestsText": {
        "description": "More than 60 requests in a minute from one IP address.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "text/plain": {
            "schema": {
              "type": "string"
            },
            "example": "Error: too many requests"
          }
        }
      }
    },
    "schemas": {
      "ZoneList": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "example": [
          "Europe/Amsterdam",
          "Europe/Andorra"
        ]
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "DateTime": {
        "type": "object",
        "description": "WorldTimeAPI's 15 fields, in its key order.",
        "required": [
          "utc_offset",
          "timezone",
          "day_of_week",
          "day_of_year",
          "datetime",
          "utc_datetime",
          "unixtime",
          "raw_offset",
          "week_number",
          "dst",
          "abbreviation",
          "dst_offset",
          "dst_from",
          "dst_until",
          "client_ip"
        ],
        "properties": {
          "utc_offset": {
            "type": "string",
            "pattern": "^[+-]\\d{2}:\\d{2}$",
            "example": "+01:00"
          },
          "timezone": {
            "type": "string",
            "example": "Europe/London"
          },
          "day_of_week": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6,
            "description": "0 is Sunday."
          },
          "day_of_year": {
            "type": "integer",
            "minimum": 1,
            "maximum": 366
          },
          "datetime": {
            "type": "string",
            "format": "date-time",
            "description": "Local time with microseconds and offset.",
            "example": "2026-09-26T05:21:59.563515+01:00"
          },
          "utc_datetime": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-26T04:21:59.563515+00:00"
          },
          "unixtime": {
            "type": "integer",
            "example": 1790396519
          },
          "raw_offset": {
            "type": "integer",
            "description": "Standard offset from UTC in seconds, without DST.",
            "example": 0
          },
          "week_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 53,
            "description": "ISO 8601 week number."
          },
          "dst": {
            "type": "boolean"
          },
          "abbreviation": {
            "type": "string",
            "example": "BST"
          },
          "dst_offset": {
            "type": "integer",
            "description": "Seconds added for DST right now; 0 outside DST.",
            "example": 3600
          },
          "dst_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the current DST period began (UTC), or null outside DST."
          },
          "dst_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the current DST period ends (UTC), or null outside DST."
          },
          "client_ip": {
            "type": "string",
            "description": "The caller's IP address."
          }
        }
      }
    }
  }
}
