Act on what Margin computes
Follow the discussion for what you actually hold
- Connects
- MarginDiscussion forum
- Writes
- Changes notification levels on forum threads
- Updated
- 17 September 2026 · 4 min read
Subscribing to a stock’s discussion thread takes a minute, and keeping those subscriptions current is what slips. You buy something in March, mean to subscribe to its thread, and find out in November that the last four quarters of discussion happened without you, while you still get notifications for a company you sold two years ago.
Margin holds the list of what you own, and a forum with an API holds the list of threads you follow. Keeping the second in step with the first is a small, repeatable job.
What the agent reads
GET /web/holdings
GET /web/stocksList
GET /web/stocksList/{id}
Holdings covers the main case, and a list you keep for positions held elsewhere, in a family account or an old broker, belongs in the same sweep. GET /web/stocksList returns every list with its id and name, so the skill can match the list you named rather than asking you for a number.
Three of the entries that endpoint returns are not lists you made. All, Holdings and NotCurrentlyHeld carry autoGenerated: true and no id, because they are views derived from the account and not stored membership. Over the API they are counts only. A skill that guesses an id for one of them gets a 404 that reads like a missing list.
Keep the map
Resolving a symbol to a thread is the slow part, because forum search is rate limited and many symbols have no dedicated thread at all, so a skill that searches from scratch every run spends most of its time rediscovering what it already knew.
A checked-in thread-map.json mapping symbol to thread id fixes this, and it should record the negative results too. A symbol known to have no thread needs to be stored as such, otherwise it gets re-searched on every run forever. Treat the file as durable state and not as a scratch file, and write back whenever a run resolves something new.
Rate limits and verbs
Forum APIs tend to limit reads and writes separately and tightly, and a 429 usually carries the wait in its body. Parsing that number and backing off by it works better than retrying on a fixed interval.
Discourse, which is what many investing forums run on, sets notification level with a POST to the topic’s notifications path and not a PUT. A PUT answers with a 404 HTML page, which looks like a missing topic and sends you after the wrong bug. Subscription list endpoints also lag behind writes, so confirm a change by reading the topic itself instead of re-reading the list.
A skill to start from
---
name: forum-watch-sync
description: Take the stocks in Margin's holdings and the lists the user names,
and make sure each one's discussion thread on the forum is set to notify. Use
when asked to sync, check or fix which threads are being followed.
allowed-tools: Bash(bash *), Bash(jq *), Bash(curl *), AskUserQuestion, Read, Write, Edit
---
Pull every stock the user counts as held from Margin and make sure its forum
thread is set to notify, fixing the ones that are not.
Read `https://go.marginapp.in/llms.txt` before building any Margin request.
## 1. Read what the user holds
GET /web/holdings
GET /web/stocksList
Holdings is the main source. Ask whether any named list should be included too.
`All`, `Holdings` and `NotCurrentlyHeld` in the stocks list response carry
`autoGenerated: true` and no id. They are counts only. Do not invent an id for
them and do not report one as an empty list.
## 2. Resolve symbols against the map
`thread-map.json` next to this file maps symbol to thread id, and records the
symbols known to have no thread. **Read it before searching.** Search only for
symbols it does not answer, and write back every symbol this run resolves,
including the ones confirmed to have no thread.
The map is durable state and is checked in. Do not treat it as a cache to clear.
## 3. Check each thread's current level
Read the topic itself and not the subscription list. The list endpoint lags
behind writes and will show a change that has not happened, or miss one that has.
## 4. Show what would change and wait
List the threads to subscribe and the threads to drop, with the stock each one
belongs to. Get the user's go-ahead before any write, the same as for a Margin
write.
## 5. Apply, respecting the limits
Reads and writes are limited separately and tightly. A 429 carries the wait in
its body: parse it and back off by that amount instead of retrying on a fixed
interval.
On Discourse, setting a level is POST to the topic's notifications path. PUT
answers with a 404 HTML page that reads like a missing topic.
## 6. Verify
Re-read each topic that changed and confirm the level took.
Also under act on what margin computes
Try it
You need a token to start
Create one in Margin under Settings, on the API Tokens tab. Tokens never expire and you can revoke any of them at any time.
Create an API token