Tillor
OntwikkelaarsVoorbeelden

Openingsuren API

Opgeloste openingsuren en komende feestdagen ophalen voor een website

Gebruik de opgeloste openingsuren-API als je seizoensuren (bijvoorbeeld Zomer / Winter) of komende feestdagen op een publieke site toont. Tillor past al uitzonderingen, seizoensperiodes en het gewone weekrooster toe, en voegt wettelijke feestdagen in de gevraagde range toe. Je hoeft dat niet opnieuw te implementeren.

Permissie: organization:settings:read of organization:settings:write

API-sleutel blijft server-side

Roep Tillor alleen aan vanuit een server (Next.js Route Handler, Server Component of backend). Zet de sleutel in omgevingsvariabelen. Stuur hem nooit naar de browser.

Authenticatie: zie HTTP API. Probeer het endpoint in de API Playground of via OpenAPI (tag organization-settings).

Endpoint

GET https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours

Headers:

x-api-key: tkn_xxx
X-Tillor-Org-Id: org_abc123

Vervang org_abc123 door het organisatie-ID (hetzelfde als in X-Tillor-Org-Id).

Queryparameters

Gebruik of date, of from/to. Combineer ze niet.

ParameterBetekenis
(geen)Vandaag in de timezone van de organisatie
dateEén kalenderdag (YYYY-MM-DD)
fromBegindag (inclusief). Zonder to: alleen die dag
toEinddag (inclusief). Vereist from. Maximaal 366 dagen
languageIsoCodeTaal voor feestdagnamen (NL, FR, …). Standaard: locale van de organisatie

Response

Elk item is één kalenderdag, al opgelost:

VeldBetekenis
timeZoneIANA-timezone van de organisatie
from / toGevraagde range
holidaysWettelijke feestdagen die overlap hebben met fromto
items[].dateKalenderdag YYYY-MM-DD
items[].weekdaymondaysunday
items[].sourceexception, period of regular
items[].periodLabelAlleen bij source: "period": het label uit Tillor, bijvoorbeeld "Zomer" of "Winter"
items[].holidayAlleen als die dag een wettelijke feestdag is: { id, name, startDate, endDate }
items[].blocksTijdvakken in minuten vanaf middernacht
items[].closedtrue als blocks leeg is

Prioriteit: uitzondering (feestdag of custom range) → laatste matching seizoensperiodegewoon weekrooster.

Seizoenslabels komen uit Instellingen > Openingsuren. Periodes mogen over de jaarwisseling lopen (bijvoorbeeld 1 november t/m 31 maart). Dagen buiten elke periode vallen terug op het gewone weekrooster (source: "regular", geen periodLabel).

Minuten naar kloktijd

startMinutes / endMinutes zijn minuten vanaf 00:00.

MinutenTijd
54009:00
60010:00
72012:00
78013:00
102017:00
114019:00
function formatMinutes(minutes: number): string {
  const hour = Math.floor(minutes / 60);
  const minute = minutes % 60;
  return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
}

Voorbeelden

Dag in een seizoensperiode

curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?date=2026-07-15" \
  -H "x-api-key: tkn_xxx" \
  -H "X-Tillor-Org-Id: org_abc123"
{
  "timeZone": "Europe/Brussels",
  "from": "2026-07-15",
  "to": "2026-07-15",
  "holidays": [],
  "items": [
    {
      "date": "2026-07-15",
      "weekday": "wednesday",
      "source": "period",
      "periodLabel": "Zomer",
      "blocks": [{ "startMinutes": 540, "endMinutes": 720 }],
      "closed": false
    }
  ]
}

09:00–12:00, Zomeruren.

Dag buiten seizoensperiodes

curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?date=2026-01-15" \
  -H "x-api-key: tkn_xxx" \
  -H "X-Tillor-Org-Id: org_abc123"
{
  "timeZone": "Europe/Brussels",
  "from": "2026-01-15",
  "to": "2026-01-15",
  "holidays": [],
  "items": [
    {
      "date": "2026-01-15",
      "weekday": "thursday",
      "source": "regular",
      "blocks": [
        { "startMinutes": 540, "endMinutes": 720 },
        { "startMinutes": 780, "endMinutes": 1020 }
      ],
      "closed": false
    }
  ]
}

09:00–12:00 en 13:00–17:00.

Range over een periodegrens

curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?from=2026-03-30&to=2026-04-02" \
  -H "x-api-key: tkn_xxx" \
  -H "X-Tillor-Org-Id: org_abc123"
DatumsourceperiodLabel
2026-03-30regular
2026-03-31regular
2026-04-01periodZomer
2026-04-02periodZomer

Komende feestdagen

Wettelijke feestdagen zitten in dezelfde response: holidays voor een lijst (naam + datums), items[].holiday als die kalenderdag een feestdag is. Uren blijven het opgeloste rooster; een feestdag zonder ingevulde uitzondering in Tillor volgt het seizoen- of weekrooster (source is dan niet "exception").

curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?from=2026-08-27&to=2026-12-31&languageIsoCode=NL" \
  -H "x-api-key: tkn_xxx" \
  -H "X-Tillor-Org-Id: org_abc123"
{
  "timeZone": "Europe/Brussels",
  "from": "2026-08-27",
  "to": "2026-12-31",
  "holidays": [
    {
      "id": "0fad0035-6b77-404a-953d-c66dac014483",
      "name": "Allerheiligen",
      "startDate": "2026-11-01",
      "endDate": "2026-11-01"
    },
    {
      "id": "d90e5f53-bc92-4860-bdae-f7e75935848d",
      "name": "Kerstmis",
      "startDate": "2026-12-25",
      "endDate": "2026-12-25"
    }
  ],
  "items": [
    {
      "date": "2026-11-01",
      "weekday": "sunday",
      "source": "regular",
      "holiday": {
        "id": "0fad0035-6b77-404a-953d-c66dac014483",
        "name": "Allerheiligen",
        "startDate": "2026-11-01",
        "endDate": "2026-11-01"
      },
      "blocks": [],
      "closed": true
    }
  ]
}

Het items-voorbeeld hierboven is ingekort; de echte response bevat elke dag in de range. Schoolvakanties zitten niet in dit endpoint; die blijven GET /holidays?kind=school.

Next.js (server)

Voor een weekwidget of “nu open” op een publieke site:

const TILLOR_API_URL = "https://tillor.eu";
const ORGANIZATION_ID = process.env.TILLOR_ORG_ID ?? "";

type OpeningHoursBlock = {
  startMinutes: number;
  endMinutes: number;
};

type OpeningHoursHoliday = {
  id: string;
  name: string;
  startDate: string;
  endDate: string;
};

type OpeningHoursItem = {
  date: string;
  weekday: string;
  source: "exception" | "period" | "regular";
  periodLabel?: string;
  holiday?: OpeningHoursHoliday;
  blocks: OpeningHoursBlock[];
  closed: boolean;
};

type OpeningHoursResponse = {
  timeZone: string;
  from: string;
  to: string;
  holidays: OpeningHoursHoliday[];
  items: OpeningHoursItem[];
};

export async function getOpeningHours(
  from: string,
  to: string,
): Promise<OpeningHoursResponse> {
  const url = new URL(
    `${TILLOR_API_URL}/api/orgs/${ORGANIZATION_ID}/organization-settings/opening-hours`,
  );
  url.searchParams.set("from", from);
  url.searchParams.set("to", to);
  url.searchParams.set("languageIsoCode", "NL");

  const response = await fetch(url, {
    headers: {
      "x-api-key": process.env.TILLOR_API_KEY ?? "",
      "X-Tillor-Org-Id": ORGANIZATION_ID,
    },
    next: { tags: ["opening-hours"], revalidate: 3600 },
  });

  if (!response.ok) {
    throw new Error(`Tillor opening hours ${response.status}`);
  }

  return response.json() as Promise<OpeningHoursResponse>;
}

holidays is de lijst voor een “komende feestdagen”-blok. items[].holiday is handig in een weekkalender. items[].periodLabel is seizoenstekst (bijvoorbeeld "Zomer" of "Winter"). Cache 1 uur is meestal genoeg.

Cache ongeldig maken (webhook)

Bij elke wijziging van organisatie-instellingen stuurt Tillor organizationSettings:updated (webhook en SSE). Abonneer daarop en haal openingsuren opnieuw op. De payload is expres klein (geen printer-IP’s of het volledige rooster):

{
  "event": "organizationSettings:updated",
  "data": {
    "openingHoursChanged": true
  },
  "timestamp": 1787829600000
}

openingHoursChanged is true als het openingsurenrooster, de timezone of het standaardland wijzigt — dat is wat GET .../opening-hours beïnvloedt. Bij false kun je de openingsuren-cache laten staan.

Voorbeeld Next.js Route Handler:

import { revalidateTag } from "next/cache";

export async function POST(request: Request) {
  const body = (await request.json()) as {
    event?: string;
    data?: { openingHoursChanged?: boolean };
  };
  if (body.event === "organizationSettings:updated" && body.data?.openingHoursChanged) {
    await revalidateTag("opening-hours");
  }
  return new Response(null, { status: 204 });
}

Webhook aanmaken: zie Webhooks. Event key: organizationSettings:updated (permissie organization:settings:read of organization:settings:write).

Volledig rooster (optioneel)

Alleen nodig als je de seizoenskalender zelf wilt tonen (labels + fromMonth/untilDay), zonder per dag op te lossen:

GET https://tillor.eu/api/orgs/org_abc123/organization-settings

Lees openingHoursSchedule.periods (labels zoals "Zomer") en openingHoursSchedule.weekdays (gewoon rooster). Voor de website zelf blijft GET .../opening-hours de eenvoudigste bron.

MCP

In Cursor of Claude: endpoint organizationSettings_listOpeningHours (categorie organizationSettings), argumenten organizationId, optioneel date of from/to, optioneel languageIsoCode.

Gerelateerd

On this page