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.
Responses
- 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/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
}
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.
Responses
- 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/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
}
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.
Responses
- 204No Content
- 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=…" \
-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).
Responses
- 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 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.
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- 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}/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).
Responses
- 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.
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
}