Answer Updates

News moves fast. A question from last week can have a better answer today. Answer Updates let a reader subscribe to a conversation. Miso watches that topic, appends a fresh follow-up answer when it finds important new content, and raises an indicator your interface can show.

This builds on User History — a thread has to exist before a reader can subscribe to it. Read that page first.

History is enabled per app. Miso records a question in history only for apps that have the feature switched on. On an app without it, POST /v1/ask/user_history returns an empty list, and subscribe answers 404 "Thread not found" — the thread it looks for was never recorded. Ask your Miso representative to enable it before you build against these endpoints.

News moves fast. A question from last week can have a better answer today. Answer Updates let a reader subscribe to a conversation. Miso then watches that topic. When Miso finds important new content, it appends a fresh follow-up answer to the thread and raises a notification.

Two levels of unread indicator

Miso reports two booleans. Most interfaces render them as a dot or a badge, but the API only tells you whether an unseen update exists.

Indicator Question it answers How you read it
Account level Does this user have any unseen update? Poll POST /v1/ask/user_history/thread/updates
Thread level Does this thread have an unseen update? The has_new field on the history list

Miso calculates both values at read time. It compares the time of the last update with the time the user last dismissed that level. Miso does not store a separate flag.

Every endpoint, and what it returns

Each call takes user_id, and the per-thread calls also take thread_id (the root question of the thread). These are the exact bodies, from a live run:

Endpoint Body Response
…/thread/updates user_id {"message": "success", "data": {"has_new": false}}
…/thread/updates/subscribe user_id, thread_id {"message": "success"}, or 404 {"message": "Thread not found"}
…/thread/updates/unsubscribe user_id, thread_id {"message": "success"}. Idempotent.
…/thread/updates/dismiss_thread user_id, thread_id {"message": "success"}. Idempotent.
…/thread/updates/dismiss_overall user_id {"message": "success"}
…/thread/updates/touch user_id, thread_id {"message": "success", "data": {"touched": 0}}

Only two calls return a data object. The poll returns has_new, and touch returns touchedthe number of subscriptions it stamped. touched: 0 means no live subscription matches, so nothing lights up. Use it to check your test setup before you blame the front end.

With generate: true, touch also writes the update, and names it:

{
  "message": "success",
  "data": {
    "generated": true,
    "question_id": "c925d60f-bf71-47b7-992e-9c732f2a34d3",
    "touched": 1
  }
}

That question_id is a new turn at the end of the thread. Read it with the single-answer endpoint, the same way you read any other turn.

Every one of these requires user_id. Without it you get 400 {"message": "user_id is required"}.

Subscribe a thread

POST /v1/ask/user_history/thread/updates/subscribe

Field Type Notes
user_id string The subscriber.
thread_id UUID The thread's root question id.

This call is idempotent. If the user does not own the thread, Miso returns 404.

Unsubscribe

Subscribe answers 404 "Thread not found" when that thread_id is not a thread of that user_id. Two causes, in this order: history is not enabled for the app, or the user_id does not match the one that asked the question.

POST /v1/ask/user_history/thread/updates/unsubscribe uses the same body (user_id, thread_id). This call is idempotent.

Poll the account-level indicator

POST /v1/ask/user_history/thread/updates takes the body user_id. Your UI polls this endpoint to show or clear the account-level indicator, for example every 60 seconds.

{
  "data": {
    "has_new": true
  }
}

Dismiss

Endpoint Body Effect
…/thread/updates/dismiss_thread user_id, thread_id Clears one thread. If no other thread has an unseen update, the account-level indicator clears too.
…/thread/updates/dismiss_overall user_id Clears the account-level indicator only. Each thread keeps its own.

How each value is decided:

thread has_new = an update arrived after you last dismissed that thread
account has_new = some subscribed, visible thread has an unseen update
                  that is newer than your last "dismiss all"

If the user dismisses every thread, the account-level indicator clears on its own. dismiss_overall clears only the account level. Each thread keeps its own indicator for the user to review.

How updates are generated

  • Miso monitors subscribed threads periodically, not on every request. By default, a thread produces at most one generated update per day.
  • Miso counts only content published after the thread's last activity as an update. Older articles can appear only as clearly-labeled background.
  • Miso judges the importance of the content before it appends. If nothing important is new, Miso creates no update and no indicator.
  • Generation is asynchronous. The new follow-up answer streams like any other answer. To read it, reopen the thread or fetch the new question_id.
  • Miso titles the follow-up like "Latest developments since July 7, 2026 regarding: <thread title>".

What a generated update looks like

Miso writes the question for the reader, from the thread's title. A subscribed thread titled "Rocky Linux" produces a turn like this:

{
  "question": "Latest developments since July 31, 2026 regarding: Rocky Linux",
  "metadata": {
    "miso_generated_by": "answer_update_monitor"
  },
  "answer": "There are no new updates on Rocky Linux in the knowledge base since July 31, 2026. This topic will continue to be monitored for any future developments."
}

Two things follow. Renaming a thread changes the wording of its later updates, because the title is the subject. And an update is written even when there is nothing new, so the reader can see that the topic was checked. Show the indicator, and let them read the turn.

Telling a generated update from a reader's question

A generated update is appended to the thread as an ordinary follow-up, so parent_question_id does not separate the two — both have one.

Miso marks every generated update instead. Read the answer and check metadata:

{
  "data": {
    "question_id": "7c8d9e0f-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
    "question": "Latest developments since July 7, 2026 regarding: …",
    "answer": "…",
    "metadata": {
      "miso_generated_by": "answer_update_monitor"
    }
  }
}

A question the reader typed carries no such key.

const isGeneratedUpdate = (answer) =>
  answer.metadata?.miso_generated_by === "answer_update_monitor";

The key appears on both routes that create an update: the automatic monitor, and touch with generate: true. It reaches you through the single-answer poll and through the bulk /v1/ask/answers endpoint.

This is an origin hint, not a security boundary. metadata is client-writable, so a caller can send the same key on a typed question. That misleads only that caller's own interface, and it grants no extra access. Do not use it to gate anything.

Trigger an update on demand (advanced, server-side)

POST /v1/ask/user_history/thread/updates/touch

This endpoint is optional. It marks a thread's subscriptions as updated now. Use it for server-side integrations and end-to-end tests.

Field Type Notes
thread_id UUID The thread to mark as updated.
user_id string Optional (secret key). Narrows the change to one subscriber.
generate boolean If true, also appends a generated follow-up answer.
  • Secret key: marks every live subscription of the thread. The user_id field narrows the change to one subscriber.
  • Publishable key: limited to the caller's own subscription. You can light set the indicator only for yourself.
  • The API key determines the app_id. As a result, a key can mark only the threads of its own app.
{
  "data": {
    "generated": true,
    "question_id": "…",
    "touched": 1
  }
}

CAUTION: touch appends and stamps without any check. If the thread has no new content, generate: true produces a sourceless "no new updates" card. The automatic monitor judges the content first and never does this. Use subscriptions for the real user experience. Use touch only for tests or explicit server-side triggers.


Putting it together

  1. On load — poll …/thread/updates for the account-level indicator, and read each thread's has_new from the history list.
  2. Open a thread — fetch it, then call …/dismiss_thread to clear that thread's indicator.
  3. Offer updates — call …/subscribe on the threads a reader cares about, and keep polling for fresh answers.
  4. Tell the two apart — check metadata.miso_generated_by before you render a turn as the reader's own question.