Chat

Bryti in the chat: conversations, turns and proposed actions.14 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}/conversations

List the household's conversations, newest activity first

One page at a time (ADR-292, #3002): cursor and limit in, items/nextCursor out, 50 rows by default and 100 at most. Home writes a thread a day, so a household that stays a year has 365 of them. total is null — nobody counts the threads above a switcher. Threads without messages never list: the apps create threads lazily on the first send, so an empty one is an abandoned draft, hidden at once and deleted after a day. Opening the list also makes sure the deterministic «update the pantry?» nudge thread exists.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
cursorquerystring——
limitqueryinteger (int32)——

Responses

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=…" \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/conversations"

Example response

200application/json
{
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "title": "string",
      "createdAt": "2026-09-07T16:30:00Z",
      "lastMessageAt": "2026-09-07T16:30:00Z",
      "lastMessagePreview": "string"
    }
  ],
  "nextCursor": "string",
  "total": 0
}
POST/api/v1/households/{householdId}/conversations

Start a new conversation with Bryti

The body is optional: an empty POST starts an untitled thread, which is named after its first message. The starter is recorded so a data export carries only that person's own conversations (#984, ADR-084).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—

Request body

application/jsonOptionalCreateConversationRequest | null

Responses

201Created
application/jsonConversationResponse
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
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/conversations" \
  -H "Content-Type: application/json" \
  -d '{"title":"string"}'

Example response

201application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "householdId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "title": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "messages": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "role": {},
      "content": "string",
      "toolActivity": [
        {}
      ],
      "widgets": [
        {}
      ],
      "createdAt": "2026-09-07T16:30:00Z",
      "failed": false,
      "stopped": false
    }
  ],
  "proposals": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "actionType": "string",
      "payload": {},
      "humanSummary": "string",
      "status": {},
      "requiresConfirmation": false,
      "error": "string",
      "createdAt": "2026-09-07T16:30:00Z",
      "appliedAt": "2026-09-07T16:30:00Z",
      "undoable": false
    }
  ],
  "hasEarlier": false
}
GET/api/v1/households/{householdId}/conversations/{conversationId}

Read a window of a conversation's newest messages

Always a window (ADR-292, #3002, #2965): the newest 40 messages when no limit is named, 200 at most, and nextCursor says where the older page starts — hand it back as ?cursor= to read it. hasEarlier is the same fact as a non-null nextCursor. before is the old spelling of the same question, a timestamp instead of a cursor; it still answers, and disappears once the app version floor has been raised past the builds that ask with it. Proposals are those of the messages in the window plus any still open, however old their message is.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—
limitqueryinteger (int32)——
cursorquerystring——
beforequerystring (date-time)——

Responses

200OK
application/jsonConversationResponse
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=…" \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6"

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "householdId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "title": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "messages": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "role": {},
      "content": "string",
      "toolActivity": [
        {}
      ],
      "widgets": [
        {}
      ],
      "createdAt": "2026-09-07T16:30:00Z",
      "failed": false,
      "stopped": false
    }
  ],
  "proposals": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "actionType": "string",
      "payload": {},
      "humanSummary": "string",
      "status": {},
      "requiresConfirmation": false,
      "error": "string",
      "createdAt": "2026-09-07T16:30:00Z",
      "appliedAt": "2026-09-07T16:30:00Z",
      "undoable": false
    }
  ],
  "hasEarlier": false
}
DELETE/api/v1/households/{householdId}/conversations/{conversationId}

Delete a conversation and everything in it

Messages and proposals go with it.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—

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/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6"
POST/api/v1/households/{householdId}/conversations/{conversationId}/report

Report a reply from Bryti as offensive or wrong

