Guide

Exchange calendar API: check if a market is open, in code

Market hours look like a constant until the first half day, lunch break or clock change. Put the calendar behind one request and let your code ask.

On this page
  1. Why a trading calendar belongs behind an API
  2. The exchange calendar API in four endpoints
  3. Is the stock market open today? One request
  4. Global market hours for a watchlist with /markets/status/bulk
  5. Asian stock market hours, lunch breaks and DST with /markets/sessions
  6. Holidays and half days with /markets/holidays
  7. Patterns that keep it cheap and correct
  8. Questions

Key takeaways

  • GET /markets/status returns whether a market is open, its phase and the next regular open and close, with holidays, early closes and daylight saving applied.
  • is_open is true in pre-market and after-hours too; test status or phase when you mean the regular session.
  • GET /markets/status/bulk checks up to 25 instruments in one request, and an unknown item fails alone while the response stays 200.
  • GET /markets/sessions returns a local day's trading windows in UTC, and GET /markets/holidays lists every closure and early close for a year.
  • The at parameter evaluates any instant, so holiday and half-day logic can be tested in CI instead of waiting for Thanksgiving.

An exchange calendar API tells your code whether a market is open right now, which session it is in, and when it next opens or closes, with holidays, half days and daylight saving time already applied. TickerLayer exposes one as four REST endpoints: GET /markets/status, /markets/status/bulk, /markets/sessions and /markets/holidays. They cover 20 regional stock calendars plus crypto, forex and commodities, and they answer from a curated calendar rather than from live prices.

If you want the hours themselves rather than code, the guide to stock market hours covers the US schedule in every time zone. This page is the developer layer: real requests, real responses from September 28, 2026, and the edge cases that make hard-coded schedules fail.

Why a trading calendar belongs behind an API

  • Clocks moveThe US changes clocks on March 8 and November 1, 2026, Europe on March 29 and October 25, and most of Asia never. For weeks each year the gaps between markets change.
  • Half daysUS exchanges close at 1:00 p.m. ET on November 27 and December 24, 2026. A job that waits for 4:00 p.m. runs three hours late.
  • Lunch breaksTokyo, Hong Kong and Shanghai stop for lunch, and Thailand pauses from 12:30 to 14:30. "Open 9 to 5" is wrong in both halves.
  • Different weekendsThe Saudi market trades Sunday to Thursday. A Monday-to-Friday assumption misses one trading day and invents another.
  • Clustered holidaysJapan closed Monday to Wednesday, September 21 to 23, 2026: two public holidays and the bridge day between them.
  • Moving feastsLunar New Year, Eid and Easter move every year, so last year's holiday list is wrong this year.

The exchange calendar API in four endpoints

EndpointAnswersKey parameters
GET /markets/statusIs it open now, which phase, next open and close. With no parameters: one overview of every regionasset, symbol, market, at, includeSessions
GET /markets/status/bulkThe same, for up to 25 instruments in one callitems as asset:symbol, at
GET /markets/sessionsOne local day's trading windows, in UTCmarket (or asset and symbol), date
GET /markets/holidaysClosures and early closes for a yearmarket, year, start, end
Regional codes: US, AR, BR, MX, GB, DE, FR, ES, IT, TR, IN, JP, CN, HK, KR, SA, AE, SE, TW, TH, plus CRYPTO, FOREX, COMMODITIES and GLOBAL. Each call costs one request.

Is the stock market open today? One request

Pass a market, or an asset and symbol, and you get one status object. The at parameter evaluates any instant instead of now, which is how this response describes Thanksgiving morning although it was requested in September:

Shell
curl -sS "https://api.tickerlayer.com/markets/status?asset=stocks&market=US&at=2026-11-26T15:00:00Z" \
  -H "x-api-key: $TICKERLAYER_API_KEY"

US status at 10:00 a.m. ET on Thanksgiving 2026

{
  "asset": "stocks",
  "market": "US",
  "status": "closed",
  "is_open": false,
  "phase": "holiday",1
  "reason": "Regional calendar closure",
  "timestamp": "2026-11-26T15:00:00.000Z",2
  "timezone": "America/New_York",
  "local_time": "2026-11-26T10:00:00.000-05:00",
  "next_open": "2026-11-27T14:30:00.000Z",3
  "next_close": "2026-11-27T18:00:00.000Z",4
  "holiday": {5
    "date": "2026-11-26",
    "name": "Thanksgiving Day",
    "schedule": "closed",
    "is_open": false,
    "observed": true
  },
  "meta": { "calendar_version": "v1-static-2026-2027" }
}
  1. phaseWhy it is closed: holiday here. Other values include primary, pre_market, post_market, closed, weekend and early_close.
  2. timestampThe instant evaluated: the at you passed, or the current time.
  3. next_openFriday's 9:30 a.m. ET open, in UTC. 14:30Z, because New York is back on standard time.
  4. next_close18:00Z is 1:00 p.m. ET. The day after Thanksgiving is a half day, and the calendar already knows.
  5. holidayPresent when a calendar row applies to the local date. The nested object has no memo field; the holidays route always sends one.
