Calendar feeds

Subscribe to the week from a calendar app.10 operations

Headers on every response

Every response on this page carries these headers.
X-Trace-Id
— The W3C trace id of this request — the same id in the log and in the traceId of a problem. Quote it when reporting.
Server-Timing
— Where the time went: total, db;dur=…;desc="N queries", and every step the handler named (ADR-163).
X-Diagnostics
— Only when the request asked with X-Diagnostics: 1 or ?diagnostics=1: the same breakdown as one JSON object, with the trace id (ADR-163).

Operations

GET/api/v1/households/{householdId}/calendar-events

List upcoming events from every feed, one slice per feed

Any member, a Junior included (#553). from defaults to today and to to from + 14 days; the window is clamped to 31 days. A feed that cannot be read comes back with a fixed error on its own slice — one broken calendar never hides the others (#979). busyEvenings names, per day, the event that touches that day's dinner hour — the planner's rule, so the week marks the day busy for the same reason (#3379).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
fromquerystring (date)——
toquerystring (date)——

Responses

200OK
application/jsonUpcomingCalendarEventsResponse
400The request could not be read as the route needs it: a body that is not the documented shape (a required field left out, a null where none is allowed, a value too long for its field), a parameter that does not parse, or a NUL character anywhere (#3540, #3541, #3543). Code validation_failed or value_too_long.
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-events"

Example response

200application/json
{
  "feeds": [
    {
      "feedId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "feedName": "string",
      "events": [
        {}
      ],
      "error": "string"
    }
  ],
  "from": "2026-09-07",
  "to": "2026-09-07",
  "busyEvenings": [
    {
      "date": "2026-09-07",
      "title": "string",
      "startTime": "string",
      "endTime": "string"
    }
  ]
}
GET/api/v1/calendar/{token}.icsNo session needed

Fetch the planned dinners as an iCalendar feed from a private link

Public: a calendar app fetches it with no account (#3394); the token in the path is the proof. Each dinner cooked at home from 14 days back to 42 ahead is one event from when to start cooking until it is served, titled with the dish, with a UID stable per household and date. A token Bryti did not mint, or one the household has replaced or turned off, answers 404 without saying which. Rate-limited per IP.

Parameters

NameInTypeRequiredDescription
tokenpathstringRequired—

Responses

200OK
404Not Found
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl \
  "https://bryti.app/api/v1/calendar/string.ics"
GET/api/v1/households/{householdId}/calendar-feeds

List the household's calendar feeds

Both kinds: Ics (a shared address the server fetches) and Device (a phone's own calendar the app pushes, #222). Pass deviceKey to have the row this very phone pushed marked isThisDevice — only that phone can act on «Oppdater nå» (#1186); the web app sends none. An ICS address is masked to scheme and host (https://host/…/•••) for every caller — it is a bearer key to the whole calendar, and only the answer to the create request carries it whole (#3581). isMine marks the device feeds the caller's own login pushed (ADR-087).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
deviceKeyquerystring——

Responses

200OK
application/jsonCalendarFeedResponse[]
400The request could not be read as the route needs it: a body that is not the documented shape (a required field left out, a null where none is allowed, a value too long for its field), a parameter that does not parse, or a NUL character anywhere (#3540, #3541, #3543). Code validation_failed or value_too_long.
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-feeds"

Example response

200application/json
[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "string",
    "url": "string",
    "createdAt": "2026-09-07T16:30:00Z",
    "kind": "Ics",
    "isThisDevice": false,
    "isMine": false
  }
]
POST/api/v1/households/{householdId}/calendar-feeds

Subscribe the household to an ICS calendar address

Adults only; a Junior member gets 403. The server fetches the address later, so it passes the same guard as recipe-URL import — http(s), standard ports, no loopback/private/link-local — and is refused with 400 otherwise (#979).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—

Request body

application/jsonRequiredCreateCalendarFeedRequest

Responses

201Created
application/jsonCalendarFeedResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  -X POST \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-feeds" \
  -H "Content-Type: application/json" \
  -d '{"name":"string","url":"string"}'

Example response

201application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "url": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "kind": "Ics",
  "isThisDevice": false,
  "isMine": false
}
DELETE/api/v1/households/{householdId}/calendar-feeds/{feedId}

Remove a calendar feed

Adults only; a Junior member gets 403. A device calendar is its owner's alone (ADR-087): another member removing it by id gets 403 (#3581).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
feedIdpathstring (uuid)Required—

Responses

204No Content
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
403Forbidden
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  -X DELETE \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-feeds/3fa85f64-5717-4562-b3fc-2c963f66afa6"
PUT/api/v1/households/{householdId}/calendar-feeds/device

Push this phone's own calendar events, replacing the last sync

Any member (US-510), but bound to the caller: the feed is keyed by the caller's login and deviceKey, created on the first sync and replaced whole on every one after — another member's key never matches, so nobody overwrites anyone else's (#1056, ADR-087). Only events from yesterday to 31 days ahead are kept, at most 500.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—

Request body

application/jsonRequiredSyncDeviceCalendarRequest

Responses

200OK
application/jsonCalendarFeedResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  -X PUT \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-feeds/device" \
  -H "Content-Type: application/json" \
  -d '{"deviceKey":"string","name":"string","events":[{"title":"string","date":"2026-09-07","startTime":"string","endTime":"string","isAllDay":false,"location":"string"}]}'

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "url": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "kind": "Ics",
  "isThisDevice": false,
  "isMine": false
}
DELETE/api/v1/households/{householdId}/calendar-feeds/device/{deviceKey}

Remove this phone's calendar feed

Only the caller's own: another member's device key answers 404 rather than deleting theirs (ADR-087).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
deviceKeypathstringRequired—

Responses

204No Content
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
426The build named in X-App-Version is below its platform's version floor (ADR-070). Problem type app-version-unsupported; the only way forward is the store. Callers without the header are never turned away.
application/problem+jsonProblemDetails
429Too many calls in the window; Retry-After says how long.
application/problem+jsonProblemDetails
Headers
Retry-After
— Seconds to wait when a rate limit answered, or an HTTP date when the household's AI is paused. Absent when the household's AI quota for the period is used up — that resets by itself.

Example

curl -b "bryti_session=…" \
  -X DELETE \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/calendar-feeds/device/string"

Schemas

BusyEveningResponse

PropertyTypeRequired
datestring (date)Required
titlestringRequired
startTimestring | nullRequired
endTimestring | nullRequired

CalendarEventResponse

PropertyTypeRequired
titlestringRequired
datestring (date)Required
startTimestring | nullRequired
endTimestring | nullRequired
isAllDaybooleanRequired
locationstring | nullRequired

CalendarFeedEventsResponse

PropertyTypeRequired
feedIdstring (uuid)Required
feedNamestringRequired
eventsCalendarEventResponse[]Required
errorstring | nullRequired

CalendarFeedResponse

PropertyTypeRequired
idstring (uuid)Required
namestringRequired
urlstringRequired
createdAtstring (date-time)Required
kindstring—
syncedAtstring (date-time) | null—
eventCountinteger (int32) | null—
isThisDeviceboolean—
isMineboolean—

CreateCalendarFeedRequest

PropertyTypeRequired
namestringRequired
urlstringRequired

DeviceCalendarEvent

PropertyTypeRequired
titlestringRequired
datestring (date)Required
startTimestring | nullRequired
endTimestring | nullRequired
isAllDaybooleanRequired
locationstring | nullRequired

DinnerCalendarLinkResponse

PropertyTypeRequired
urlstring | nullRequired
webcalUrlstring | nullRequired

ProblemDetails

PropertyTypeRequired
typestring | null—
titlestring | null—
statusinteger (int32) | null—
detailstring | null—
instancestring | null—
codestring | null—

SyncDeviceCalendarRequest

PropertyTypeRequired
deviceKeystringRequired
namestringRequired
eventsDeviceCalendarEvent[]Required

UpcomingCalendarEventsResponse

PropertyTypeRequired
feedsCalendarFeedEventsResponse[]Required
fromstring (date)Required
tostring (date)Required
busyEveningsBusyEveningResponse[]Required