For utviklere

Det åpne API-et til denne kalenderen, hvordan du bygger den inn på ditt nettsted, og nøklene som identifiserer applikasjonen din.

Tysnes Kalender — developer portal

Tysnes Kalender publishes its events through a public GraphQL API. No account, no key and no approval are needed to read it: the data is public and stays public.

  • Endpoint: https://hvaskjer-staging.web.app/graphQL
  • Documentation: API · Reference · Widget · Changelog · Keys
  • Machine-readable copies: llms.txt, schema.graphql, and every page as markdown at https://hvaskjer-staging.web.app/utviklere/<page>.md (or send Accept: text/markdown).

The API is per licence: this endpoint only ever answers with this calendar's events. Another kommune's calendar has its own endpoint, its own category ids and its own keys.

The three rules

Every one of these has cost somebody weeks. Read them before the first query.

  1. IDs are the contract. Filter and match on id (events, venues, organizers) and on category ids. Names and slugs are presentation: they are edited by people, they differ between licences, and they change. Fetch the labels from categories on every run; never cache them or write them by hand.
  2. Dates carry the UTC offset in force on the event's date. startDate and endDate look like 2026-11-01 10:00:00+01:00 in winter and 2026-07-01 10:00:00+02:00 in summer. They are not "ISO with +00", and the separator is a space, not a T. Render them in Europe/Oslo, or use startTime (the Norwegian wall clock as the organiser typed it) and duration (minutes).
  3. Nothing that comes from a form is guaranteed numeric. Price.price is typed Int and is rounded at the boundary, but the organiser may have typed 1.595 or 150,-; duration, availableTickets, minimumAge may be null. Treat every numeric field defensively.

A first call

curl -s https://hvaskjer-staging.web.app/graphQL \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ events(page: 0, pageSize: 3) { totalCount hasMore data { id title_nb startDate startTime venue { name } eventLink } } }"}'

The same query, readable:

{
  events(page: 0, pageSize: 3) {
    totalCount
    hasMore
    data {
      id
      title_nb
      startDate
      startTime
      venue { name }
      eventLink
    }
  }
}

startDate is the next upcoming occurrence of the event and repetitions lists only the future ones; past dates are never returned. page starts at 0 and pageSize defaults to 10. The API page has the filter, the date rules and the errors.

Identify yourself

Send an API key with every request:

X-Api-Key: hsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The key is identity, not security — the data is the same with or without it. What it buys you:

  • Change notices. A key carries a contact address. When a change would affect your queries (a category retired, a field renamed, a licence moved), the contacts of the keys that use those fields are told before it happens. Anonymous callers find out when something breaks.
  • Your own record. Anonymous requests are grouped by the shape of the query; with a key, yours are yours, which matters the day you ask why something looks wrong.
  • Your own quota, later. There is no rate limit today. When one arrives, keyed traffic keeps its own budget.

One key per application; a consumer reading five calendars asks each of them for a key. Create yours on the Keys page — you need an account on Tysnes Kalender with a verified e-mail address. The same page gives you a block of instructions to paste to a coding agent.

Responses to anonymous requests carry an extensions.notice string saying as much. It is informational; a client that never looks at extensions is not affected.

Markdown-versjon