Live response captured on September 28, 2026 with at=2026-11-26T15:00:00Z. The long meta.data_notice string is trimmed.

Three fields answer different questions, and mixing them up is the classic bug:

QuestionReadWatch out for
Is the regular session on?status == "open"status is pre_market or post_market in extended hours
Is any session active?is_openTrue in pre-market and after-hours as well
Why is it closed?phase and reasonclosed covers both night and a midday break; reason tells them apart
When does it open next?next_openOmitted while the regular session runs, and for 24/7 markets

The overview has a trap of its own. Called with no parameters, /markets/status returns a regions map with one word per market. At 10:50 UTC on September 28 it read "us": "open" while the detail call said pre_market: the map flattens is_open. Use it to color a world map, not to drive trading logic.

Global market hours for a watchlist with /markets/status/bulk

Dashboards rarely care about one market. The bulk route takes up to 25 asset:symbol items, resolves each to its calendar and returns one row per item. An unknown item comes back as a row with an error while the others succeed, so one typo does not blank the board:

board.pyPython
import os
from datetime import datetime, timezone

import requests

BASE_URL = "https://api.tickerlayer.com"
session = requests.Session()
session.headers["x-api-key"] = os.environ["TICKERLAYER_API_KEY"]

WATCHLIST = [
    "stocks:US:KO",
    "stocks:DE:SAP",
    "stocks:JP:7203",
    "stocks:HK:0700",
    "forex:EURUSD",
    "crypto:BTCUSD",
    "stocks:XX:NOPE",
]


def get(path, **params):
    resp = session.get(BASE_URL + path, params=params, timeout=10)
    resp.raise_for_status()
    return resp.json()


