Conversations
Every resource you can read carries a threads/ folder: topics, nested comments, reactions, and a resolved state that collapses a finished thread.
AI-assisted, human-approvednovem uses AI to review and keep our documentation up to date.
Overview
A conversation is a topic (the thread's first message) with comments
nested under it. Threads live in the threads/ folder of the resource they
discuss, for example /v1/users/:user/vis/plots/:plot/threads for a plot, or
/v1/users/:user/code/repos/:repo/threads for a repo. Topics and comments are
addressed as @author~slug:
threads
└── @sam~axis-labels => a topic started by sam
├── msg => the topic's text
├── audience => public | private
├── status => active | archived
├── reaction => your like / dislike
├── resolved => whether the thread is resolved
└── comments
└── @lee~fixed => a reply by lee
├── msg
├── reaction
└── comments => replies to the reply
Anyone who can read the resource can read its public threads. A private
topic is visible only to its author and the resource's owner.
Note: creating, editing or deleting topics, comments and reactions, and
resolving threads, requires a paid subscription (basic and up). Reading is
available on all plans. The owner can turn comments off with
config/options/comments.
Topics and comments
| Verb | Path | Description |
|---|---|---|
GET | threads | List the topics you can see |
PUT | threads/:slug | Start a topic as yourself. The body is plain text, or JSON {"message": "…", "audience": "public"} |
GET / DELETE | threads/@author~slug | List a topic's leaves, or delete it (its author or the resource's owner) |
GET / POST | threads/@author~slug/msg | Read or edit the text (the author) |
GET / POST / DELETE | threads/@author~slug/reaction | Your reaction: like or dislike |
PUT | threads/@author~slug/comments/:slug | Reply to the topic. Nest further with …/comments/@author~slug/comments/:slug |
Messages are capped at 10,000 characters, and replies nest at most eight deep.
Resolving a thread
Resolving marks a thread as done. It hides nothing: the web app collapses a resolved thread to one line saying who resolved it, when, and how many comments it holds, and anyone who can read the thread can expand it again.
| Verb | Path | Description |
|---|---|---|
GET | threads/@author~slug/resolved | The thread's resolved state |
POST | threads/@author~slug/resolved | Resolve the thread |
DELETE | threads/@author~slug/resolved | Reopen the thread |
curl -X POST -H "Authorization: Bearer $NOVEM_TOKEN" \
https://api.novem.io/v1/users/sam/vis/plots/sales/threads/@lee~axis-labels/resolved
{
"resolved": true,
"resolved_at": "Wed, 07 Oct 2026 12:00:00 UTC",
"resolved_by": "sam"
}
The rules:
- Who can resolve: anyone with write access to the resource the thread is
attached to, the owner included. The thread's author gets no extra right, and
read-only collaborators cannot resolve or reopen. A caller who can read the
thread but not write the resource gets
403. A caller who cannot see the thread gets404, as for any thread they cannot read. - One state per thread. It sits on the topic, and everyone who can read the thread sees the same state. Replies cannot be resolved separately.
- Resolving again keeps the original resolver and time. Reopening clears both.
- The resolver is named only to readers who can see that account. Others
get
resolved_by: nullwith the rest of the state. - Replies are still allowed on a resolved thread and do not reopen it.
- No notifications are sent when a thread is resolved or reopened.
In GraphQL, the same state is on Topic: resolved_at, resolved_by (a
User, or null) and can_resolve, which tells the caller whether they may
change it.