Docs

CSV and iCalendar

Any calendar window can come back as JSON, as a spreadsheet, or as a calendar file. All three are rendered from the same payload, so they cannot disagree about what a window contains.

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

format takes json (the default), csv or ics, and works on /v1/calendar and /v1/exchanges/{mic}/calendar. Both non-JSON formats come back with a Content-Disposition filename.

CSV

One row per event, flattened. The nesting that makes the JSON pleasant makes a CSV useless, so jurisdiction is repeated on every row — which is what a pivot table needs anyway.

ColumnWhat it holds
jurisdictionThe code you asked about.
date / nominal_dateObserved date, and the original where a substitution moved it.
name_en / name_localEnglish, and the name in the jurisdiction's own language and script.
originWhich jurisdiction in the chain the holiday came from — the country, for an inherited one.
closestrue or false: whether anything actually shuts.
precision, assurance, assurance_declaredThe vocabulary travels with the export. A spreadsheet that has lost the assurance column is a spreadsheet of unlabelled claims.

iCalendar

Events are all-day, with no timezone attached. That is deliberate and it is the thing most holiday feeds get wrong: a public holiday is a civil date belonging to its own jurisdiction, so shifting it into the reader's zone would put Christmas in Tokyo on the 24th for a reader in London. That is not a rendering preference, it is a wrong answer.

DetailWhat we do, and why
DTSTART;VALUE=DATEAll-day, never DATE-TIME, and no VTIMEZONE anywhere in the file.
DTENDExclusive, as the spec requires — a one-day holiday on the 25th is DTSTART 25, DTEND 26. Emitting 25 makes a zero-length event that several clients silently drop.
TRANSP:TRANSPARENTA Swedish holiday is information to a reader in Chicago, not an appointment. Free/busy is what schedulers consult, and a subscribed holiday feed should not mark you unavailable for the year.
UIDStable across exports, derived from jurisdiction, observance and date. Re-fetching updates events instead of duplicating them.
Line foldingAt 75 octets, not characters, so folding a name in Arabic, Thai or Japanese does not split a UTF-8 sequence into mojibake.
DESCRIPTIONCarries assurance, precision, operational status, the origin jurisdiction, and the nominal date where a substitution moved it. An estimated Islamic date says so inside your calendar, where you will actually be looking at it.

Why the server builds these

Because an .ics is only worth having if a calendar client can subscribe to it, and subscribing means re-fetching a URL on the client's own schedule. That needs a server emitting text/calendar at a stable address. A file built in a browser is a one-time download — the least useful form of the feature, and the form that leaves every non-browser caller with nothing.

Pre-generating files is not an option either: 241 countries × any window × assurance floor × categories × closures_only is millions of files to serve a handful of them. By the time the serializer runs, the rows are already assembled — this is a rendering step, not a second pipeline.

Subscription is not finished. You can download an .ics today. You cannot yet point Google Calendar or Outlook at a timesys URL, because a calendar client cannot send an X-API-Key header — it just fetches a URL. That needs a separate, revocable feed token in the URL itself, scoped to one saved query and revocable without touching your API key. It is not built yet, and until it is, this page will not pretend otherwise.

Two practical notes

Split by jurisdiction if you are subscribing. One file per country makes a cleaner calendar than one file with six countries' holidays interleaved — and lets a reader turn one off.

Consider closures_only=true for a work calendar. Without it you also get the observed-but-open days, which is right for planning meetings and noisy for planning cover.

← Docs   API reference   Open the console