def countdown(iso):
    """'2026-09-28T13:30:00.000Z' -> 'in 2h 32m' (or '' when absent)."""
    if not iso:
        return ""
    when = datetime.fromisoformat(iso.replace("Z", "+00:00"))
    minutes = int((when - datetime.now(timezone.utc)).total_seconds() // 60)
    days, rest = divmod(minutes, 1440)
    hours, mins = divmod(rest, 60)
    return f"in {days}d {hours}h" if days else f"in {hours}h {mins:02d}m"


board = get("/markets/status/bulk", items=",".join(WATCHLIST))
print(f"{'SYMBOL':<9} {'MARKET':<7} {'PHASE':<11} {'OPENS':<11} CLOSES")
for row in board["data"]:
    if "error" in row:  # unresolved items fail alone; the response is still 200
        print(f"{row['item']:<17} error {row['error']['code']}")
        continue
    print(
        f"{row['symbol']:<9} {row['market']:<7} {row['phase']:<11} "
        f"{countdown(row.get('next_open')):<11} {countdown(row.get('next_close'))}"
    )
Output (10:58 UTC, Monday, September 28, 2026)
SYMBOL    MARKET  PHASE       OPENS       CLOSES
US:KO     US      pre_market  in 2h 32m   in 9h 02m
DE:SAP    DE      primary                 in 4h 32m
JP:7203   JP      closed      in 13h 02m  in 19h 32m
HK:0700   HK      closed      in 14h 32m  in 21h 02m
EURUSD    FOREX   primary                 in 4d 11h
BTCUSD    CRYPTO  primary
stocks:XX:NOPE    error UNRESOLVED

Price the call before you ship it: one bulk request per board refresh, never one status call per row, and never one per tick. The calendar only changes at session boundaries, so refreshing when the nearest next_open or next_close passes is enough. Even a 25-market board then needs well under a hundred bulk requests a day, against 1,440 at one a minute.

Asian stock market hours, lunch breaks and DST with /markets/sessions

The sessions route answers "what does this market's day look like" in UTC, with that local date's time zone rules applied. The US calendar returns a 13:30 UTC open for September 28 and a 14:30 UTC open for November 2, the first Monday after New York leaves daylight time, with no code on your side. Thailand, which pauses at midday, comes back as two primary windows:

GET /markets/sessions?market=TH&date=2026-09-29JSON
{
  "market": "TH",
  "date": "2026-09-29",
  "timezone": "Asia/Bangkok",
  "is_open": true,
  "holiday": null,
  "sessions": [
    { "phase": "primary", "status": "open", "start": "2026-09-29T03:00:00.000Z", "end": "2026-09-29T05:30:00.000Z" },
    { "phase": "primary", "status": "open", "start": "2026-09-29T07:30:00.000Z", "end": "2026-09-29T09:30:00.000Z" }
  ],
  "meta": { "calendar_version": "v1-static-2026-2027" }
}

Windows carry "status": "open" for the regular session and "available" for extended hours such as US pre-market. On a weekend or holiday the windows still come back with their scheduled times, each marked "closed", so you can always draw the shape of a normal day. One limit to know: the API models the Thailand break today, while Tokyo, Hong Kong and Shanghai come back as one continuous window. Their breaks are on the country pages, for example Japan market hours.

Global market hours on a UTC clock

TokyoUTC+9
Hong KongUTC+8
ShanghaiUTC+8
BangkokUTC+7
MumbaiUTC+5:30
FrankfurtUTC+2 in summer
LondonUTC+1 in summer
New YorkUTC-4 in summer

Hours in UTC

Regular sessions on a late-September weekday, with Europe and the US on summer time. Gaps are midday breaks. None of the Asian markets shown observe daylight saving time.

Holidays and half days with /markets/holidays

The holidays route returns a year of closures and early closes for one calendar. Combine it with the sessions route and you can describe any day in full. This script lists the US half days of 2026, then prints the day after Thanksgiving in UTC:

calendar_check.pyPython
import os

import requests

BASE_URL = "https://api.tickerlayer.com"
HEADERS = {"x-api-key": os.environ["TICKERLAYER_API_KEY"]}


def get(path, **params):
    resp = requests.get(BASE_URL + path, params=params, headers=HEADERS, timeout=10)
    resp.raise_for_status()
    return resp.json()


# 1. Every early close in the US calendar for 2026.
cal = get("/markets/holidays", market="US", year=2026)
for day in cal["holidays"]:
    if day["schedule"] == "early_close":
        print("early close:", day["date"], day["name"])

# 2. What the day after Thanksgiving looks like, in UTC, DST already applied.
day = get("/markets/sessions", market="US", date="2026-11-27")
for window in day["sessions"]:
    print(f"{window['phase']:<12} {window['start'][11:16]} to {window['end'][11:16]} UTC")
Output
early close: 2026-11-27 Post-holiday early close
early close: 2026-12-24 Christmas Eve early close
pre_market   09:00 to 14:30 UTC
primary      14:30 to 18:00 UTC
post_market  18:00 to 22:00 UTC

Early-close rows carry "is_open": true, because the market does open; full closures carry false. meta.completeness is full when a market's year is fully seeded and partial when it is not, which is your cue to fall back to a conservative default instead of assuming the market is open. On the half day, after-hours ends at 5:00 p.m. ET (22:00 UTC), not 8:00 p.m.

Patterns that keep it cheap and correct

  1. Ask once, then sleepRead next_open or next_close and schedule the next check for that instant, instead of polling every minute all night.
  2. Cache per local daySessions and holidays come from a versioned static calendar (calendar_version "v1-static-2026-2027"). Fetch them once a day per market.
  3. Test with atPass at=2026-11-27T19:00:00Z and the API answers post_market for the half day. Put Thanksgiving, a daylight saving Monday and a weekend in your test suite.
  4. Gate on the data as wellThe calendar says when a market should trade, not that a quote arrived. Check quote timestamps, and follow trading halts for single stocks.
  5. Give agents the same clockThe MCP server exposes get_market_status, get_market_sessions and get_market_holidays, so an assistant can check the calendar before quoting a price. See financial MCP server.

For people rather than programs, every calendar also has a page: the world market hours map shows 38 markets, and each country page, such as United States, lists sessions, breaks and the 2026 holidays. Currencies run on their own weekly clock, covered in forex market hours, and the US extended sessions in after-hours trading.

Questions

Is the stock market open today?

US stocks trade Monday to Friday, 9:30 a.m. to 4:00 p.m. ET, except market holidays. In code, call GET /markets/status?asset=stocks&market=US: status reads open during the regular session, and phase explains any closure.

What is an exchange calendar?

A dataset of a market's trading days, session times, holidays and early closes, in the market's own time zone. An exchange calendar API turns it into answers such as "open now" and "next open at 13:30 UTC".

What is the difference between a trading calendar and market hours?

Market hours are the normal daily schedule. A trading calendar adds which specific days in a year are trading days, holidays or shortened sessions.

Does the API handle daylight saving time?

Yes. Sessions are defined in each market's time zone and returned in UTC for the date you ask about, so the US open is 13:30 UTC in summer and 14:30 UTC in winter without any conversion on your side.

What are Asian stock market hours in UTC?

On a normal weekday: Tokyo 00:00 to 06:30 with a lunch break, Hong Kong 01:30 to 08:00 and Shanghai 01:30 to 07:00, both with lunch breaks, Mumbai 03:45 to 10:00, and Bangkok 03:00 to 09:30 with a midday pause. None of these markets change clocks.

How many markets does the calendar cover?

The API covers 20 regional stock calendars plus crypto, forex and commodities. The public market-hours pages cover 38 markets.

Keep reading

Ready to integrate?

Start with the free tier, explore the docs, and connect via REST or WebSocket in minutes.