Any member may press it, a Junior included (#349). The body is optional: a bare POST reports the thread, messageId narrows it to one reply, and reason plus a note of at most 500 characters say why (ADR-145). Safe to retry: a second report of the same message leaves one row and still answers 204. 400 when the note is too long.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—

Request body

application/jsonOptionalReportChatContentRequest | null

Responses

204No Content
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/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6/report" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/api/v1/households/{householdId}/conversations/{conversationId}/messages

Send a message to Bryti and wait for the whole reply

The non-streaming twin of the stream route, kept for clients without SSE support: same body, same rules, and costs credits like any turn. continuation asks Bryti to carry on after «Accept all» (#23); replacesMessageId edits the household's last own message, deleting everything after it (ADR-145). Send an Idempotency-Key header to make a retry safe.409 chat.edit_not_last / chat.edit_applied when the thread no longer allows that edit — reload the thread instead of retrying; 409 duplicate_ai_request when the Idempotency-Key was already accepted — refresh instead of retrying. 429 quota_exceeded when the household's monthly AI allowance is spent, or ai_paused when the platform's cost guard has paused AI this month (ADR-023, Retry-After set).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—
Idempotency-Keyheaderstring——

Request body

application/jsonRequiredSendChatMessageRequest

Responses

200OK
application/jsonSendChatMessageResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
409Conflict
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 Requests
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/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6/messages" \
  -H "Content-Type: application/json" \
  -d '{"content":"string","continuation":false}'

Example response

200application/json
{
  "userMessage": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "role": {},
    "content": "string",
    "toolActivity": [
      {}
    ],
    "widgets": [
      {}
    ],
    "createdAt": "2026-09-07T16:30:00Z",
    "failed": false,
    "stopped": false
  },
  "assistantMessage": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "role": {},
    "content": "string",
    "toolActivity": [
      {}
    ],
    "widgets": [
      {}
    ],
    "createdAt": "2026-09-07T16:30:00Z",
    "failed": false,
    "stopped": false
  },
  "proposals": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "actionType": "string",
      "payload": {},
      "humanSummary": "string",
      "status": {},
      "requiresConfirmation": false,
      "error": "string",
      "createdAt": "2026-09-07T16:30:00Z",
      "appliedAt": "2026-09-07T16:30:00Z",
      "undoable": false
    }
  ]
}
POST/api/v1/households/{householdId}/conversations/{conversationId}/messages/stream

Send a message to Bryti and stream the reply (SSE)

