API des heures d'ouverture
Récupérer les heures d'ouverture résolues et les prochains jours fériés pour un site web
Dernière mise à jour le
Utilisez l'API des heures d'ouverture résolues si vous affichez sur un site public des horaires saisonniers (par exemple Zomer / Winter) ou les prochains jours fériés. Tillor applique déjà les exceptions, les périodes saisonnières et l'horaire hebdomadaire habituel, et ajoute les jours fériés légaux de la plage demandée. Vous n'avez pas à le réimplémenter.
Permission : organization:settings:read ou organization:settings:write
La clé API reste côté serveur
N'appelez Tillor que depuis un serveur (Route Handler Next.js, Server Component ou backend). Placez la clé dans des variables d'environnement. Ne l'envoyez jamais au navigateur.
Authentification : voir API HTTP. Essayez l'endpoint dans la référence de l'API ou via OpenAPI (tag organization-settings).
Endpoint
GET https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hoursEn-têtes :
x-api-key: tkn_xxxRemplacez org_abc123 par l'ID de votre organisation.
Paramètres de requête
Utilisez soit date, soit from/to. Ne les combinez pas.
| Paramètre | Signification |
|---|---|
| (aucun) | Aujourd'hui, dans le fuseau horaire de l'organisation |
date | Un seul jour calendaire (YYYY-MM-DD) |
from | Premier jour (inclus). Sans to : uniquement ce jour |
to | Dernier jour (inclus). Nécessite from. Maximum 366 jours |
languageIsoCode | Langue des noms de jours fériés (NL, FR, …). Par défaut : la langue de l'organisation |
Réponse
Chaque élément correspond à un jour calendaire, déjà résolu :
| Champ | Signification |
|---|---|
timeZone | Fuseau horaire IANA de l'organisation |
from / to | Plage demandée |
holidays | Jours fériés légaux qui chevauchent from–to |
items[].date | Jour calendaire YYYY-MM-DD |
items[].weekday | monday … sunday |
items[].source | exception, period ou regular |
items[].periodLabel | Uniquement pour source: "period" : le libellé défini dans Tillor, par exemple "Zomer" ou "Winter" |
items[].holiday | Uniquement si ce jour est un jour férié légal : { id, name, startDate, endDate } |
items[].blocks | Plages horaires en minutes depuis minuit |
items[].closed | true si blocks est vide |
Priorité : exception (jour férié ou plage personnalisée) → dernière période saisonnière correspondante → horaire hebdomadaire habituel.
Les libellés de saison proviennent de Paramètres > Heures d'ouverture. Les périodes peuvent chevaucher le changement d'année (par exemple du 1er novembre au 31 mars). Les jours hors de toute période retombent sur l'horaire hebdomadaire habituel (source: "regular", pas de periodLabel).
Minutes en heure d'horloge
startMinutes / endMinutes sont des minutes à partir de 00:00.
| Minutes | Heure |
|---|---|
| 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")}`;
}Exemples
Jour dans une période saisonnière
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, horaires d'été.
Jour hors des périodes saisonnières
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 et 13:00–17:00.
Plage à cheval sur une limite de période
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"| Date | source | periodLabel |
|---|---|---|
| 2026-03-30 | regular | - |
| 2026-03-31 | regular | - |
| 2026-04-01 | period | Zomer |
| 2026-04-02 | period | Zomer |
Prochains jours fériés
Les jours fériés légaux figurent dans la même réponse : holidays pour une liste (nom + dates), items[].holiday si ce jour calendaire est un jour férié. Les heures restent celles de l'horaire résolu ; un jour férié sans exception saisie dans Tillor suit l'horaire saisonnier ou hebdomadaire (source n'est alors pas "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
}
]
}L'exemple de items ci-dessus est abrégé ; la vraie réponse contient chaque jour de la plage. Les vacances scolaires ne font pas partie de cet endpoint ; elles restent disponibles via GET /holidays?kind=school.
Next.js (serveur)
Pour un widget hebdomadaire ou un « ouvert maintenant » sur un site public :
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 est la liste pour un bloc « prochains jours fériés ». items[].holiday est utile dans un calendrier hebdomadaire. items[].periodLabel est le texte de saison (par exemple "Zomer" ou "Winter"). Un cache d'une heure suffit généralement.
Invalider le cache (webhook)
À chaque modification des paramètres de l'organisation, Tillor envoie organizationSettings:updated (webhook et SSE). Abonnez-vous à cet événement et récupérez à nouveau les heures d'ouverture. Le payload est volontairement réduit (ni adresses IP d'imprimantes ni horaire complet) :
{
"event": "organizationSettings:updated",
"data": {
"openingHoursChanged": true
},
"timestamp": 1787829600000
}openingHoursChanged vaut true lorsque l'horaire d'ouverture, le fuseau horaire ou le pays par défaut change - c'est ce qui influence GET .../opening-hours. Si la valeur est false, vous pouvez conserver le cache des heures d'ouverture.
Exemple de Route Handler 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 });
}Créer un webhook : voir Webhooks. Clé d'événement : organizationSettings:updated (permission organization:settings:read ou organization:settings:write).
Horaire complet (facultatif)
Nécessaire uniquement si vous voulez afficher vous-même le calendrier saisonnier (libellés + fromMonth/untilDay), sans résolution jour par jour :
GET https://tillor.eu/api/orgs/org_abc123/organization-settingsLisez openingHoursSchedule.periods (libellés comme "Zomer") et openingHoursSchedule.weekdays (horaire habituel). Pour le site web lui-même, GET .../opening-hours reste la source la plus simple.
MCP
Dans Cursor ou Claude : endpoint organizationSettings_listOpeningHours (catégorie organizationSettings), arguments organizationId, date ou from/to en option, languageIsoCode en option.
Voir aussi
- API HTTP - authentification et en-têtes
- Exemples HTTP - exemples cURL généraux
- Webhooks -
organizationSettings:updatedpour la revalidation du cache - Paramètres de l'organisation - configurer les heures d'ouverture dans Tillor