User History APIs
Save every question a signed-in reader asks, let them reopen past conversations, and notify them when Miso has a fresher answer.
Records are created for you
You do not write history. When a signed-in user asks a question through
POST /v1/ask/questions, Miso records it in the background. Only the first
question of a conversation becomes a history row (a thread); follow-ups attach
to that thread and move it to the top of the list. Questions from anonymous
users are never saved.
Pass log_user_history: false on POST /v1/ask/questions to keep one question
out of history — useful for a per-question "private mode" toggle.
Authentication
Every endpoint needs your API key and an authenticated user:
- Secret key (server side) — pass
user_idin the body; it is trusted. -
Publishable key (browser) — must carry a signed JWT in
Authorization: Bearer <token>or ajwt_tokenbody field. Sign it with HS256 using your app's secret key; itsuser_id(orsub) claim is the authenticated user.
If user_id appears in both the JWT and the body, the two must match or the
request returns 401.
Answer Updates
A reader can subscribe to a thread. Miso watches that topic and, when it finds important new content, appends a fresh follow-up answer and raises an unread indicator. Miso judges significance before appending, so no update means no indicator.
Two levels are reported, both derived at read time by comparing the last update with the last dismissal:
-
Account level — does this user have any unseen update?
Poll
POST /v1/ask/user_history/thread/updates. -
Thread level — does this thread have one? The
has_newfield on the history list.
Typical front-end flow
-
Poll
.../thread/updatesfor the account indicator, and call/v1/ask/user_historyfor the sidebar. -
Open a thread with
.../thread, fetch every answer in one call with/v1/ask/answers, then clear it with.../dismiss_thread. - Offer
.../subscribeon threads the reader cares about.
Examples
The examples below build one sidebar: list conversations, open one, then offer updates. Each request needs your API key plus an authenticated user (see Authentication above).
Example 1 — Render the sidebar (simplest)
POST /v1/ask/user_history
{ "user_id": "alice", "rows": 20 }
{
"message": "success",
"data": [
{
"id": "3xK7mN",
"time": "2026-06-12T10:15:00Z",
"question_id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4…",
"question": "How do interest rate cuts affect mor…",
"subscribed": true,
"has_new": true
}
]
}
Render question as the row label. Show the thread-level unread indicator when
has_new is true.
Example 2 — Open a thread in two calls
Get the conversation's questions in order:
POST /v1/ask/user_history/thread
{
"question_id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"user_id": "alice"
}
{
"message": "success",
"data": {
"question_ids": [
"0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
],
"has_more": false
}
}
Then fetch every answer in one call:
POST /v1/ask/answers
{
"question_ids": [
"0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
]
}
data is aligned with your input, and an id you cannot see comes back as
null. Use this instead of one poll per question — it is one round trip rather
than many.
To page a long thread, pass the last question_id as after and repeat while
has_more is true. Pass "order": "desc" for a newest-first view.
Example 3 — Let the reader manage the list
POST /v1/ask/user_history/thread/rename
{
"question_id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"user_id": "alice",
"title": "Mortgage research"
}
Delete selected rows with the opaque id values from Example 1 — not the
question_id:
POST /v1/ask/user_history/delete
{ "ids": ["3xK7mN", "9pQ2rS"], "user_id": "alice" }
Example 4 — Offer Answer Updates
Subscribe the thread the reader cares about:
POST /v1/ask/user_history/thread/updates/subscribe
{
"user_id": "alice",
"thread_id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b"
}
Poll the account-level indicator, for example every 60 seconds:
POST /v1/ask/user_history/thread/updates
{ "user_id": "alice" }
{ "message": "success", "data": { "has_new": true } }
When it turns true, refresh the sidebar. The row whose has_new is true
holds the new answer. Reopen that thread to read it.
Example 5 — Clear the indicators correctly
The two calls do different jobs:
POST /v1/ask/user_history/thread/updates/dismiss_thread
{
"user_id": "alice",
"thread_id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b"
}
Call this when the reader opens a thread. It clears that thread, and clears the account level too if no other thread is waiting.
POST /v1/ask/user_history/thread/updates/dismiss_overall
{ "user_id": "alice" }
Call this when the reader dismisses the notification without opening anything. Every thread keeps its own indicator, so nothing is lost.
Example 6 — Do it all from the browser
A publishable key must carry a JWT. Sign it on your server with your secret key
(HS256) and put user_id in the claims. Then send it with every call:
POST /v1/ask/user_history
Authorization: Bearer <signed-jwt>
{ "rows": 20 }
Omit user_id from the body — it comes from the token. If you send both, they
must match, or the request returns 401.
- post/v1/ask/user_history/thread
- post/v1/ask/answers
- post/v1/ask/user_history/thread/rename
- post/v1/ask/user_history/delete
- post/v1/ask/user_history/delete_all
- post/v1/ask/user_history/thread/updates
- post/v1/ask/user_history/thread/updates/subscribe
- post/v1/ask/user_history/thread/updates/unsubscribe
- post/v1/ask/user_history/thread/updates/dismiss_thread
- post/v1/ask/user_history/thread/updates/dismiss_overall
- post/v1/ask/user_history/thread/updates/touch
- post/v1/ask/user_history/list
