API godzin otwarcia
Pobieranie rozwiązanych godzin otwarcia i nadchodzących świąt dla strony internetowej
Ostatnio zaktualizowano
Użyj API rozwiązanych godzin otwarcia, jeśli na publicznej stronie pokazujesz godziny sezonowe (na przykład Zomer / Winter) lub nadchodzące święta. Tillor stosuje już wyjątki, okresy sezonowe i zwykły harmonogram tygodniowy oraz dodaje ustawowe święta z żądanego zakresu. Nie musisz tego implementować od nowa.
Uprawnienie: organization:settings:read lub organization:settings:write
Klucz API zostaje po stronie serwera
Wywołuj Tillor tylko z serwera (Route Handler Next.js, Server Component lub backend). Umieść klucz w zmiennych środowiskowych. Nigdy nie wysyłaj go do przeglądarki.
Uwierzytelnianie: zobacz HTTP API. Wypróbuj endpoint w dokumentacji API lub przez OpenAPI (tag organization-settings).
Endpoint
GET https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hoursNagłówki:
x-api-key: tkn_xxxZastąp org_abc123 ID swojej organizacji.
Parametry zapytania
Użyj albo date, albo from/to. Nie łącz ich.
| Parametr | Znaczenie |
|---|---|
| (brak) | Dzisiaj w strefie czasowej organizacji |
date | Jeden dzień kalendarzowy (YYYY-MM-DD) |
from | Dzień początkowy (włącznie). Bez to: tylko ten dzień |
to | Dzień końcowy (włącznie). Wymaga from. Maksymalnie 366 dni |
languageIsoCode | Język nazw świąt (NL, FR, …). Domyślnie: język organizacji |
Odpowiedź
Każdy element to jeden dzień kalendarzowy, już rozwiązany:
| Pole | Znaczenie |
|---|---|
timeZone | Strefa czasowa IANA organizacji |
from / to | Żądany zakres |
holidays | Ustawowe święta, które nakładają się na from–to |
items[].date | Dzień kalendarzowy YYYY-MM-DD |
items[].weekday | monday … sunday |
items[].source | exception, period lub regular |
items[].periodLabel | Tylko przy source: "period": etykieta z Tillor, na przykład "Zomer" lub "Winter" |
items[].holiday | Tylko gdy ten dzień jest ustawowym świętem: { id, name, startDate, endDate } |
items[].blocks | Przedziały czasu w minutach od północy |
items[].closed | true, gdy blocks jest puste |
Priorytet: wyjątek (święto lub własny zakres) → ostatni pasujący okres sezonowy → zwykły harmonogram tygodniowy.
Etykiety sezonów pochodzą z Ustawienia > Godziny otwarcia. Okresy mogą przechodzić przez przełom roku (na przykład od 1 listopada do 31 marca). Dni poza każdym okresem wracają do zwykłego harmonogramu tygodniowego (source: "regular", bez periodLabel).
Minuty na godzinę zegarową
startMinutes / endMinutes to minuty od 00:00.
| Minuty | Godzina |
|---|---|
| 540 | 09:00 |
| 600 | 10:00 |
| 720 | 12:00 |
| 780 | 13:00 |
| 1020 | 17:00 |
| 1140 | 19: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")}`;
}Przykłady
Dzień w okresie sezonowym
curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?date=2026-07-15" \
-H "x-api-key: tkn_xxx"{
"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, godziny letnie.
Dzień poza okresami sezonowymi
curl -X GET "https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hours?date=2026-01-15" \
-H "x-api-key: tkn_xxx"{
"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 i 13:00–17:00.
Zakres przekraczający granicę okresu
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"| Data | source | periodLabel |
|---|---|---|
| 2026-03-30 | regular | - |
| 2026-03-31 | regular | - |
| 2026-04-01 | period | Zomer |
| 2026-04-02 | period | Zomer |
Nadchodzące święta
Ustawowe święta są w tej samej odpowiedzi: holidays dla listy (nazwa + daty), items[].holiday, gdy dany dzień kalendarzowy jest świętem. Godziny pozostają rozwiązanym harmonogramem; święto bez wprowadzonego w Tillor wyjątku podąża za harmonogramem sezonowym lub tygodniowym (source nie jest wtedy "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"{
"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
}
]
}Powyższy przykład items jest skrócony; prawdziwa odpowiedź zawiera każdy dzień z zakresu. Ferie szkolne nie są częścią tego endpointu; nadal służy do nich GET /holidays?kind=school.
Next.js (serwer)
Dla widżetu tygodniowego lub „teraz otwarte” na publicznej stronie:
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 ?? "",
},
next: { tags: ["opening-hours"], revalidate: 3600 },
});
if (!response.ok) {
throw new Error(`Tillor opening hours ${response.status}`);
}
return response.json() as Promise<OpeningHoursResponse>;
}holidays to lista dla bloku „nadchodzące święta”. items[].holiday przydaje się w kalendarzu tygodniowym. items[].periodLabel to tekst sezonu (na przykład "Zomer" lub "Winter"). Cache na 1 godzinę zwykle wystarcza.
Unieważnianie cache (webhook)
Przy każdej zmianie ustawień organizacji Tillor wysyła organizationSettings:updated (webhook i SSE). Subskrybuj to zdarzenie i pobierz godziny otwarcia ponownie. Payload jest celowo mały (bez adresów IP drukarek ani pełnego harmonogramu):
{
"event": "organizationSettings:updated",
"data": {
"openingHoursChanged": true
},
"timestamp": 1787829600000
}openingHoursChanged ma wartość true, gdy zmieni się harmonogram godzin otwarcia, strefa czasowa lub kraj domyślny - to wpływa na GET .../opening-hours. Przy false możesz zostawić cache godzin otwarcia bez zmian.
Przykład Route Handlera Next.js:
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 });
}Tworzenie webhooka: zobacz Webhooki. Klucz zdarzenia: organizationSettings:updated (uprawnienie organization:settings:read lub organization:settings:write).
Pełny harmonogram (opcjonalnie)
Potrzebny tylko wtedy, gdy chcesz sam pokazać kalendarz sezonów (etykiety + fromMonth/untilDay), bez rozwiązywania dzień po dniu:
GET https://tillor.eu/api/orgs/org_abc123/organization-settingsOdczytaj openingHoursSchedule.periods (etykiety takie jak "Zomer") i openingHoursSchedule.weekdays (zwykły harmonogram). Dla samej strony internetowej najprostszym źródłem pozostaje GET .../opening-hours.
MCP
W Cursorze lub Claude: endpoint organizationSettings_listOpeningHours (kategoria organizationSettings), argumenty organizationId, opcjonalnie date lub from/to, opcjonalnie languageIsoCode.
Powiązane
- HTTP API - uwierzytelnianie i nagłówki
- Przykłady HTTP - ogólne przykłady cURL
- Webhooki -
organizationSettings:updateddo unieważniania cache - Ustawienia organizacji - ustawianie godzin otwarcia w Tillor