{
  "version": "1.0.0",
  "generated": "2026-09-07T18:58:06.450Z",
  "service": "fraudnews query API",
  "client_requirements": "None. Any HTTP client works, including Python's stdlib `urllib` with no headers set. Sending a User-Agent that identifies you is appreciated rather than required — it is how we tell a partner integration apart from an anonymous scraper when something looks wrong.",
  "endpoints": [
    "GET  /openapi.json                — OpenAPI 3.1, generated from the router's own constants",
    "GET  /docs                        — the same document, rendered for humans",
    "GET  /v1/vocabulary               — every accepted filter value, with live counts",
    "GET  /v1/articles?q=&subject=&predicate=&jurisdiction=&since=&changed_since=&band=&limit=&offset=",
    "GET  /v1/articles/:id",
    "GET  /v1/entities?name=&type=&role=&limit=&offset=",
    "GET  /v1/entities/:id",
    "GET  /v1/firms?name=&lei=&status=&home_state=&type=&limit=&offset=",
    "GET  /v1/firms/:esma_id",
    "POST /v1/flags   (authenticated: Authorization: Bearer <key>)",
    "GET  /v1/health"
  ],
  "spec_url": "/openapi.json",
  "docs_url": "/docs",
  "vocabulary_url": "/v1/vocabulary",
  "parameters": {
    "/v1/articles": [
      "q",
      "subject",
      "predicate",
      "jurisdiction",
      "since",
      "changed_since",
      "band",
      "limit",
      "offset"
    ],
    "/v1/entities": [
      "name",
      "type",
      "role",
      "limit",
      "offset"
    ],
    "/v1/firms": [
      "name",
      "lei",
      "status",
      "register",
      "home_state",
      "type",
      "limit",
      "offset"
    ],
    "POST /v1/flags (body)": [
      "subject_name",
      "subject_type",
      "subject_lei",
      "subject_domain",
      "subject_address",
      "reason",
      "confidence",
      "provenance_url",
      "rule_version",
      "origin"
    ]
  },
  "vocabulary": {
    "subject": [
      "crypto",
      "forex",
      "investment"
    ],
    "predicate": [
      "fraud",
      "warning",
      "law",
      "grant"
    ],
    "band": [
      "breaking",
      "major",
      "notable",
      "routine"
    ],
    "entity_type": [
      "firm",
      "platform",
      "token",
      "person",
      "unknown"
    ],
    "firm_status": [
      "active",
      "inactive",
      "unknown"
    ],
    "flag_subject_type": [
      "firm",
      "platform",
      "token",
      "person",
      "domain",
      "wallet",
      "unknown"
    ],
    "jurisdiction": "ISO 3166-1 alpha-2 plus `Global`, but NOT a closed set — read live from the data at /v1/vocabulary, because the list grows as coverage does. Guessing a value is how a caller concludes we hold no data for a country we cover: until 2026-09-05 UK articles were split between `UK` and `United Kingdom` and `GB` returned nothing at all."
  },
  "sync": "Mirror with GET /v1/articles?changed_since=<sync.next_cursor>, not with `since`. `since` filters by SOURCE PUBLICATION date and cannot show you corrections, reclassifications or withdrawals; `changed_since` can, and reports removals in `sync.deleted`.",
  "search": "`q` is a case-insensitive substring match over article title and, where the licence permits us to hold one, summary. Most articles carry no summary, so treat `q` as a title search.",
  "unknown_parameters": "Rejected with 400, never ignored. An ignored filter returns the whole corpus with a 200 and is indistinguishable from a successful query.",
  "read_access": "Reads are open: no key, no per-caller quota. That is deliberate — this is a free, non-profit register and the point of it is to be queried. Responses are edge-cached for 300s, so repeated identical URLs mostly do not reach the database. Two asks rather than rules: send a User-Agent that identifies you, and if you are backfilling the whole corpus prefer `changed_since` for subsequent syncs over re-paging it. Only POST /v1/flags requires a key, because it writes.",
  "licence": "Article body text is never served. A summary appears only where the source licence permits reproduction; every other item is link, headline, publisher, date and our classification. Firm records are reproduced from ESMA's union public register and every /v1/firms response carries the required source acknowledgement."
}