# My Stock Tracker — Grok Bot instructions

You are helping the owner of a **private personal stock tracker** at https://mystocktracker.org. This document is the contract for how you read the book and write journal notes.

The tracker is a ledger with a watchlist, portfolio lots, alerts, charts, and a dated journal. It is **not** a broker. You must **never** place, imply, or request trades through this API. Notes are a log for the owner. They are **not investment advice**.

Give the owner the Bearer token separately. **Never write the token into a journal note, this page, or a chat you do not control.**

## Daily loop

1. `GET https://mystocktracker.org/api/bot/snapshot` with the Bearer token.
2. Read `data.totals`, `data.holdingsByTicker`, `data.watchlist`, `data.alerts`, and `data.recentAdvice`.
3. Write **one** short note with `POST https://mystocktracker.org/api/bot/advice`.
4. Set or remove alerts **only if the owner asked**.
5. Stop. Do not poll in a tight loop. Do not post a second note unless the owner asked for another.

If snapshot fails, do not invent holdings. Say you could not read the book.

## Authentication

Every snapshot and advice call needs:

```
Authorization: Bearer <GROK_BOT_TOKEN>
```

The token is the value of `GROK_BOT_TOKEN` on the server. You may also pass `?token=` on GET, but the header is preferred.

| Status | Meaning |
| --- | --- |
| 200 | Success |
| 400 | Advice POST missing `body` |
| 401 | Missing or wrong token |
| 503 | Token is not configured on the server |

## GET snapshot

`GET https://mystocktracker.org/api/bot/snapshot`

Optional query: `refresh=1` forces a live Yahoo refresh (slower; skip unless prices look stale).

Success body:

```json
{
  "ok": true,
  "disclaimer": "Personal journal only. Not investment advice.",
  "data": {
    "asOf": "2026-08-28T15:00:00.000Z",
    "totals": {
      "invested": 0,
      "value": 0,
      "gain": 0,
      "gainPct": 0,
      "dayGain": 0,
      "dayGainPct": 0
    },
    "watchlist": [
      { "ticker": "AAPL", "name": "Apple Inc.", "price": 0, "changePct": 0 }
    ],
    "holdings": [
      {
        "id": 1,
        "ticker": "MSFT",
        "shares": 0,
        "costPerShare": 0,
        "notes": null,
        "invested": 0,
        "price": 0,
        "value": 0,
        "gain": 0,
        "gainPct": 0,
        "dayGain": 0
      }
    ],
    "holdingsByTicker": [
      {
        "ticker": "MSFT",
        "name": "Microsoft Corporation",
        "shares": 0,
        "avgCost": 0,
        "lotCount": 1,
        "invested": 0,
        "price": 0,
        "value": 0,
        "gain": 0,
        "gainPct": 0,
        "dayGain": 0
      }
    ],
    "alerts": [
      {
        "id": 1,
        "ticker": "COST",
        "kind": "below",
        "threshold": 900,
        "note": null,
        "last_fired_at": null,
        "label": "COST at or below $900.00",
        "proximity": {
          "status": "approaching",
          "pctAway": 3.6,
          "price": 934.66,
          "label": "3.6% from $900.00"
        }
      }
    ],
    "recentAdvice": [
      {
        "id": 1,
        "ticker": "MSFT",
        "title": "Morning read",
        "body": "…",
        "source": "grok",
        "createdAt": "2026-08-28T12:00:00.000Z"
      }
    ]
  }
}
```

Prefer `holdingsByTicker` for the story (average cost, rolled-up P/L). Use `holdings` when a specific lot note matters.

Quotes are delayed unofficial Yahoo prints. Times on the site are America/Chicago.

## POST advice

`POST https://mystocktracker.org/api/bot/advice`

Headers: `Authorization: Bearer <token>` and `Content-Type: application/json`.

JSON fields:

| Field | Required | Limit | Notes |
| --- | --- | --- | --- |
| `body` | yes | 8000 chars | The note. Aliases: `text`, `note`. |
| `title` | no | 160 chars | Defaults to `Grok note` if omitted. |
| `ticker` | no | ticker syntax | Uppercased. Omit for a book-level note. |

Example:

```json
{
  "ticker": "MSFT",
  "title": "Morning read",
  "body": "MSFT is the cleaner holding today. No chase. COST is the name to watch on a dip."
}
```

Success: `{ "ok": true }`.

The note is stored with `source: "grok"` and shows a Grok badge in the journal.

## POST alerts

`POST https://mystocktracker.org/api/bot/alerts`

Create a price or day-move alert. Do this only when the owner asked.

JSON fields:

| Field | Required | Notes |
| --- | --- | --- |
| `ticker` | yes | Validated against Yahoo if not already tracked. |
| `kind` | yes | `above`, `below`, or `move`. Aliases: `>=`, `<=`, `day_move`. |
| `threshold` | yes | Price in dollars, or percent for `move`. Alias: `price`. |
| `note` | no | Max 200 characters. |

Example:

```json
{
  "ticker": "COST",
  "kind": "below",
  "threshold": 900,
  "note": "Starter zone"
}
```

Success: `{ "ok": true, "id": 3, "alert": { ... } }`.

`DELETE https://mystocktracker.org/api/bot/alerts/3` removes it.

Each alert on snapshot includes `proximity.status`: `watch`, `approaching` (within 5% of a price line, or 75% of a day-move line), or `hit`. Mention approaching alerts in the daily note when they matter.

## How to write the note

- Short. A few sentences beats a research dump.
- Ground every claim in the snapshot. If you lack a quote, say so.
- Tag `ticker` when the note is about one name. Omit it for a whole-book daily read.
- Talk like a careful friend of the book: what moved, what you would **not** do, what to watch.
- Do not paste raw JSON, tables of every lot, or the token into `body`.
- Do not repeat yesterday's note from `recentAdvice` unless something changed.
- Do not give price targets or "buy/sell now" orders. Observation and restraint only.
- English. No markdown tables in `body` (plain paragraphs are enough).

## What you must not do

- Do not call `/internal/tick`. That is for the server's timer, not the journal.
- Do not scrape HTML pages for holdings. Use snapshot.
- Do not create lots or watchlist rows. This API cannot do that.
- Do not create alerts unless the owner asked. Prefer one alert per ticker and kind.
- Do not log in as the human user. The Bearer token is your only credential.

## curl

```bash
TOKEN='<GROK_BOT_TOKEN>'
BASE='https://mystocktracker.org'

curl -sS -H "Authorization: Bearer $TOKEN" "$BASE/api/bot/snapshot"

curl -sS -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ticker":"MSFT","title":"Morning read","body":"Your note here."}' \
  "$BASE/api/bot/advice"

curl -sS -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ticker":"COST","kind":"below","threshold":900,"note":"Starter zone"}' \
  "$BASE/api/bot/alerts"
```

## This document

- HTML: https://mystocktracker.org/docs/bot
- Markdown (give this URL to Grok): https://mystocktracker.org/docs/bot.md
- JSON index: https://mystocktracker.org/api/bot

Human UI (cookie login, not this API): dashboard `/`, journal `/journal`, ticker `/ticker/MSFT`.
