throughlineapi

A news API for Polymarket prediction markets.

One read-only feed: which news articles are relevant to which Polymarket contracts, and why. Free and rate-limited. You hold a cursor and read forward, and corrections arrive on the same stream as the matches themselves. Geopolitical markets first.

This is a proposal, not a running service. The publication contract is not frozen and the API does not serve traffic yet, so treat every field and status below as open to change. If you would build against this, the useful thing to do now is argue with the shape of it — naming what is missing is worth more than agreement.

request

GET /v1/news?after=48217&limit=1
Host: api.throughlineapi.com
Authorization: Bearer tl_...

200 · proposed shape

{
  "as_of": 48219,
  "cursor": 48219,
  "complete": true,
  "matches": [
    {
      "match_id": "m_7f31c9",
      "revision": 1,
      "sequence": 48218,
      "stage": "preliminary",
      "novelty": "new",
      "impact": 3,

      "article": {
        "report_id": "r_9a21c4",
        "publisher": "reuters",
        "url": "https://www.reuters.com/world/...",
        "language": "en",
        "title": "Israel and Lebanon agree a framework
          to demarcate the land border"
      },

      "contract": {
        "condition_id": "0x9f2c7a...e13b",
        "question": "Israel-Lebanon border agreement
          signed before 30 June 2027?",
        "rule_revision": 3
      },

      "reason": "The framework names a demarcation
        mechanism and a working timetable, which is
        the step a signed agreement in the window
        depends on.",
      "uncertainty": "Framework texts have preceded
        signature by more than a year before.",

      "evidence": {
        "availability": "full_text",
        "refs": ["ev_3301", "ev_3302"]
      },

      "clocks": {
        "source_published_at": "2026-11-03T08:14:00Z",
        "received_at":         "2026-11-03T08:16:41Z",
        "assessed_at":         "2026-11-03T08:17:09Z",
        "public_at":           "2026-11-03T08:17:52Z"
      }
    }
  ]
}

Reading forward

Every published revision gets a sequence, and it only ever goes up. Keep the cursor from your last response, pass it back as after, and you receive each revision exactly once, in order.

When complete is false there is more behind the page, so call again immediately with the new cursor. When it is true you are at the head and can back off.

Corrections arrive as revisions, not edits. A match that changes stage, gains an impact score or gets withdrawn comes down the stream as a new revision of the same match_id. Upsert on match_id, keep the highest revision you have seen, and a withdrawal is a revision with stage: "withdrawn" rather than a deletion you have to infer from an absence.

This matters more than it sounds: a feed that only ever adds would let early, wrong matches sit in your copy forever. Reading the stream to the head is what keeps your copy honest, so a client that only reads new matches and never applies revisions is misusing the API.

Replaying a page you already processed is safe. Make your side idempotent on (match_id, revision) and a retry costs nothing.

Endpoints

Four reads. There are no write endpoints, and no request causes any analysis to run — you are reading a feed that was produced whether you asked or not.

GET /v1/news

Matches at or after a cursor, oldest first, including revisions and withdrawals of matches you have already seen.

GET /v1/news/{match_id}

The current revision of one match, with its revision history.

GET /v1/markets/{condition_id}/news

Matches for one contract. The watchlist primitive: this is what an email subscription reads underneath.

GET /v1/coverage

What is covered and what is actually being screened right now. See below — this is the endpoint that makes a quiet feed interpretable.

Parameters

NameMeaning
afterCursor from your last response. Omit it and you start at the head, not at the beginning of time.
limitMatches per page, 1 to 200. Defaults to 50.
condition_idRestrict to specific contracts. Repeatable.
stagepreliminary, assessed, withdrawn. Repeatable. Filtering out withdrawals will leave stale matches in your copy.
noveltynew, update, repeat, uncertain. Repeatable.
min_impact0 to 4. Impact is a model assessment, not a probability — treat it as a sort key, not a threshold you trust.

Why there is a coverage endpoint

An empty result has four possible meanings and the matches feed cannot tell them apart. /v1/coverage reports them separately for each contract: whether it is in the declared scope, when it was last actually screened, whether processing is delayed or unavailable, and whether it is simply quiet.

A contract's last match is not its last screen. If you build an alerting product on this, read coverage as well as matches, or your users will read a broken pipeline as a calm week.

Declared coverage starts with geopolitical markets and is checked against what upstream selection really produces before launch. Reusing an existing analysis flow does not establish complete coverage of every market, and the endpoint will not claim otherwise.

Keys and limits

A bearer token in the Authorization header. Keys are free and read-only, because the whole API is read-only.

Exact rate limits are not set. They will be published as numbers rather than described as "generous", and they exist to bound operating cost, which is the constraint that keeps access free. If a limit would break a reasonable use of this, say which and why.

Optional email updates for contracts you follow will read this same feed. Cadence and provider are undecided.

Errors

Errors carry a stable machine-readable reason. The status says whether to retry; the reason says why.

StatusWhat happened
400A parameter is malformed or out of range. The response names which one. Do not retry unchanged.
401Missing or rejected key.
404No such match or contract. A withdrawn match returns its final revision, not a 404.
409Your cursor is ahead of the published head, so it did not come from us. Reset to the head.
429Rate limited. Retry-After is always present and always honoured.
503The feed is unavailable. This is never returned as an empty page of matches — an empty feed and a missing feed are different answers.

Tell us what is wrong with it

The contract is still soft, which is the only time feedback is cheap to act on. If you run something that would consume this, the most useful reply names the contracts you want covered and the field you would need that is not listed above.