API de horário de funcionamento
Obter o horário de funcionamento resolvido e os próximos feriados para um site
Última atualização em
Utilize a API de horário de funcionamento resolvido quando mostrar num site público horários sazonais (por exemplo Zomer / Winter) ou os próximos feriados. O Tillor já aplica exceções, períodos sazonais e o horário semanal normal, e acrescenta os feriados legais no intervalo pedido. Não precisa de voltar a implementar isso.
Permissão: organization:settings:read ou organization:settings:write
A chave de API fica do lado do servidor
Chame o Tillor apenas a partir de um servidor (Next.js Route Handler, Server Component ou backend). Guarde a chave em variáveis de ambiente. Nunca a envie para o navegador.
Autenticação: consulte a API HTTP. Experimente o endpoint na referência da API ou através do OpenAPI (etiqueta organization-settings).
Endpoint
GET https://tillor.eu/api/orgs/org_abc123/organization-settings/opening-hoursCabeçalhos:
x-api-key: tkn_xxxSubstitua org_abc123 pelo ID da sua organização.
Parâmetros de consulta
Utilize ou date, ou from/to. Não os combine.
| Parâmetro | Significado |
|---|---|
| (nenhum) | Hoje, no fuso horário da organização |
date | Um único dia de calendário (YYYY-MM-DD) |
from | Dia inicial (inclusive). Sem to: apenas esse dia |
to | Dia final (inclusive). Requer from. No máximo 366 dias |
languageIsoCode | Idioma dos nomes dos feriados (NL, FR, …). Por defeito: o idioma da organização |
Resposta
Cada item é um dia de calendário, já resolvido:
| Campo | Significado |
|---|---|
timeZone | Fuso horário IANA da organização |
from / to | Intervalo pedido |
holidays | Feriados legais que se sobrepõem a from–to |
items[].date | Dia de calendário YYYY-MM-DD |
items[].weekday | monday … sunday |
items[].source | exception, period ou regular |
items[].periodLabel | Apenas com source: "period": a etiqueta do Tillor, por exemplo "Zomer" ou "Winter" |
items[].holiday | Apenas se esse dia for um feriado legal: { id, name, startDate, endDate } |
items[].blocks | Intervalos de tempo em minutos desde a meia-noite |
items[].closed | true se blocks estiver vazio |
Prioridade: exceção (feriado ou intervalo personalizado) → último período sazonal correspondente → horário semanal normal.
As etiquetas sazonais vêm de Definições > Horário de funcionamento. Os períodos podem atravessar a viragem do ano (por exemplo de 1 de novembro a 31 de março). Os dias fora de qualquer período recorrem ao horário semanal normal (source: "regular", sem periodLabel).
Minutos para hora do relógio
startMinutes / endMinutes são minutos desde as 00:00.
| Minutos | Hora |
|---|---|
| 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")}`;
}Exemplos
Dia num período sazonal
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, horário de verão.
Dia fora dos períodos sazonais
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 e 13:00–17:00.
Intervalo que atravessa o limite de um período
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 |
Próximos feriados
Os feriados legais vêm na mesma resposta: holidays para uma lista (nome + datas), items[].holiday se esse dia de calendário for um feriado. As horas continuam a ser o horário resolvido; um feriado sem exceção preenchida no Tillor segue o horário sazonal ou semanal (source não é então "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
}
]
}O exemplo de items acima está encurtado; a resposta real contém todos os dias do intervalo. As férias escolares não estão neste endpoint; essas continuam em GET /holidays?kind=school.
Next.js (servidor)
Para um widget semanal ou “aberto agora” num site público:
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 é a lista para um bloco de “próximos feriados”. items[].holiday é útil num calendário semanal. items[].periodLabel é o texto sazonal (por exemplo "Zomer" ou "Winter"). Uma cache de 1 hora costuma bastar.
Invalidar a cache (webhook)
A cada alteração das definições da organização, o Tillor envia organizationSettings:updated (webhook e SSE). Subscreva esse evento e volte a obter o horário de funcionamento. O payload é propositadamente pequeno (sem IPs de impressoras nem o horário completo):
{
"event": "organizationSettings:updated",
"data": {
"openingHoursChanged": true
},
"timestamp": 1787829600000
}openingHoursChanged é true se o horário de funcionamento, o fuso horário ou o país predefinido mudarem - é isso que afeta GET .../opening-hours. Com false, pode manter a cache do horário de funcionamento.
Exemplo de Route Handler do 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 });
}Criar um webhook: consulte Webhooks. Chave do evento: organizationSettings:updated (permissão organization:settings:read ou organization:settings:write).
Horário completo (opcional)
Só é necessário se quiser mostrar o próprio calendário sazonal (etiquetas + fromMonth/untilDay), sem resolver dia a dia:
GET https://tillor.eu/api/orgs/org_abc123/organization-settingsLeia openingHoursSchedule.periods (etiquetas como "Zomer") e openingHoursSchedule.weekdays (horário normal). Para o próprio site, GET .../opening-hours continua a ser a fonte mais simples.
MCP
No Cursor ou no Claude: endpoint organizationSettings_listOpeningHours (categoria organizationSettings), argumentos organizationId, opcionalmente date ou from/to, opcionalmente languageIsoCode.
Relacionado
- API HTTP - autenticação e cabeçalhos
- Exemplos HTTP - exemplos gerais de cURL
- Webhooks -
organizationSettings:updatedpara revalidação da cache - Definições da organização - definir o horário de funcionamento no Tillor