---
title: "The current-flags feed (same payload as the get_signals MCP tool)"
method: GET
path: "/api/signals"
---

# The current-flags feed (same payload as the get_signals MCP tool)

`GET /api/signals`

## Request

- Base URL: `https://api.signalbureau.ai`
- URL: `https://api.signalbureau.ai/api/signals`
- Auth: none declared

Every currently flagged entity with trajectory, domains, desk membership, and an explicit evidenceStatus per signal ('receipted' rows carry source-attributed evidence URLs; 'unreceipted' rows report the attention measurement without article receipts — filter on evidenceStatus for fully attributable rows). Snapshot-backed: refreshes nightly; edge-cached 10 minutes (`cache-control: public, max-age=600`). No pagination — the feed is a bounded set (all currently flagged entities, `totalFlagged` in the envelope); `limit` truncates from the top of the ranking. Sorting is fixed: the platform's priority ranking, highest first.

Rate limits: 30 requests/minute burst per network address (shared egress shares the allowance) and 500/day anonymous, plus a global daily breaker — enforced on ORIGIN reads. Edge-cached responses (10-minute TTL) serve without consuming quota, so short read bursts against a warm cache may all return 200; quota protects origin compute, not cached reads. Every 429 carries a `retry-after` header (seconds); daily-quota 429s additionally carry `requiresAuth: true`.

## Query parameters

- `limit` integer
- `direction` 'rising' | 'fading' | 'steady' | 'new' | 'insufficient_history'

## Response `200`

The feed envelope.

