Shared

Public holidays for this business's country and state

get/api/organization/holidays

Suggestions for the Special hours screen, proxied from date.nager.at and narrowed to the company's own country and state.

Read-only, and it writes nothing. It answers "which dates does your country and state observe"; what the business then does on those dates is a separate, deliberate POST /api/organization/special-hours. Keeping the two apart is what stops a third-party dataset from ever changing a tenant's availability on its own.

Regional filtering is not cosmetic. In 2026 the source returns Anzac Day twice, on 25 April for SA/TAS/VIC and 27 April for NSW/ACT/WA. Unfiltered, a Sydney venue is shown two Anzac Days and one of them is a day it is open. When the company's state cannot be resolved to an ISO 3166-2 code, everything is returned and regionUnknown says so, because hiding a holiday we could not verify is the worse failure of the two.

Only Public holidays are offered; the source also reports Bank, School, Optional, Observance and Authorities days, and a list that offers to close a salon for Groundhog Day is a list nobody trusts again.

Never 5xx on a source failure. A country the source does not cover, a missing country setting and an upstream outage all answer 200 with supported: false and a reason, because the Special hours screen works perfectly well without suggestions and rendering an error over a working feature teaches operators to distrust it. Cached for a week per country-year. Readable by any member.

Authorization

sessionCookie
sb-qxrvgfkjyvbngipqvslu-auth-token<token>

The dashboard's Supabase Auth session cookie, set at sign-in. Large sessions are split across numbered chunks (…auth-token.0, .1), so treat this as a cookie family rather than one name.

Every request re-validates it against the Auth server (getUser()), never by decoding the cookie locally: a JWT nothing has checked is not a credential. Tenancy is then read from the verified app_metadata.company_id claim and enforced by row-level security; it is never read from request input, on any route, ever.

role (admin / staff) is deliberately not in RLS. It gates specific actions in route code, the operations marked admin below, so hiding a button in the UI is cosmetic only, and a route's own check is the enforcement.

In: cookie

Query Parameters

year?integer

Defaults to the current year. Bounded to last year through three years ahead: the value is interpolated into a URL on a third-party host, so an unbounded one would make this an open proxy.

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/organization/holidays"
{  "supported": true,  "reason": "no_country",  "country": "string",  "state": "string",  "regionUnknown": true,  "year": 0,  "yearRange": {    "min": 0,    "max": 0  },  "holidays": [    {      "date": "2019-08-24",      "name": "string",      "englishName": "string",      "regional": true,      "regions": [        "string"      ]    }  ]}