Docs

Using the timesys API

Public holidays, bank and market closures, tax deadlines and calendar systems for 241 countries and more than 900 jurisdictions — with a label on every row saying how well we know it.

Your first request

Authentication is an X-API-Key header. There is no OAuth dance and no token exchange.

curl -s "https://api.timesys.pro/v1/calendar\
?jurisdictions=SE,DE-BY&from=2027-01-01&to=2027-12-31" \
  -H "X-API-Key: $TIMESYS_KEY"

Two things about that request are worth noticing. DE-BY returns Bavaria's holidays and Germany's, because subdivisions inherit their country's calendar. And the window is inclusive at both ends.

Keep the key on your server. Anything in a browser is public, whatever the minification. If you need holiday data in a front end, fetch it server-side and cache it — which you should be doing anyway, for the reason below.

The three fields that carry the honesty

Most of a response is dates. Three fields are the reason to pay for them.

assurance — how well we know it

verifiedChecked against a primary source: a gazette, a statute, a central bank notice, an exchange operator's own calendar.
corroboratedTwo or more independent secondary sources agree.
compiledOne source, or a source we cannot independently confirm. Usable, labelled, and not trusted.

Every row also carries assurance_declared — what the rule claims, next to what this particular date claims. They differ when a well-sourced rule produces a date that depends on something we cannot confirm.

Filtering with min_assurance removes rows. It does not improve the ones that remain. Because every row is labelled, deciding per row in your own code is usually better than deciding per request.

precision — how firm the date is

exactFixed and known.
estimateComputed astronomically or arithmetically and subject to local confirmation. Most Islamic dates are here: they may move by a day when the moon is actually sighted.
announcedSet by decree, for this year only.

operational_status — whether anything actually shuts

closed_general, public_sector, banks and half_day close something. optional and open do not — the day is observed and the office is working. The boolean closes collapses that to the question most callers are actually asking, and closures_only=true filters on it.

Both questions are legitimate. Is the bank open wants the filter on. Should I schedule the all-hands wants it off: nothing closes for Yom Kippur in London, and it would still empty the room.

Dates are civil dates, and are never shifted

A public holiday belongs to its jurisdiction, not to your timezone. 25 December in Tokyo is 25 December, whatever it is where you are reading from. Passing tz adds UTC bounds and the date the holiday falls on for you; it does not move the date itself.

Where a holiday has been moved by a substitution rule — a Saturday holiday taken on the following Monday — date is the observed date and nominal_date is the original. When they differ, the move is the interesting fact.

Scope, and what a 403 means

You are billed for scope: how much of the world your key may ask about. Not for calls.

PlanCountriesSubdivisions WindowRate limit
Developer1±365 days60/min
Single1yesall300/min
Professional40yesall600/min
Businessallyesall1,200/min
Enterpriseallyesall6,000/min

Countries are recorded on first use, not chosen for you by us — so a Developer key can evaluate whichever single market you actually care about. A 403 means the jurisdiction, the subdivision depth, or the window is outside what your key covers; /v1/account tells you what it does cover.

There is no call quota

None. Not a large one — none. A payroll system that checks holidays quarterly makes roughly forty thousand calls a year, so a call-tiered product would leave nearly every customer on the cheapest tier forever, and billing per call would punish exactly the caching this API asks you to do.

rate_per_minute exists only to stop a runaway loop. Reaching it returns a 429 telling you to slow down. It never generates an invoice.

Caching

Next year's holidays will not change while you sleep. Cache for a day at minimum; a week is defensible. The one endpoint with a reason to be polled is /v1/announcements/{code}, which carries the one-off decrees no rule predicts — mourning days, election days, and the confirmed dates of moon-dependent holidays.

If a date you depend on changes, we correct it, log it in the public errata, and issue a new edition. See Editions.

Errors

401No key, or a key we do not recognise.
403Outside your scope — jurisdiction, subdivision depth, or window.
404Unknown jurisdiction or exchange code. Check /v1/jurisdictions.
422The request did not validate. The body names the parameter.
429Rate limited. Abuse protection, never a bill.

Every response carries X-Request-Id. Quote it and we can find the exact request in the logs.

Aliases

Some places have two codes. Ask for either; the response says which one answered, in requested_as, so a caller who asked for FR-971 and got a block labelled GP does not have to guess whether that is the right place.

Full API reference   CSV & iCalendar   Open the console