---
title: "Catch up on the events ledger: the cold-start brief, or a delta since a cursor"
method: GET
path: "/api/catch-up"
tags: ["Events"]
---

# Catch up on the events ledger: the cold-start brief, or a delta since a cursor

`GET /api/catch-up`

## Request

- Base URL: `https://tre-app.com`
- URL: `https://tre-app.com/api/catch-up`
- Auth: HTTP bearer

Same contract as MCP's `catch_up` (`catchUpQuerySchema` in lib/schemas/events.ts validates both). Without `cursor`: the brief — the NON-ARCHIVED boards you can read (each with its id) with their lists (with their ids) and card counts, a tail of recent activity (`recent` is a taste of the ledger, not a page — no `hasMore` — and, unlike the inventory, it does include archived boards), per workspace the care counts `stale`, `inventory` and `attention` (`BriefWorkspace` says what each counts), and a fresh `cursor`. With `cursor`: `{ events, cursor, hasMore, resynced? }`, only what happened since. Activity on boards you cannot read is filtered out after the scan, so a page may carry fewer events than `limit` — even none — while `hasMore` is true: keep calling with the returned cursor until `hasMore` is false. Keep the cursor verbatim between sessions, like a cardKey; never parse it. `limit` (1-100, default 50) is ignored without a cursor and split evenly across the workspaces in scope (floor, minimum one each — with more workspaces than `limit`, a page can carry one event per workspace and exceed it). A position retention has pruned past is restarted from the oldest event that workspace still has and reported in `resynced` (the delta's optional array of slugs) — not an error, and the other workspaces' deltas in the same response are unaffected. Only a cursor that is damaged or names a position this ledger never issued answers 410 `STALE_CURSOR`: call again without one to restart from the brief.

## Query parameters

- `workspace` string
- `cursor` string
- `limit` integer

## Response `200`

Success

- union
  - CatchUpBrief
    - `workspaces` object[], required
      - `workspace` string, required
      - `boards` object[], required
        - `id` string, uuid, required: Board id — what listCards wants.
        - `board` string, required: Board slug.
        - `key` string, required: cardKey prefix.
        - `name` string, required
        - `lists` object[], required
          - `id` string, uuid, required: List id — what createCard wants.
          - `name` string, required
          - `cards` integer, required
      - `stale` integer, required: Cards on the non-archived boards you can read that the lint reports as stale_status: open cards (not closed — actualEndDate null and scheduleState not cancelled) whose dated STATUS/UPDATED is more than 14 days old (W3-D2). Since 2026-10-15 exactly the lint view's own count (before, it counted closed cards too). Those updated within the last 30 days are in attention, the others in inventory.
      - `inventory` integer, required: OPEN cards on the non-archived boards you can read carrying at least one lint finding that attention does not count, and none it does (since 2026-10-15): the audit a session is not being asked to do now — a stale line on a card nobody touched for 30 days, a legacy card without a STATUS, a bare orphan. Disjoint from attention.count; the lint view per board lists them.
      - `attention` object, required
        - `count` integer, required: Cards on the non-archived boards you can read carrying at least one ACTIONABLE lint finding (W3-D5, calibrated 2026-09-05 and 2026-10-15): unresolved_reference, oversize_description, duplicate_status, overdue, stale_verification (the last two since 2026-09-26) and status_log (since 2026-10-15) at any age; stale_status only when the card was updated within the last 30 days; missing_status only when it was updated within the last 14 days. orphan never counts; a closed card (actualEndDate set, or scheduleState cancelled) is never stale_status, missing_status, overdue, stale_verification or status_log; the lint view remains the full audit, and `inventory` counts the open cards it names that attention does not. A card on an archived board counts towards none of the three (since 2026-10-15; before, every readable board counted).
        - `sample` string[], required: At most five cardKeys with actionable findings, most recently updated first.
      - `guidance` object
        - `cardKey` string, required
        - `excerpt` string, required: The oldest non-archived kind: guidance card's description, first 280 characters (W3-D7). Absent from BriefWorkspace when the workspace has none.
    - `recent` object[], required
      - `seq` integer, required: Strictly increasing per workspace.
      - `at` string, date-time, required
      - `workspace` string, required: Workspace slug.
      - `verb` string, required: A catalogued verb, e.g. `card.created`.
      - `board` string, required: Board slug.
      - `card` string: Card cardKey, when this verb names one.
      - `by` object, required: Who did it. `user` is null for a deleted account or a member who never set a display name — never fall back to an email here.
        - `user` string, nullable, required
        - `via` string, required
        - `token` string
        - `agent` object: Present when the ledger recorded a token id. The agent name is snapshotted at write time; user remains the delegating human. Historical name-only events have no agent. OAuth tokens also carry `client` (the CIMD URL).
          - `profile` 'ai_agent', required
          - `tokenId` string, uuid, required
          - `name` string, required
          - `kind` 'personal' | 'oauth', required
          - `client` string: CIMD URL when kind is oauth and the token row still names a client.
    - `cursor` string, required
  - CatchUpDelta
    - `events` object[], required
      - `seq` integer, required: Strictly increasing per workspace.
      - `at` string, date-time, required
      - `workspace` string, required: Workspace slug.
      - `verb` string, required: A catalogued verb, e.g. `card.created`.
      - `board` string, required: Board slug.
      - `card` string: Card cardKey, when this verb names one.
      - `by` object, required: Who did it. `user` is null for a deleted account or a member who never set a display name — never fall back to an email here.
        - `user` string, nullable, required
        - `via` string, required
        - `token` string
        - `agent` object: Present when the ledger recorded a token id. The agent name is snapshotted at write time; user remains the delegating human. Historical name-only events have no agent. OAuth tokens also carry `client` (the CIMD URL).
          - `profile` 'ai_agent', required
          - `tokenId` string, uuid, required
          - `name` string, required
          - `kind` 'personal' | 'oauth', required
          - `client` string: CIMD URL when kind is oauth and the token row still names a client.
    - `cursor` string, required
    - `hasMore` boolean, required: True when unfiltered rows remain beyond this scan. Events on boards the caller cannot read are filtered out AFTER the scan, so a page can carry fewer events than `limit` — even zero — while this is true.
    - `resynced` string[]: Workspace slugs, sorted, whose cursor position had fallen off the ledger (retention) and was restarted from the oldest event still retained. The events between are unrecoverable; every other workspace in this same response is unaffected, so keep using the returned cursor rather than restarting from the brief. Absent — not an empty array — when no workspace was resynced.

## Other responses

- `400`: Invalid request
- `401`: Unauthenticated
- `403`: Forbidden: insufficient role or token scope; scope denials name the held scope and the operation
- `404`: Not found
- `409`: Conflict
- `410`: Cursor damaged or forged; call again without one
- `429`: Rate limited
- `500`: Internal server error
- `503`: Temporarily unavailable

---

[API](https://skmtc.dev/tre-app/apis/tre-rest-api.md) · [All operations](https://skmtc.dev/tre-app/apis/tre-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tre-app/apis/tre-rest-api/revisions/26a7187a05fc?raw)
