Skip to Content
Exemplos

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-hours

Cabeçalhos:

x-api-key: tkn_xxx

Substitua org_abc123 pelo ID da sua organização.

Parâmetros de consulta

Utilize ou date, ou from/to. Não os combine.

ParâmetroSignificado
(nenhum)Hoje, no fuso horário da organização
dateUm único dia de calendário (YYYY-MM-DD)
fromDia inicial (inclusive). Sem to: apenas esse dia
toDia final (inclusive). Requer from. No máximo 366 dias
languageIsoCodeIdioma dos nomes dos feriados (NL, FR, …). Por defeito: o idioma da organização

Resposta

Cada item é um dia de calendário, já resolvido:

CampoSignificado
timeZoneFuso horário IANA da organização
from / toIntervalo pedido
holidaysFeriados legais que se sobrepõem a from–to
items[].dateDia de calendário YYYY-MM-DD
items[].weekdaymonday … sunday
items[].sourceexception, period ou regular
items[].periodLabelApenas com source: "period": a etiqueta do Tillor, por exemplo "Zomer" ou "Winter"
items[].holidayApenas se esse dia for um feriado legal: { id, name, startDate, endDate }
items[].blocksIntervalos de tempo em minutos desde a meia-noite
items[].closedtrue 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.

MinutosHora
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")}`;
}

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"
DatasourceperiodLabel
2026-03-30regular-
2026-03-31regular-
2026-04-01periodZomer
2026-04-02periodZomer

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-settings

Leia 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

Esta página foi útil?

Nesta página