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.
Share

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