Set location special hours
Replace a location's upcoming special dates — holidays, early closes, full-day closures. The list you send replaces all special dates from today forward; past dates are untouched. Propagates to every storefront at the location, asynchronously — including those of an organization that has set its own weekly hours at this kitchen: a closure closes them like every other storefront, and a date that opens the kitchen opens each one only within the hours fetchStoreHours reports as its regular.
The LOCATION tier is the only special-hours tier this API models. OneTablet also carries brand-at-location overrides internally, and a storefront's effective special dates are the union of the two with the more-closed schedule winning on a shared date — but that tier has no operation here, in either direction, so nothing on this contract reads or writes it. If it is ever published it arrives as a matched read and write pair, announced in the changelog.
dates is required and must be non-empty UNLESS wipeAll: true, which deliberately clears every upcoming special date instead. See SetLocationSpecialHoursRequest.
Scope: owner-only, which is narrower than the reads. Only a locationId your organization OWNS — one whose Location.organizationId from fetchLocations equals your own organization id. If you operate a brand out of somebody else's host kitchen, fetchLocations shows you that kitchen and fetchStoreHours reports its special dates, but you may NOT write them: a location-hours write is not brand-scoped, it moves the schedule for every brand trading there, including the host's. Ask the host to make the change.
A locationId that is not yours — whether another organization's outright or a host kitchen you merely operate in — is INDISTINGUISHABLE from one that does not exist at all. All of them are the same 404 {"message":"Not Found"}, and never a write. The body is deliberately bare: anything that told the cases apart would let you enumerate locations you cannot see. The rule above is the explanation the body does not carry, so check organizationId on the location from fetchLocations against your own organization id before you write.
Safe to retry: this operation changes state but is idempotent.
Request
- locationIdstring
The
Locationto write special hours for. Required. - datesSpecialDate[]
The desired COMPLETE set of special hours for the location, replacing every upcoming date not present in it. Required and must be non-empty unless
wipeAll: true. See the request's own description. - wipeAllboolean
Deliberately clear every upcoming special date. Absent means the normal behavior (send
dates). See the request's own description.
{
"locationId": "00000000-0000-0000-0000-000000000000",
"dates": [
{
"date": "<date>",
"closed": true,
"opensAt": "<opensAt>",
"closesAt": "<closesAt>"
}
],
"wipeAll": true
}Responses
Headers
- x-mealco-tx-idstringoptional
The correlation id for this call, echoed on every response — a 200 exactly as much as a 400, 401 or 500. Quote it when reporting a problem and we can find every log line for the request, in every service it touched. You may also send your own x-mealco-tx-id on the request and we adopt it, so your correlation id becomes ours. Not marked required for one reason: a request whose JSON body is malformed is rejected before it reaches an operation, so no id exists yet and that single response carries neither this header nor the txId field of the error body. Everything that reaches an operation carries it.
- datesSpecialDate[]
The location's special dates as persisted after this call.
About Stores
The places you operate and the brands you operate there.
OneTablet models a restaurant business in three layers, and every other section of this API assumes them. A brand is a menu concept — what a customer sees on a delivery app. A location is a physical address with a kitchen in it. A store is one storefront: a single brand, at a single location, on a single platform — so a location running two brands on three platforms has six stores, each with its own menu, hours and pause state.
The directory reads join on IDS, never on display names: every store carries its location.id and brand.id, and a location carries the id of each brand it runs.
Start here — a location carries the timezone that every schedule, report window and business day elsewhere on this API is interpreted in.
Every operation is org-scoped to the organization your api key resolves to, and nothing here calls out to a delivery platform live. The directory reads (fetchLocations, fetchBrands, fetchStores, fetchStore, fetchStoreHours, fetchStoreMenus) never mutate; setLocationHours and setLocationSpecialHours write a location you own.
Whether a storefront is currently taking orders is NOT here — fetchStoreStatuses, pauseStores, unpauseStores and the store.status.changed webhook live in the Store status section. This section answers "what do I operate"; that one answers "is it open right now, and does the platform agree".