Timezones.in — Stay In Sync

Timezone API

A small, stable JSON API for the things this site computes: the time now in any zone, conversions between zones, and daylight-saving transitions. No SDK, no sign-up for light use; a free key when you need more than 60 requests a minute.

Authentication

Anonymous requests are allowed and limited per IP. For a higher limit, create a key in your account and send it as a bearer token:

Authorization: Bearer tz_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Keys are stored hashed; we cannot show a key again after creation — revoke and create a new one if lost. A request with a revoked or malformed key is rejected with 401 invalid_key rather than silently falling back to anonymous, so you notice.

Rate limits

60 requests per minute per IP without a key; 600 per minute per key. Every response carries x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset (seconds until the window resets). Over the limit you get 429 with a retry-after header. Cache /v1/timezones on your side — it changes only when the IANA database does — and compute between calls to /v1/now rather than polling it.

Zone identifiers

Every endpoint that takes a zone accepts an IANA name (America/New_York), a legacy alias (Asia/Calcutta), or a common abbreviation (EST, IST, GMT). Abbreviations are ambiguous — IST is India, Ireland and Israel — so they resolve to the zone people usually mean (India for IST, New York for EST). Use IANA names in anything automated.

Endpoints

GET/v1/timezones

The full catalogue: every zone with its alternative name, abbreviation, country, main cities and current offset.

Request

curl "https://api.timezones.in/v1/timezones"

Response 200

[
  {
    "name": "Asia/Kolkata",
    "alternativeName": "India Time",
    "abbreviation": "IST",
    "countryCode": "IN",
    "countryName": "India",
    "continentCode": "AS",
    "mainCities": ["Mumbai", "Delhi", "Bengaluru", "Kolkata"],
    "rawOffsetInMinutes": 330,
    "currentTimeOffsetInMinutes": 330,
    "currentTimeFormat": "+05:30 India Time - Mumbai, Delhi"
  },
  …
]

GET/v1/timezones/:name

One zone with the time now and its next offset change (null when the zone never changes).

ParameterInMeaning
namepathIANA name, alias or abbreviation. Slashes may be sent as-is or URL-encoded.

Request

curl "https://api.timezones.in/v1/timezones/Europe/London"

Response 200

{
  "name": "Europe/London",
  "alternativeName": "United Kingdom Time",
  "abbreviation": "GMT",
  "countryCode": "GB",
  "mainCities": ["London", "Birmingham", "Glasgow"],
  "now": {
    "zone": "Europe/London",
    "iso": "2026-09-06T14:05:12.000+01:00",
    "offsetMinutes": 60,
    "offset": "+01:00",
    "abbreviation": "BST",
    "isDST": true,
    "epochMs": 1788699912000
  },
  "nextTransition": {
    "at": "2026-10-25T01:00:00.000Z",
    "localBefore": "2026-10-25T01:59",
    "localAfter": "2026-10-25T01:00",
    "offsetBeforeMinutes": 60,
    "offsetAfterMinutes": 0,
    "direction": "back",
    "abbreviationBefore": "BST",
    "abbreviationAfter": "GMT"
  }
}

GET/v1/now

Current time in up to 50 zones in one call.

ParameterInMeaning
zonesqueryComma-separated zone identifiers. Default UTC. Maximum 50.

Request

curl "https://api.timezones.in/v1/now?zones=Asia/Kolkata,America/New_York"

Response 200

{
  "utc": "2026-09-06T13:05:12.000Z",
  "zones": [
    { "zone": "Asia/Kolkata", "iso": "2026-09-06T18:35:12.000+05:30", "offsetMinutes": 330, "offset": "+05:30", "abbreviation": "IST", "isDST": false, "epochMs": 1788699912000, "offsetLabel": "UTC+5:30" },
    { "zone": "America/New_York", "iso": "2026-09-06T09:05:12.000-04:00", "offsetMinutes": -240, "offset": "-04:00", "abbreviation": "EDT", "isDST": true, "epochMs": 1788699912000, "offsetLabel": "UTC-4" }
  ]
}

GET/v1/convert

Convert a wall-clock time in one zone to another. Omit `at` for right now.

ParameterInMeaning
fromquerySource zone.
toqueryTarget zone.
atqueryOptional local date-time in the source zone, ISO 8601 without an offset, e.g. 2026-03-10T09:30.

Request

curl "https://api.timezones.in/v1/convert?from=Asia/Kolkata&to=Europe/London&at=2026-03-10T09:30"

Response 200

{
  "from": { "zone": "Asia/Kolkata", "iso": "2026-03-10T09:30:00.000+05:30", "offset": "+05:30", "abbreviation": "IST" },
  "to":   { "zone": "Europe/London", "iso": "2026-03-10T04:00:00.000+00:00", "offset": "+00:00", "abbreviation": "GMT" },
  "differenceMinutes": -330
}

GET/v1/transitions/:zone

The next N UTC-offset changes for a zone, to the minute. Empty list for zones without daylight saving.

ParameterInMeaning
zonepathZone identifier.
countqueryHow many transitions to return. 1–10, default 2.

Request

curl "https://api.timezones.in/v1/transitions/America/New_York?count=2"

Response 200

{
  "zone": "America/New_York",
  "transitions": [
    { "at": "2026-11-01T06:00:00.000Z", "localBefore": "2026-11-01T01:59", "localAfter": "2026-11-01T01:00", "offsetBeforeMinutes": -240, "offsetAfterMinutes": -300, "direction": "back", "abbreviationBefore": "EDT", "abbreviationAfter": "EST" },
    { "at": "2027-03-14T07:00:00.000Z", "localBefore": "2027-03-14T01:59", "localAfter": "2027-03-14T03:00", "offsetBeforeMinutes": -300, "offsetAfterMinutes": -240, "direction": "forward", "abbreviationBefore": "EST", "abbreviationAfter": "EDT" }
  ]
}

Errors

StatuserrorWhen
400unknown_zoneA zone identifier could not be resolved. The body lists the offending values where there are several.
400bad_request`at` is not a valid ISO 8601 date-time.
400validationA parameter is missing or the wrong shape.
401invalid_keyAn Authorization header is present but the key is malformed or revoked.
404unknown_zonePath zone (/v1/timezones/:name, /v1/transitions/:zone) does not exist.
429—Rate limit exceeded. Wait `retry-after` seconds.
503unavailableThe API is restarting. Retry after a few seconds.

Error bodies are always { "error": "<code>", "message": "<human-readable>" }.

Examples

JavaScript

const res = await fetch("https://api.timezones.in/v1/convert?from=Asia/Kolkata&to=America/New_York&at=2026-01-15T09:00", {
  headers: { Authorization: "Bearer tz_…" }, // optional
});
const { to, differenceMinutes } = await res.json();
console.log(to.iso, differenceMinutes); // "2026-01-14T22:30:00.000-05:00" -630

Python

import requests
r = requests.get("https://api.timezones.in/v1/now", params={"zones": "Asia/Kolkata,Europe/London"},
                 headers={"Authorization": "Bearer tz_…"})
for z in r.json()["zones"]:
    print(z["zone"], z["iso"], z["abbreviation"])

Data and accuracy

Zone rules come from the IANA tz database through ICU and are updated with each release; the catalogue (names, cities) comes from @vvo/tzdb. Transitions are computed to the minute. Governments change rules at short notice, so do not rely on this for anything where a wrong time causes harm. Report an error via the contact form.

Versioning and terms

The /v1 contract is stable: fields may be added, never removed or renamed. Free for personal and commercial use under the terms of use; do not resell raw access as your own service without attribution. “Data from timezones.in” is appreciated, not required.