Same body and rules as the non-streaming route; costs credits. The response is text/event-stream: a ping first (and every 10 s of silence), then started with the aiRequestId the stop route needs, then any number of text_delta, tool_started, tool_completed, proposal and widget events. The stream ends with exactly one of completed (both messages and the turn's proposals), stopped (the household pressed Stop; whatever was reached is kept and nothing is charged, #1681) or error. When the turn failed part-way, error is followed by completed with a failed message.Closing the socket does not cancel the turn: it finishes in the background, the reply is persisted, and a push tells the phone (#200). 409 and 429 mean the same as on the non-streaming route and arrive as a plain problem before any event, never mid-stream.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—
Idempotency-Keyheaderstring——

Request body

application/jsonRequiredSendChatMessageRequest

Responses

200OK
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
404Not Found
application/problem+jsonProblemDetails
409Conflict
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 Requests
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/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6/messages/stream" \
  -H "Content-Type: application/json" \
  -d '{"content":"string","continuation":false}'
POST/api/v1/households/{householdId}/conversations/{conversationId}/turns/{aiRequestId}/stop

Stop the reply Bryti is writing right now

aiRequestId is what the stream's started event named (#1681). Answers only once the turn has unwound and persisted what it reached, so the thread can be refetched the moment this returns. stopped: false means the turn was already over — not an error. A stopped turn is not charged. 404 when the turn is not this household's.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
conversationIdpathstring (uuid)Required—
aiRequestIdpathstring (uuid)Required—

Responses

200OK
application/jsonStopChatTurnResponse
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/conversations/3fa85f64-5717-4562-b3fc-2c963f66afa6/turns/3fa85f64-5717-4562-b3fc-2c963f66afa6/stop"

Example response

200application/json
{
  "stopped": false
}
GET/api/v1/households/{householdId}/chat-permission-mode

Read how eagerly Bryti applies proposed changes without asking

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—

Responses

200OK
application/jsonChatPermissionModeResponse
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=…" \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/chat-permission-mode"

Example response

200application/json
{
  "permissionMode": "AlwaysAsk"
}
PUT/api/v1/households/{householdId}/chat-permission-mode

Set how eagerly Bryti applies proposed changes without asking

Adults only; a Junior member gets 403. AlwaysAsk, AutoApplyLowRisk or AutoApplyAll; every write still records a proposal whatever the mode.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—

Request body

application/jsonRequiredUpdateChatPermissionModeRequest

Responses

200OK
application/jsonChatPermissionModeResponse
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/chat-permission-mode" \
  -H "Content-Type: application/json" \
  -d '{"permissionMode":"AlwaysAsk"}'

Example response

200application/json
{
  "permissionMode": "AlwaysAsk"
}
POST/api/v1/households/{householdId}/action-proposals/{proposalId}/apply

Apply a change Bryti proposed

Adults only; a Junior member gets 403 — a Junior may ask for anything in chat, but an adult applies it. A card that changes the household's own settings or language is the owner's, as PATCH households/{id} is: anyone else gets 403 with code owner_required and nothing changes (ADR-415 (#3423)). Runs the same handler the ordinary forms use, in one transaction: either the whole change lands, or the card comes back 200 with status Failed and its error and nothing changed. A proposal that plans the week puts the run in the planning queue and comes back Running with its jobId (GET plans/runs/{jobId} says how it goes); the card turns Applied, with its outcome, when the run lands, or Failed (ADR-337 (#3184)). It costs credits. 409 with code consent_required when the card would store an allergy, an intolerance, a diet tied to a condition or breastfeeding and the subject's explicit yes is not on file (GDPR art. 9(2)(a), #3077): the card stays pending, so it works once the yes is given. 409 without a code when another press took the card in the same moment: the change ran once, for that press (#3586).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
proposalIdpathstring (uuid)Required—

Responses

200OK
application/jsonActionProposalResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
409Conflict
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.

Problem codes

The `code` in the problem body is what to branch on. `detail` is English, written for a log.

consent_required
— Bryti needs an explicit yes before it can save health details. You give that yes on the person's card under Household.

Example

curl -b "bryti_session=…" \
  -X POST \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/action-proposals/3fa85f64-5717-4562-b3fc-2c963f66afa6/apply"

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "actionType": "string",
  "payload": {},
  "humanSummary": "string",
  "status": "Proposed",
  "requiresConfirmation": false,
  "error": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "appliedAt": "2026-09-07T16:30:00Z",
  "undoable": false
}
POST/api/v1/households/{householdId}/action-proposals/{proposalId}/undo

Take back an applied change

Adults only; a Junior member gets 403. Only within 24 hours of applying, and only when the change has an inverse (undoable on the card) — 400 otherwise (#63). 409 when another press took the change back in the same moment (#3586).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
proposalIdpathstring (uuid)Required—

Responses

200OK
application/jsonActionProposalResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
409Conflict
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/action-proposals/3fa85f64-5717-4562-b3fc-2c963f66afa6/undo"

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "actionType": "string",
  "payload": {},
  "humanSummary": "string",
  "status": "Proposed",
  "requiresConfirmation": false,
  "error": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "appliedAt": "2026-09-07T16:30:00Z",
  "undoable": false
}
POST/api/v1/households/{householdId}/action-proposals/{proposalId}/redo

Do an undone change again

Adults only; a Junior member gets 403. Only an undone change can be redone (400 otherwise). The action re-runs from its stored payload, so a coherence failure — a duplicate member, a date already covered — also comes back as 400 and the card stays undone. 409 with code consent_required when the change would store health data the subject has not said yes to (#3077); 409 without a code when another press did it again in the same moment (#3586).

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
proposalIdpathstring (uuid)Required—

Responses

200OK
application/jsonActionProposalResponse
400Bad Request
application/problem+jsonProblemDetails
401No session, or the session is no longer valid.
application/problem+jsonProblemDetails
404Not Found
application/problem+jsonProblemDetails
409Conflict
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.

Problem codes

The `code` in the problem body is what to branch on. `detail` is English, written for a log.

consent_required
— Bryti needs an explicit yes before it can save health details. You give that yes on the person's card under Household.

Example

curl -b "bryti_session=…" \
  -X POST \
  "https://bryti.app/api/v1/households/3fa85f64-5717-4562-b3fc-2c963f66afa6/action-proposals/3fa85f64-5717-4562-b3fc-2c963f66afa6/redo"

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "actionType": "string",
  "payload": {},
  "humanSummary": "string",
  "status": "Proposed",
  "requiresConfirmation": false,
  "error": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "appliedAt": "2026-09-07T16:30:00Z",
  "undoable": false
}
POST/api/v1/households/{householdId}/action-proposals/{proposalId}/reject

Reject a change Bryti proposed

Adults only; a Junior member gets 403.

Parameters

NameInTypeRequiredDescription
householdIdpathstring (uuid)Required—
proposalIdpathstring (uuid)Required—

Responses

200OK
application/jsonActionProposalResponse
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/action-proposals/3fa85f64-5717-4562-b3fc-2c963f66afa6/reject"

Example response

200application/json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "conversationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sourceMessageId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "actionType": "string",
  "payload": {},
  "humanSummary": "string",
  "status": "Proposed",
  "requiresConfirmation": false,
  "error": "string",
  "createdAt": "2026-09-07T16:30:00Z",
  "appliedAt": "2026-09-07T16:30:00Z",
  "undoable": false
}

Schemas

ActionProposalResponse

PropertyTypeRequired
idstring (uuid)Required
conversationIdstring (uuid)Required
sourceMessageIdstring (uuid)Required
actionTypestringRequired
payloadChatActionRequired
humanSummarystringRequired
statusProposalStatusRequired
requiresConfirmationbooleanRequired
errorstring | nullRequired
createdAtstring (date-time)Required
appliedAtstring (date-time) | nullRequired
undoableboolean—
undoneAtstring (date-time) | null—
undoExpiresAtstring (date-time) | null—
jobIdstring (uuid) | null—
spanPlanProposalSpan | null—
outcomePlanProposalOutcome | null—
askedAfterReadingChatForeignTextSource | null—

ChatAction

Type

One of

Told apart by type

ChatActionActivatePlanAction

PropertyTypeRequired
type"ActivatePlan"—
weekStartstring (date)Required

ChatActionAdaptDinnerIngredientAction

PropertyTypeRequired
type"AdaptDinnerIngredient"—
datestring (date)Required
useFoodstringRequired
insteadOfFoodstringRequired

ChatActionAddDietaryConstraintAction

PropertyTypeRequired
type"AddDietaryConstraint"—
memberNamestring | nullRequired
kindDietaryConstraintKindRequired
foodOrCategorystringRequired
severityConstraintSeverityRequired
notesstring | nullRequired

ChatActionAddFoodPreferenceAction

PropertyTypeRequired
type"AddFoodPreference"—
memberNamestring | nullRequired
subjectTypePreferenceSubjectTypeRequired
subjectstringRequired
sentimentPreferenceSentimentRequired

ChatActionAddGuestsForDateAction

PropertyTypeRequired
type"AddGuestsForDate"—
datestring (date)Required
adultCountinteger (int32)Required
childCountinteger (int32)Required
notesstring | nullRequired
endDatestring (date) | null—
guestNamesstring[] | null—
babyCountinteger (int32)—

ChatActionAddHouseholdMemberAction

PropertyTypeRequired
type"AddHouseholdMember"—
namestringRequired
birthDatestring (date)Required
defaultDinnerParticipantbooleanRequired
isBreastfedboolean | null—
isGuestboolean | null—
portionFactornumber (double) | null—

ChatActionAddInventoryObservationAction

PropertyTypeRequired
type"AddInventoryObservation"—
foodKeystringRequired
displayNamestringRequired
observationTypeObservationTypeRequired
quantitynumber (double) | nullRequired
unitstring | nullRequired
storageLocationStorageLocationRequired

ChatActionAddShoppingItemAction

PropertyTypeRequired
type"AddShoppingItem"—
weekStartstring (date)Required
displayNamestringRequired
quantitynumber (double) | null—
unitstring | null—

ChatActionBuildShoppingListAction

PropertyTypeRequired
type"BuildShoppingList"—
weekStartstring (date)Required

ChatActionCheckShoppingItemAction

PropertyTypeRequired
type"CheckShoppingItem"—
weekStartstring (date)Required
itemNamestringRequired
purchasedbooleanRequired

ChatActionDeleteDietaryConstraintAction

PropertyTypeRequired
type"DeleteDietaryConstraint"—
foodOrCategorystringRequired
memberNamestring | null—

ChatActionDeleteFoodPreferenceAction

PropertyTypeRequired
type"DeleteFoodPreference"—
subjectstringRequired
memberNamestring | null—

ChatActionDeleteMealEventAction

PropertyTypeRequired
type"DeleteMealEvent"—
datestring (date)Required
eventTypeMealEventType | null—

ChatActionDeleteMealRuleAction

PropertyTypeRequired
type"DeleteMealRule"—
kindMealRuleKindRequired
categoryMealCategory | null—
datestring (date) | null—

ChatActionDeleteRecipeAction

PropertyTypeRequired
type"DeleteRecipe"—
titlestringRequired

ChatActionEditRecipeAction

PropertyTypeRequired
type"EditRecipe"—
recipeTitlestringRequired
newTitlestring | null—
categoryMealCategory | null—
ingredientsRecipeIngredientDto[] | null—
stepsstring[] | null—
tagsstring[] | null—
activeMinutesinteger (int32) | null—
totalMinutesinteger (int32) | null—
portionsinteger (int32) | null—

ChatActionImportRecipeFromUrlAction

PropertyTypeRequired
type"ImportRecipeFromUrl"—
urlstringRequired

ChatActionMarkAwayAction

PropertyTypeRequired
type"MarkAway"—
datestring (date)Required
endDatestring (date) | null—
notesstring | null—

ChatActionMarkEatingOutAction

PropertyTypeRequired
type"MarkEatingOut"—
datestring (date)Required
notesstring | nullRequired
endDatestring (date) | null—

ChatActionMarkMemberAbsentAction

PropertyTypeRequired
type"MarkMemberAbsent"—
memberNamestringRequired
datestring (date)Required

ChatActionMergePantryFoodsAction

PropertyTypeRequired
type"MergePantryFoods"—
fromFoodKeystringRequired
toFoodKeystringRequired

ChatActionPlanWeekAction

PropertyTypeRequired
type"PlanWeek"—
weekStartstring (date)Required
policyPlanPolicy | null—

ChatActionRecordOutcomeAction

PropertyTypeRequired
type"RecordOutcome"—
datestring (date)Required
statusOutcomeStatusRequired
reasonOutcomeReason | null—
notesstring | null—

ChatActionReplaceDinnerAction

PropertyTypeRequired
type"ReplaceDinner"—
datestring (date)Required
dishTitlestringRequired

ChatActionReplanOpenDaysAction

PropertyTypeRequired
type"ReplanOpenDays"—
weekStartstring (date)Required
policyPlanPolicy | null—

ChatActionSaveRecipeAction

PropertyTypeRequired
type"SaveRecipe"—
titlestringRequired
categoryMealCategoryRequired
ingredientsRecipeIngredientDto[]Required
stepsstring[]Required
tagsstring[]Required
activeMinutesinteger (int32)Required
totalMinutesinteger (int32)Required
portionsinteger (int32)Required

ChatActionSelectStoresAction

PropertyTypeRequired
type"SelectStores"—
storeNamesstring[]Required
addressstring | null—

ChatActionSetCategoryForDateAction

PropertyTypeRequired
type"SetCategoryForDate"—
datestring (date)Required
categoryMealCategoryRequired
strengthRuleStrength | null—

ChatActionSetDinnerLockAction

PropertyTypeRequired
type"SetDinnerLock"—
datestring (date)Required
lockedbooleanRequired

ChatActionSetDinnerTimeAction

PropertyTypeRequired
type"SetDinnerTime"—
timestringRequired
datestring (date) | null—
weekdaysWeekday[] | null—

ChatActionSetHouseholdLanguageAction

PropertyTypeRequired
type"SetHouseholdLanguage"—
languageCodestringRequired

ChatActionSetMaximumCookingTimeForDateAction

PropertyTypeRequired
type"SetMaximumCookingTimeForDate"—
datestring (date)Required
minutesinteger (int32)Required
strengthRuleStrength | null—

ChatActionSetRecipeFavoriteAction

PropertyTypeRequired
type"SetRecipeFavorite"—
recipeTitlestringRequired
favoritebooleanRequired
memberNamestring | null—

ChatActionUpdateHouseholdMemberAction

PropertyTypeRequired
type"UpdateHouseholdMember"—
memberNamestringRequired
newNamestring | nullRequired
birthDatestring (date) | nullRequired
defaultDinnerParticipantboolean | nullRequired
isActiveboolean | nullRequired
isBreastfedboolean | null—
isGuestboolean | null—
portionFactornumber (double) | null—

ChatActionUpdateHouseholdSettingsAction

PropertyTypeRequired
type"UpdateHouseholdSettings"—
namestring | null—
timeZoneIdstring | null—
defaultDinnerTimestring | null—
addressstring | null—
prefersLeftoverDinnersboolean | null—
tailorServingToTastesboolean | null—
showSoftServingAdviceboolean | null—
maxNewDishesPerWeekinteger (int32) | null—
alwaysNewDishesboolean | null—
babyEatsSeparatelyWhenNeededboolean | null—
pantryWeightstring | null—

ChatActionUpsertCategoryExcludedDaysRuleAction

PropertyTypeRequired
type"UpsertCategoryExcludedDaysRule"—
categoryMealCategoryRequired
excludedWeekdaysWeekday[]Required
strengthRuleStrength | null—

ChatActionUpsertCategoryFrequencyRuleAction

PropertyTypeRequired
type"UpsertCategoryFrequencyRule"—
categoryMealCategoryRequired
minimumPerWeekinteger (int32)Required
maximumPerWeekinteger (int32)Required
strengthRuleStrength | null—

ChatActionUpsertCategoryOnDayRuleAction

PropertyTypeRequired
type"UpsertCategoryOnDayRule"—
categoryMealCategoryRequired
weekdayWeekdayRequired
strengthRuleStrength | null—

ChatActionUpsertMaximumCookingTimeRuleAction

PropertyTypeRequired
type"UpsertMaximumCookingTimeRule"—
minutesinteger (int32)Required
weekdaysWeekday[] | null—
strengthRuleStrength | null—

ChatActionUpsertPriceClassRuleAction

PropertyTypeRequired
type"UpsertPriceClassRule"—
ceilingPriceCeilingRequired
weekdaysWeekday[] | null—
strengthRuleStrength | null—

ChatActionUpsertRepeatAfterDaysRuleAction

PropertyTypeRequired
type"UpsertRepeatAfterDaysRule"—
daysinteger (int32)Required
strengthRuleStrength | null—

ChatActionWishDishAction

PropertyTypeRequired
type"WishDish"—
titlestringRequired
memberNamestring | null—

ChatForeignTextSource

Type

Values

PantryRecipeCalendar

or null

ChatMessageResponse

PropertyTypeRequired
idstring (uuid)Required
roleChatRoleRequired
contentstringRequired
toolActivityChatToolActivityResponse[]Required
widgetsChatWidgetResponse[]Required
createdAtstring (date-time)Required
failedboolean—
stoppedboolean—
systemNoteChatSystemNote | null—

ChatPermissionMode

Type

Values

AlwaysAskAutoApplyLowRiskAutoApplyAll

ChatPermissionModeResponse

PropertyTypeRequired
permissionModeChatPermissionModeRequired

ChatReportReason

Type

Values

WrongOrDangerousBreaksHouseRulesInappropriateOther

or null

ChatRole

Type

Values

UserAssistantSystem

ChatSystemNote

Type

Values

ProposalsAcceptedLanguageChanged

or null

ChatToolActivityResponse

PropertyTypeRequired
toolNamestringRequired
summarystringRequired
isErrorbooleanRequired

ChatWidgetResponse

PropertyTypeRequired
typestringRequired
payloadJsonElementRequired

ConstraintSeverity

Type

Values

HardSoft

ConversationResponse

PropertyTypeRequired
idstring (uuid)Required
householdIdstring (uuid)Required
titlestring | nullRequired
createdAtstring (date-time)Required
messagesChatMessageResponse[]Required
proposalsActionProposalResponse[]Required
hasEarlierboolean—
nextCursorstring | null—

ConversationSummaryResponse

PropertyTypeRequired
idstring (uuid)Required
titlestring | nullRequired
createdAtstring (date-time)Required
lastMessageAtstring (date-time)Required
lastMessagePreviewstring | nullRequired

CreateConversationRequest

PropertyTypeRequired
titlestring | nullRequired

DietaryConstraintKind

Type

Values

AllergyIntoleranceDietaryPatternAvoidance

JsonElement

Type

anything

MealCategory

Type

Values

FishMeatPoultryVegetarianVeganSoupPastaTacoLeftoversOther

MealEventType

Type

Values

GuestsEatingOutPersonAbsentPersonPresentActivityCelebrationTravelCustom

MealRuleKind

Type

Values

CategoryFrequencyCategoryExcludedDaysCategoryOnDayMaximumActiveCookingTimeDinnerTimeOnWeekdayPriceClassOnDaysRepeatAfterDays

ObservationType

Type

Values

PurchasedConfirmedPresentEstimatedConsumedManuallyAdjustedFrozenDiscardedLeftoverCreatedConfirmedGone

OutcomeReason

Type

Values

UnexpectedEventMissingIngredientNotEnoughTimeTooTiredNotAppealingIllnessPlansChangedOtherDidNotLike

or null

OutcomeStatus

Type

Values

CookedCookedWithChangesNotCookedAteElsewhere

PagedConversationSummaryResponse

PropertyTypeRequired
itemsConversationSummaryResponse[]Required
nextCursorstring | nullRequired
totalinteger (int32) | nullRequired

PlanDeviationKind

Type

Values

BentSoftNearMissLeftOpenHandPicked

PlanDeviationOptionResponse

PropertyTypeRequired
codestringRequired
datestring (date) | null—
categorystring | null—
ruleIdstring (uuid) | null—

PlanDeviationResponse

PropertyTypeRequired
kindPlanDeviationKindRequired
rulePlanDeviationRuleRequired
ruleIdstring (uuid) | nullRequired
datestring (date) | nullRequired
categorystring | nullRequired
targetinteger (int32) | nullRequired
actualinteger (int32) | nullRequired
minutesinteger (int32) | nullRequired
reasonstringRequired
optionsPlanDeviationOptionResponse[]Required
ingredientstring | null—
memberNamestring | null—
constraintKindstring | null—
lockedByHouseholdboolean | null—
capSpentboolean | null—
priceCeilingPriceCeiling | null—

PlanDeviationRule

Type

Values

CategoryFrequencyMaximumActiveCookingTimeCalendarCapCategoryOnDayCategoryExcludedDaysHardConstraintBabySafePortionDietaryPreferencePriceClassOnDaysRepeatAfterDays

PlanEntryType

Type

Values

CookAtHomeEatingOutNoDinnerPlanLeftovers

PlanHeldDish

PropertyTypeRequired
datestring (date)Required
titlestringRequired

PlanPickedDish

PropertyTypeRequired
datestring (date)Required
candidateIdstring (uuid) | null—
recipeIdstring (uuid) | null—

PlanPolicy

PropertyTypeRequired
allowGenerationinteger (int32) | null—
allowNearMissesboolean—
categoryCapsRunCategoryCap[] | null—
reopenDatesstring (date)[] | null—
lockedDatesstring (date)[] | null—
excludedTitlesstring[] | null—
pickedDishesPlanPickedDish[] | null—
heldDishesPlanHeldDish[] | null—

PlanPreflightBlockedRule

PropertyTypeRequired
rulePlanDeviationRuleRequired
categorystring | null—
minutesinteger (int32) | null—
priceCeilingPriceCeiling | null—

PlanPreflightDay

PropertyTypeRequired
datestring (date)Required
statePlanPreflightDayStateRequired
titlestring | null—
categorystring | null—
bendPlanDeviationResponse | null—
reasonPlanPreflightReason | null—
keptboolean | null—
usesUpPlanPreflightUseUp[] | null—

PlanPreflightDayState

Type

Values

LibraryGenerateNearMissStaysOpenLockedAnsweredPastEatingOutLeftoversReplaced

PlanPreflightReason

PropertyTypeRequired
kindPlanPreflightReasonKindRequired
usedinteger (int32) | null—
capinteger (int32) | null—
proposalsinteger (int32) | null—
rulesPlanPreflightBlockedRule[] | null—

PlanPreflightReasonKind

Type

Values

CapReachedNoCandidateFitsRuleBlocked

PlanPreflightResponse

PropertyTypeRequired
daysPlanPreflightDay[]Required
nearMissOfferPlanDeviationResponse[]Required
generationCapinteger (int32)Required
householdCapinteger (int32)Required
alwaysNewDishesbooleanRequired
nextWeekOnlyboolean—

PlanPreflightUseUp

PropertyTypeRequired
foodKeystringRequired
displayNamestringRequired
bestBeforestring (date) | nullRequired

PlanProposalOutcome

PropertyTypeRequired
weekStartstring (date)Required
fromstring (date)Required
tostring (date)Required
daysPlanProposalOutcomeDay[]Required
ruleCategoriesMealCategory[]Required
fromStarterLibraryboolean—

PlanProposalOutcomeDay

PropertyTypeRequired
datestring (date)Required
entryTypePlanEntryTypeRequired
categoryMealCategory | nullRequired

PlanProposalReplaced

PropertyTypeRequired
datestring (date)Required
entryTypePlanEntryTypeRequired
titlestring | nullRequired

PlanProposalSpan

PropertyTypeRequired
weekStartstring (date)Required
fromstring (date)Required
tostring (date)Required
replacesPlanProposalReplaced[]Required
creditsinteger (int32) | null—
preflightPlanPreflightResponse | null—

PreferenceSentiment

Type

Values

LikeDislikeStrongDislike

PreferenceSubjectType

Type

Values

IngredientCategoryDishTexturePreparationTaste

PriceCeiling

Type

Values

CheapCheapOrMid

ProblemDetails

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

ProposalStatus

Type

Values

ProposedAppliedRejectedFailedRunning

RecipeIngredientDto

PropertyTypeRequired
foodKeystringRequired
displayNamestringRequired
quantitynumber (double)Required
unitstringRequired
isOptionalbooleanRequired
functionTagsstring[] | null—
displayQuantitynumber (double) | null—
displayUnitstring | null—
sectionstring | null—

ReportChatContentRequest

PropertyTypeRequired
messageIdstring (uuid) | null—
reasonChatReportReason | null—
notestring | null—

RuleStrength

Type

Values

HardSoft

RunCategoryCap

PropertyTypeRequired
categoryMealCategoryRequired
maxPerWeekinteger (int32)Required

SendChatMessageRequest

PropertyTypeRequired
contentstringRequired
continuationboolean—
replacesMessageIdstring (uuid) | null—

SendChatMessageResponse

PropertyTypeRequired
userMessageChatMessageResponseRequired
assistantMessageChatMessageResponseRequired
proposalsActionProposalResponse[]Required

StopChatTurnResponse

PropertyTypeRequired
stoppedbooleanRequired

StorageLocation

Type

Values

FridgeFreezerPantryUnknown

UpdateChatPermissionModeRequest

PropertyTypeRequired
permissionModeChatPermissionModeRequired

Weekday

Type

Values

SundayMondayTuesdayWednesdayThursdayFridaySaturday