- SignalsFeed
  - `ok` boolean, required
  - `schema` string, required: Envelope version tag, e.g. sb.signals.v1. Additive changes only within a version.
  - `asOf` string, nullable: Snapshot date (YYYY-MM-DD).
  - `generatedAt` string, nullable
  - `nextBuildAt` string, date-time: OPTIONAL. When the NEXT scheduled data build is due (ISO-8601 UTC), derived from the build workflow's real cron schedule — never guessed. A quiet gap before nextBuildAt is scheduled rest, not staleness. Present from the first post-release data build; absent on snapshots that predate the field.
  - `buildCadence` string: OPTIONAL. Plain-text statement of the data-build schedule (e.g. how many builds per day and over which UTC window), computed from the same parsed cron schedule as nextBuildAt. Present from the first post-release data build.
  - `generated_by` string
  - `methodology` object
  - `count` integer, required: Signals in this response.
  - `totalFlagged` integer: Size of the full flagged set before limit/direction filters.
  - `coverage` object, nullable: Coverage counts for the vertical universe behind the feed — three DIFFERENT sets, never interchangeable. Served as an EXPLICIT null (with coverageUnavailableReason stating why) when the committed snapshot predates the coverage object; the next scheduled data build populates it. Counts are never fabricated.
    - `registered` integer, nullable: Every vertical in the coverage registry, including new ones in burn-in.
    - `activelyScraped` integer, nullable: Verticals producing articles on the current daily scrape cycle.
    - `spannedByFlaggedEntities` integer, nullable: Verticals the currently flagged entities draw evidence from — moves with the news.
    - `definitions` object: The same three definitions riding the payload, so integrators never have to guess which set a number names.
  - `coverageUnavailableReason` string: Present exactly when coverage is null: a plain-language reason the counts are unavailable (e.g. the committed snapshot predates the coverage object; populated by the next scheduled data build). Absent when coverage is populated.
  - `signals` Signal[], required
    - `name` string, required: Canonical (normalized) entity key.
    - `label` string, required: Display label.
    - `slug` string, required: A discovery input; it may change. canonicalId is the durable identity.
    - `url` string, required: Entity dossier page.
    - `trajectory` Trajectory, required: Story momentum — how fast the narrative is moving. NOT an outcome view.
      - `direction` 'rising' | 'fading' | 'steady' | 'new'
      - `deltaPct` number, nullable: Percent change vs the entity's trailing baseline.
      - `trackedDays` integer, nullable
    - `signalCount` integer, nullable: Deprecated alias of counts.attention.current.documents.count (kept for existing callers): article signals the tracked feeds carried on the detection day.
    - `verticalCount` integer, nullable: Deprecated alias of counts.attention.current.domains.count (kept for existing callers): coverage verticals those signals came from on the detection day.
    - `domains` string[]
    - `baselineMultiple` number, nullable: Attention vs the entity's own trailing baseline (ubiquity-normalized).
    - `firstFlagged` string, nullable: YYYY-MM-DD.
    - `why` string, nullable
    - `desks` string[]
    - `evidence` Evidence[]
      - `title` string
      - `source` string, nullable
      - `url` string, nullable: Original-article URL. Check the claim against its origin.
    - `ask` string: A pre-phrased follow-up for POST /api/ask.
    - `evidenceStatus` 'receipted' | 'unreceipted': receipted = evidence[] carries >=1 source-attributed URL to check the claim against; unreceipted = attention measurement without article receipts (treat as a lead, not a sourced claim).
    - `evidenceCount` integer: Number of evidence rows attached (0 for unreceipted).
    - `canonicalId` string, nullable: The durable identity: the entity graph id the node door serves (GET /api/v1/node/e/{hex}, MCP traverse). Null with canonicalIdState when the graph does not carry the subject.
    - `canonicalIdState` CannotMeasure
      - `state` 'cannot-measure', required
      - `reason` string, required
    - `aliases` string[]: Curated, unambiguous shorthand that resolves to this subject in search; empty means none is curated.
    - `aliasesBasis` string
    - `addresses` object: Where the subject lives on each door.
      - `page` string
      - `rest` string, nullable: The node-door URL; null without a canonicalId.
      - `mcp` object: {tool:'get_entity', arguments:{name}}
      - `traverse` object: {tool:'traverse', arguments:{id: canonicalId}}; present with a canonicalId.
    - `identityNote` string: slug is a discovery input and may change; canonicalId (sb:e/...) is the durable identity.
    - `counts` EntityCounts: Two count namespaces that answer different questions — never compare or add them.
      - `attention` object
        - `current` object: scope tracked-coverage: documents (legacy signalCount) and coverage-vertical domains (legacy verticalCount) on the row's detection day.
          - `scope` 'tracked-coverage'
          - `window` union: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
            - object
              - …
            - CannotMeasure
              - …
          - `windowBasis` string
          - `documents` CountFact: One self-describing count. A count not taken is null with state cannot-measure and a reason, never 0.
            - `count` integer, nullable, required
            - `unit` 'documents' | 'domains' | 'publishers', required
            - `window` union, required: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
              - …
            - `scope` 'tracked-coverage' | 'retained-corpus', required
            - `state` 'cannot-measure'
            - `reason` string
          - `domains` CountFact: One self-describing count. A count not taken is null with state cannot-measure and a reason, never 0.
            - `count` integer, nullable, required
            - `unit` 'documents' | 'domains' | 'publishers', required
            - `window` union, required: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
              - …
            - `scope` 'tracked-coverage' | 'retained-corpus', required
            - `state` 'cannot-measure'
            - `reason` string
          - `definition` string
      - `evidence` object
        - `total` object: scope retained-corpus: documents deduped by url and distinct publishers over firstSeen..lastSeen (legacy observed.stories / observed.outlets).
          - `scope` 'retained-corpus'
          - `window` union: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
            - object
              - …
            - CannotMeasure
              - …
          - `windowBasis` string
          - `documents` CountFact: One self-describing count. A count not taken is null with state cannot-measure and a reason, never 0.
            - `count` integer, nullable, required
            - `unit` 'documents' | 'domains' | 'publishers', required
            - `window` union, required: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
              - …
            - `scope` 'tracked-coverage' | 'retained-corpus', required
            - `state` 'cannot-measure'
            - `reason` string
          - `publishers` CountFact: One self-describing count. A count not taken is null with state cannot-measure and a reason, never 0.
            - `count` integer, nullable, required
            - `unit` 'documents' | 'domains' | 'publishers', required
            - `window` union, required: Either the measured window (start/end, YYYY-MM-DD, inclusive) or cannot-measure with the reason — never a guessed date.
              - …
            - `scope` 'tracked-coverage' | 'retained-corpus', required
            - `state` 'cannot-measure'
            - `reason` string
          - `definition` string
      - `note` string

## Other responses

- `400`: Unknown `direction` value: {ok:false, code:"invalid_param", field, accepted, error}.
- `429`: Over a limit. Every 429 carries a `retry-after` header (seconds — for daily quotas, the time to the midnight-UTC reset); burst 429s also carry `retryAfter` in the body, and daily-quota 429s carry `requiresAuth: true` (the future sign-in hook). On /api/ask a funded key can also meet `error: "draw_ceiling_reached"` — a published ceiling on how much of its BALANCE one key may draw per UTC day (GET /api/tariff, read unit, `balance.daily_draw_ceiling_usd`). It is runaway-loop and stolen-key protection on the RATE, never a claim on the balance: the body carries `dailyDrawCeiling` {usd, reads, rate, resets, why}, `drawnToday`, `balance` {intact: true, remaining}, `owed: 0` and `nextSteps` (wait for the midnight-UTC reset, or ask the desk to raise it on your account). Nothing is drawn on a refused Read, the balance never expires, and what the ceiling holds back today is drawn tomorrow.

---

[API](https://skmtc.dev/sigb/apis/signal-bureau-api.md) · [All operations](https://skmtc.dev/sigb/apis/signal-bureau-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sigb/apis/signal-bureau-api/revisions/290c9c6ca0d0?raw)
