docs/api/NewsService.openapi.yaml
Rama main · réplica de lectura del repositorio original.
openapi: 3.1.0
info:
title: NewsService API
version: 1.0.0
security:
- WorldMonitorKey: []
- ApiKeyHeader: []
servers:
- url: https://api.worldmonitor.app
paths:
/api/news/v1/summarize-article:
post:
parameters:
- name: Idempotency-Key
in: header
description: Optional client-generated idempotency key. Retrying a POST with the same key and an identical request body replays the original response (only the status, body, and Content-Type are reproduced) instead of re-executing; reusing the key with a different body is rejected with 422. For mutations this avoids duplicating the side effect, while for batch-read POSTs it replays a cached snapshot that can be up to 24 hours stale. Keys are scoped per authenticated caller (falling back to the source IP for unauthenticated endpoints) and retained for 24 hours.
required: false
example: "4f8b9c2e-1a3d-4b6f-8e0a-2c5d7f9b1e34"
schema:
type: string
minLength: 1
maxLength: 255
pattern: "^[\\x21-\\x7E]{1,255}$"
tags:
- NewsService
summary: SummarizeArticle
description: Generate an article summary with language-model provider selection and fallback support, returning the chosen provider, model and reported processing errors.
operationId: SummarizeArticle
requestBody:
content:
application/json:
example:
"bodies":
- "example"
"geoContext": "example"
"headlines":
- "example"
"lang": "en"
"mode": "brief"
"provider": "openrouter"
schema:
$ref: '#/components/schemas/SummarizeArticleRequest'
required: true
responses:
"200":
description: Successful response
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key echoed from the request. Present only when the client opted into idempotency.
Idempotent-Replayed:
schema:
type: boolean
description: true when this response was replayed from an earlier request with the same key, false on the first (original) request. Present only when the client opted into idempotency.
content:
application/json:
example:
"error": "example"
"errorType": "all"
"fallback": true
"model": "example"
"provider": "openrouter"
schema:
$ref: '#/components/schemas/SummarizeArticleResponse'
"400":
description: Validation error, invalid Idempotency-Key header, or malformed JSON request body
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
- $ref: '#/components/schemas/InvalidRequestBodyError'
"409":
description: A request with this Idempotency-Key is still being processed
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key supplied by the client.
Retry-After:
schema:
type: string
description: Seconds to wait before retrying the in-flight request.
content:
application/json:
schema:
type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
"422":
description: The Idempotency-Key was already used with a different request body
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key supplied by the client.
content:
application/json:
schema:
type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: API access requires an active subscription (the API key's subscription is inactive or expired).
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/summarize-article-cache:
get:
tags:
- NewsService
summary: GetSummarizeArticleCache
description: GetSummarizeArticleCache returns an AI summary already stored by SummarizeArticle for a deterministic cache key. Hits are CDN-cacheable; misses are not.
operationId: GetSummarizeArticleCache
parameters:
- name: cache_key
in: query
description: Deterministic cache key computed by buildSummaryCacheKey().
required: false
example: "summary:v1:example-cache"
schema:
type: string
pattern: '^summary:v\d+:[a-z0-9:_-]{3,120}$'
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"error": "example"
"errorType": "all"
"fallback": true
"model": "example"
"provider": "openrouter"
schema:
$ref: '#/components/schemas/SummarizeArticleResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: API access requires an active subscription (the API key's subscription is inactive or expired).
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-feed-digest:
get:
tags:
- NewsService
summary: ListFeedDigest
description: ListFeedDigest returns RSS headlines grouped by category for a site variant (full, tech, finance, happy, commodity, energy) and language, with coverage state.
operationId: ListFeedDigest
parameters:
- name: variant
in: query
description: 'Digest variant: full, tech, finance, happy, commodity, energy. Unsupported variants fall back to full.'
required: false
example: "example"
schema:
type: string
- name: lang
in: query
description: ISO 639-1 language code of a supported digest language (en, fr, ar, etc.). Unsupported codes are rejected with 400.
required: false
example: "en"
schema:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"categories":
"exampleKey":
"items":
- "corroborationCount": 42
"credibilityScore": 42
"importanceScore": 42
"isAlert": true
"link": "https://example.com/worldmonitor"
"source": "example"
"title": "example"
"coverage":
"attemptedAt": "2026-01-15T12:00:00Z"
"categoryCompleted": 1
"categoryStates":
"exampleKey": "example"
"categoryTotal": 1
"droppedCategoryCap": 1
"feedStatuses":
"exampleKey": "example"
"generatedAt": "2026-01-15T12:00:00Z"
schema:
$ref: '#/components/schemas/ListFeedDigestResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: API access requires an active subscription (the API key's subscription is inactive or expired).
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-country-headlines:
get:
tags:
- NewsService
summary: ListCountryHeadlines
description: ListCountryHeadlines reads fresh country reporting from existing RSS caches without fetching publishers or applying dashboard category caps.
operationId: ListCountryHeadlines
parameters:
- name: country_codes
in: query
description: ISO 3166-1 alpha-2 codes. Repeated query parameter, at most 250 countries.
required: true
style: form
explode: true
example:
- "US"
schema:
type: array
maxItems: 250
minItems: 1
items:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"countries":
"exampleKey":
"items":
- "link": "https://example.com/worldmonitor"
"publishedAt": 1717200000000
"source": "example"
"title": "example"
"feedCached": 1
"feedTotal": 1
"readAt": "2026-01-15T12:00:00Z"
"state": "example"
schema:
$ref: '#/components/schemas/ListCountryHeadlinesResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: API access requires an active subscription (the API key's subscription is inactive or expired).
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-media-perspective:
get:
tags:
- NewsService
summary: ListMediaPerspective
description: ListMediaPerspective groups headlines about one country by outlet home country and audience. PRO-gated. Requires entitlement tier >= 1.
operationId: ListMediaPerspective
security:
- WorldMonitorKey: []
- ApiKeyHeader: []
- BearerAuth: []
parameters:
- name: subject_country
in: query
description: ISO2.
required: true
example: "SA"
schema:
type: string
- name: outlet_countries
in: query
description: ISO2, at most 30.
required: false
style: form
explode: true
example:
- "US"
schema:
type: array
items:
type: string
- name: audience
in: query
description: domestic, international or diaspora.
required: false
example: "domestic"
schema:
type: string
- name: window_hours
in: query
description: 24, 48, 72 or 96.
required: false
"schema":
"type": "integer"
"format": "int32"
"enum":
- 0
- 24
- 48
- 72
- 96
example: 0
- name: outlet_regions
in: query
description: UN M49 region slugs, e.g. northern-europe.
required: false
style: form
explode: true
example:
- "northern-europe"
schema:
type: array
items:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"feedCached": 812
"feedTotal": 812
"groups":
- "audience": "international"
"framing":
"critical": 0
"favorable": 0
"hostile": 0
"method": ""
"model": ""
"neutral": 0
"promptVersion": ""
"unlabeled": 1
"headlineCount": 1
"headlines":
- "englishTitle": "Saudi Arabia hosts ceasefire talks"
"framing": ""
"link": "https://www.bbc.co.uk/news/articles/example"
"outlet": "BBC World"
"ownershipClass": "public-service"
"propagandaRisk": "low"
"publishedAt": 1717200000000
"publisherFamily": "bbc"
"stateAffiliated": ""
"tier": 1
"title": "Saudi Arabia hosts ceasefire talks"
"titleLanguage": "en"
"homeCountry": "GB"
"outletCount": 1
"noCoverageCountries":
[]
"readAt": "2026-10-27T12:00:00.000Z"
"state": "complete"
"subjectCountry": "SA"
"unattributedCount": 0
"windowHours": 72
schema:
$ref: '#/components/schemas/ListMediaPerspectiveResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: PRO entitlement access denied.
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-news-pool:
get:
tags:
- NewsService
summary: ListNewsPool
description: 'ListNewsPool merges cached news for several editions and content languages, one item per article URL: English from the warmed digest cells, other languages from their feeds'' cached parses. Reads cache only; never builds a digest or fetches a feed. PRO-gated. Requires entitlement tier >= 1.'
operationId: ListNewsPool
security:
- WorldMonitorKey: []
- ApiKeyHeader: []
- BearerAuth: []
parameters:
- name: languages
in: query
description: Content languages (ISO 639-1), at most 8. Empty means en.
required: false
style: form
explode: true
example:
- "fr"
schema:
type: array
maxItems: 8
items:
type: string
- name: editions
in: query
description: Digest editions, e.g. full, tech, finance. Empty means full.
required: false
style: form
explode: true
example:
- "full"
schema:
type: array
maxItems: 8
items:
type: string
- name: category
in: query
description: One category key within the selected editions.
required: false
example: "us"
schema:
type: string
maxLength: 32
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"cells":
- "edition": "full"
"items": 1
"language": "fr"
"state": "complete"
"generatedAt": "2026-01-15T12:00:00Z"
"items":
- "category": "us"
"editions":
- "full"
"item":
"corroborationCount": 42
"credibilityScore": 42
"importanceScore": 42
"isAlert": true
"link": "https://example.com/worldmonitor"
"source": "example"
"title": "example"
"language": "fr"
"state": "complete"
schema:
$ref: '#/components/schemas/ListNewsPoolResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: PRO entitlement access denied.
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-source-items:
get:
tags:
- NewsService
summary: ListSourceItems
description: ListSourceItems returns the newest cached items of named sources in one category, for a dashboard panel whose enabled sources fell below the digest's per-category cap. Reads cached feed parses only; never fetches a feed.
operationId: ListSourceItems
parameters:
- name: editions
in: query
description: |-
Digest editions to look for each source in, in order, e.g. full, tech.
Empty means full.
required: false
style: form
explode: true
example:
- "full"
schema:
type: array
maxItems: 8
items:
type: string
- name: category
in: query
description: One category key within the selected editions.
required: true
example: "europe"
schema:
type: string
minLength: 1
maxLength: 32
- name: sources
in: query
description: |-
Catalog source names, at most 24, each at most 120 characters. Order and
duplicates do not matter.
required: true
style: form
explode: true
example:
- "France 24"
schema:
type: array
maxItems: 24
minItems: 1
items:
type: string
maxLength: 120
- name: lang
in: query
description: |-
ISO 639-1 language code of a supported digest language (en, fr, ar, etc.);
empty means en. Unsupported codes are rejected with 400. Only sources this
language's digest fetches are read.
required: false
example: "en"
schema:
type: string
maxLength: 8
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"generatedAt": "2026-01-15T12:00:00Z"
"items":
- "corroborationCount": 42
"credibilityScore": 42
"importanceScore": 42
"isAlert": true
"link": "https://example.com/worldmonitor"
"source": "France 24"
"title": "example"
"sources":
- "edition": "full"
"items": 1
"source": "France 24"
"state": "found"
schema:
$ref: '#/components/schemas/ListSourceItemsResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
"403":
description: API access requires an active subscription (the API key's subscription is inactive or expired).
headers:
X-Billing-Verification:
description: Present when the 403 is a billing-provider-confirmed subscription lapse (value subscription_lapsed, matching the body `code`).
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
"503":
description: Service unavailable. Billing-verification responses include code and X-Billing-Verification; other gateway infrastructure failures use the generic GatewayError shape.
headers:
Retry-After:
description: Seconds to wait before retrying (1-60).
schema:
type: string
X-Billing-Verification:
description: Billing-verification state that produced this response (matches the body `code`).
schema:
type: string
X-Validation-Mode:
description: Present with value degraded when user API-key validation is temporarily unavailable.
schema:
type: string
X-RateLimit-Mode:
description: Present with value degraded when a fail-closed rate-limit dependency is unavailable.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/BillingVerificationError'
- $ref: '#/components/schemas/GatewayError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-label-changes:
get:
tags:
- NewsService
summary: ListLabelChanges
description: ListLabelChanges returns stories whose corroboration label moved between single-publisher and corroborated in the last seven days, with the publishers behind each change.
operationId: ListLabelChanges
security: []
parameters:
- name: story_id
in: query
description: Story identity hash (64 hex characters). Empty lists changes across all stories.
required: false
example: "example-id"
schema:
type: string
- name: limit
in: query
description: Maximum changes returned, newest first. 0 uses the default of 50; at most 200.
required: false
example: 25
schema:
type: integer
format: int32
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"changes":
- "at": 1767182400000
"credibilityScore": 72
"field": "corroboration"
"link": "https://example.com/news/synthetic-example"
"next": "corroborated"
"nextPublishers": 2
"previous": "single-publisher"
"previousPublishers": 1
"reason": "2 publisher families now carry this story (was 1)."
"sources":
- "name": "Example Wire (synthetic)"
"tier": 1
- "name": "Example Daily (synthetic)"
"tier": 2
"storyId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"title": "Synthetic example story"
"trigger": "digest"
"counts":
"at": 1767182400000
"corroborated": 64
"singlePublisher": 51
"stories": 120
"tier4Only": 3
"unknown": 2
"retentionDays": 7
"state": "ok"
schema:
$ref: '#/components/schemas/ListLabelChangesResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/submit-error-report:
post:
parameters:
- name: Idempotency-Key
in: header
description: Optional client-generated idempotency key. Retrying a POST with the same key and an identical request body replays the original response (only the status, body, and Content-Type are reproduced) instead of re-executing; reusing the key with a different body is rejected with 422. For mutations this avoids duplicating the side effect, while for batch-read POSTs it replays a cached snapshot that can be up to 24 hours stale. Keys are scoped per authenticated caller (falling back to the source IP for unauthenticated endpoints) and retained for 24 hours.
required: false
example: "4f8b9c2e-1a3d-4b6f-8e0a-2c5d7f9b1e34"
schema:
type: string
minLength: 1
maxLength: 255
pattern: "^[\\x21-\\x7E]{1,255}$"
tags:
- NewsService
summary: SubmitErrorReport
description: SubmitErrorReport stores a reader's report that a label or story is wrong, for an operator to review. No account required; rate-limited; never applied automatically.
operationId: SubmitErrorReport
security: []
requestBody:
content:
application/json:
example:
"contact": "example"
"message": "Example WorldMonitor observation."
"storyId": "example-id"
"url": "https://example.com/worldmonitor"
schema:
$ref: '#/components/schemas/SubmitErrorReportRequest'
required: true
responses:
"200":
description: Successful response
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key echoed from the request. Present only when the client opted into idempotency.
Idempotent-Replayed:
schema:
type: boolean
description: true when this response was replayed from an earlier request with the same key, false on the first (original) request. Present only when the client opted into idempotency.
content:
application/json:
example:
"reportId": "example-id"
"status": "example"
schema:
$ref: '#/components/schemas/SubmitErrorReportResponse'
"400":
description: Validation error, invalid Idempotency-Key header, or malformed JSON request body
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
- $ref: '#/components/schemas/InvalidRequestBodyError'
"409":
description: A request with this Idempotency-Key is still being processed
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key supplied by the client.
Retry-After:
schema:
type: string
description: Seconds to wait before retrying the in-flight request.
content:
application/json:
schema:
type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
"422":
description: The Idempotency-Key was already used with a different request body
headers:
Idempotency-Key:
schema:
type: string
description: The idempotency key supplied by the client.
content:
application/json:
schema:
type: object
required:
- error
- message
properties:
error:
type: string
message:
type: string
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/list-error-reports:
get:
tags:
- NewsService
summary: ListErrorReports
description: |-
ListErrorReports lists stored reports for review. Operators only.
Requires the X-Trust-Review-Key header (the server's TRUST_REVIEW_SECRET), not an API key; without it the response is 401.
operationId: ListErrorReports
security:
- TrustReviewKey: []
parameters:
- name: status
in: query
description: pending (default) | reviewed.
required: false
example: "example"
schema:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"reports":
- "contact": "example"
"createdAt": 1717200000000
"id": "example-id"
"message": "Example WorldMonitor observation."
"publicNote": "example"
"state": "example"
schema:
$ref: '#/components/schemas/ListErrorReportsResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"401":
description: Missing or invalid X-Trust-Review-Key, or review is not configured on the server.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/review-error-report:
post:
tags:
- NewsService
summary: ReviewErrorReport
description: |-
ReviewErrorReport accepts or rejects a report. An accepted report's public note is added to the label log. Operators only.
Requires the X-Trust-Review-Key header (the server's TRUST_REVIEW_SECRET), not an API key; without it the response is 401.
operationId: ReviewErrorReport
security:
- TrustReviewKey: []
requestBody:
content:
application/json:
example:
"decision": "example"
"publicNote": "example"
"reportId": "example-id"
schema:
$ref: '#/components/schemas/ReviewErrorReportRequest'
required: true
responses:
"200":
description: Successful response
content:
application/json:
example:
"report":
"contact": "example"
"createdAt": 1717200000000
"id": "example-id"
"message": "Example WorldMonitor observation."
"publicNote": "example"
schema:
$ref: '#/components/schemas/ReviewErrorReportResponse'
"400":
description: Validation error or malformed JSON request body
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/InvalidRequestBodyError'
"401":
description: Missing or invalid X-Trust-Review-Key, or review is not configured on the server.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/search-fact-checks:
get:
tags:
- NewsService
summary: SearchFactChecks
description: SearchFactChecks returns ratings that IFCN-verified fact-checkers published about claims similar to the one given, for citation with attribution.
operationId: SearchFactChecks
security: []
parameters:
- name: claim
in: query
description: The claim or headline, up to 300 characters.
required: false
example: "example"
schema:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"caveat": "Ratings are the fact-checkers' own, quoted with attribution from IFCN-verified signatories. WorldMonitor does not rate claims, and a rating never changes the coverage result above."
"factChecks":
- "claimReviewed": "A synthetic example claim, similar to the claim checked"
"publisher": "Example Fact-Checker (synthetic)"
"rating": "Example rating"
"reviewedAt": "2026-01-15T12:00:00.000Z"
"site": "example.com"
"title": "Synthetic example fact-check"
"url": "https://example.com/fact-check/synthetic-example"
"state": "ok"
schema:
$ref: '#/components/schemas/SearchFactChecksResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
/api/news/v1/search-claim-headlines:
get:
tags:
- NewsService
summary: SearchClaimHeadlines
description: SearchClaimHeadlines returns the fresh headlines from every configured feed that share a claim's words, so the /verify page and verify_claim can build its coverage card.
operationId: SearchClaimHeadlines
security: []
parameters:
- name: claim
in: query
description: The claim or headline, up to 300 characters. Empty returns only the counts.
required: false
example: "example"
schema:
type: string
- name: jmespath
in: query
description: |-
Optional JMESPath expression applied server-side to project or reduce the JSON response before it is returned (mirrors the MCP jmespath argument). Invalid expressions, expressions larger than 1024 UTF-8 bytes, or projections that exceed the 256 KB output cap return HTTP 400 with a {_jmespath_error, original_keys} envelope. Grammar and worked examples: https://www.worldmonitor.app/docs/mcp-jmespath.
required: false
example: "keys(@)"
schema:
type: string
responses:
"200":
description: Successful response
content:
application/json:
example:
"feedCached": 241
"feedTotal": 241
"headlines":
- "link": "https://example.com/news/synthetic-example"
"publishedAt": 1768478400000
"source": "Example Feed"
"title": "Synthetic example headline sharing the claim's words"
"readAt": "2026-01-15T12:00:00.000Z"
"searchedFeeds": 216
"searchedHeadlines": 4140
"state": "complete"
schema:
$ref: '#/components/schemas/SearchClaimHeadlinesResponse'
"400":
description: Validation error
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/JmespathProjectionError'
"429":
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
description: Maximum requests allowed in the active rate-limit window.
schema:
type: string
X-RateLimit-Remaining:
description: Requests remaining in the active rate-limit window.
schema:
type: string
X-RateLimit-Reset:
description: Unix epoch milliseconds when the active rate-limit window resets.
schema:
type: string
Retry-After:
description: Seconds to wait before retrying the request.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/RateLimitError'
default:
description: Gateway or handler error response.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- $ref: '#/components/schemas/GatewayError'
components:
securitySchemes:
WorldMonitorKey:
type: apiKey
in: header
name: X-WorldMonitor-Key
description: User-issued WorldMonitor API key.
ApiKeyHeader:
type: apiKey
in: header
name: X-Api-Key
description: Alias header for the WorldMonitor API key (X-WorldMonitor-Key).
BearerAuth:
type: http
scheme: bearer
description: 'Bearer token: a Clerk-issued JWT for browser session flows, passed as Authorization: Bearer <token>.'
TrustReviewKey:
type: apiKey
in: header
name: X-Trust-Review-Key
description: Operator review key (the server TRUST_REVIEW_SECRET). Required by the error-report review operations; a WorldMonitor API key does not authorize them.
schemas:
JmespathProjectionError:
description: Returned when a REST jmespath projection is invalid or exceeds the expression/output byte limits.
properties:
_jmespath_error:
description: Projection error discriminator and details.
type: string
original_keys:
description: Top-level keys or shape of the unprojected response.
items:
type: string
type: array
required:
- _jmespath_error
- original_keys
type: object
UnauthorizedError:
type: object
properties:
error:
type: string
description: Human-readable error message.
required:
- error
description: Returned when the API key is missing, malformed, or lacks current API access.
Error:
type: object
properties:
message:
type: string
description: Error message (e.g., 'user not found', 'database connection failed')
description: Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize.
BillingVerificationError:
type: object
description: "Returned with HTTP 503 when paid access cannot be confirmed right now: the billing provider is re-verifying a recently expired subscription, or the entitlement backend is unreachable. Retryable — honor Retry-After."
properties:
error:
type: string
description: Human-readable billing-verification failure reason.
code:
type: string
enum:
- renewal_verification_pending
- renewal_verification_failed
- entitlement_verification_unavailable
description: Machine-readable billing-verification state, mirrored in the X-Billing-Verification response header.
requiredTier:
type: integer
format: int32
description: Minimum entitlement tier required for this endpoint, when the denial came from a tier gate.
required:
- error
- code
InvalidRequestBodyError:
type: object
description: Returned when a JSON POST request body is empty or malformed.
properties:
message:
type: string
description: Invalid request body
required:
- message
GatewayError:
type: object
description: Returned by gateway infrastructure errors before an RPC handler runs, such as origin, routing, method, authentication, or quota checks.
properties:
error:
oneOf:
- type: string
- type: object
additionalProperties: true
description: Gateway error reason or structured gateway failure details.
required:
- error
RateLimitError:
type: object
description: Returned when a gateway or handler rate limit rejects the request.
properties:
error:
type: string
description: Human-readable rate-limit failure reason.
required:
- error
ForbiddenError:
type: object
properties:
error:
type: string
description: Human-readable entitlement failure reason.
code:
type: string
enum:
- subscription_lapsed
description: Machine-readable denial code, present when the 403 is a billing-provider-confirmed subscription lapse (mirrored in the X-Billing-Verification response header).
requiredTier:
type: integer
format: int32
description: Minimum entitlement tier required for this endpoint.
currentTier:
type: integer
format: int32
description: Caller entitlement tier when known.
planKey:
type: string
description: Caller plan key when known.
required:
- error
description: Returned when a PRO-gated endpoint denies access because the caller has no resolved authenticated user, entitlements cannot be verified, or the caller lacks the required entitlement tier.
FieldViolation:
type: object
properties:
field:
type: string
description: The field path that failed validation (e.g., 'user.email' for nested fields). For header validation, this will be the header name (e.g., 'X-API-Key')
description:
type: string
description: Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing')
required:
- field
- description
description: FieldViolation describes a single validation error for a specific field.
ValidationError:
type: object
properties:
violations:
type: array
items:
$ref: '#/components/schemas/FieldViolation'
description: List of validation violations
required:
- violations
description: ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong.
SummarizeArticleRequest:
type: object
properties:
provider:
type: string
minLength: 1
description: 'LLM provider: "ollama", "openrouter"'
headlines:
type: array
items:
type: string
minItems: 1
description: |-
Headlines to summarize. Up to 10 raw headlines are used for request
identity/cache matching; the LLM prompt uses up to 5 unique, non-empty
sanitized headline/body pairs.
minItems: 1
mode:
type: string
description: 'Summarization mode: "brief", "analysis", "translate", "" (default).'
geoContext:
type: string
description: Geographic signal context to include in the prompt.
variant:
type: string
description: 'Variant: "full", "tech", or target language for translate mode.'
lang:
type: string
description: Output language code, default "en".
systemAppend:
type: string
description: Optional system prompt append for analytical framework instructions.
bodies:
type: array
items:
type: string
description: |-
Optional article bodies paired 1:1 with `headlines`. When bodies[i] is
non-empty, the prompt interleaves it as grounding context under
headlines[i]; when empty, behavior is identical to headline-only today.
Callers may supply a shorter array; missing entries are treated as empty.
Each body is subject to the same sanitisation as headlines before reaching
the LLM prompt.
required:
- provider
description: SummarizeArticleRequest specifies parameters for LLM article summarization.
SummarizeArticleResponse:
type: object
properties:
summary:
type: string
description: The generated summary text.
model:
type: string
description: Model identifier used for generation.
provider:
type: string
description: Provider that produced the result (or "cache").
tokens:
type: integer
format: int32
description: Token count from the LLM response.
fallback:
type: boolean
description: Whether the client should try the next provider in the fallback chain.
error:
type: string
description: Error message if the request failed.
errorType:
type: string
description: Error type/name (e.g. "TypeError").
status:
type: string
enum:
- SUMMARIZE_STATUS_UNSPECIFIED
- SUMMARIZE_STATUS_SUCCESS
- SUMMARIZE_STATUS_CACHED
- SUMMARIZE_STATUS_SKIPPED
- SUMMARIZE_STATUS_ERROR
description: SummarizeStatus indicates the outcome of a summarization request.
statusDetail:
type: string
description: Human-readable detail for non-success statuses (skip reason, etc.).
description: SummarizeArticleResponse contains the LLM summarization result.
GetSummarizeArticleCacheRequest:
type: object
properties:
cacheKey:
type: string
description: Deterministic cache key computed by buildSummaryCacheKey().
description: GetSummarizeArticleCacheRequest looks up a pre-computed summary by cache key.
ListFeedDigestRequest:
type: object
properties:
variant:
type: string
description: 'Digest variant: full, tech, finance, happy, commodity, energy. Unsupported variants fall back to full.'
lang:
type: string
description: ISO 639-1 language code of a supported digest language (en, fr, ar, etc.). Unsupported codes are rejected with 400.
ListFeedDigestResponse:
type: object
properties:
categories:
type: object
additionalProperties:
$ref: '#/components/schemas/CategoryBucket'
description: Per-category buckets — keys match category names from feed config
feedStatuses:
type: object
additionalProperties:
type: string
description: |-
Per-feed status — only non-ok states emitted; absent key implies ok.
Values: empty (feed returned 0 items), timeout (timed out during fetch),
all-undated (every parsed item lacked a usable date), partial-undated
(some parsed items lacked a usable date).
generatedAt:
type: string
description: ISO 8601 timestamp of when this digest was generated
coverage:
$ref: '#/components/schemas/DigestCoverage'
CategoriesEntry:
type: object
properties:
key:
type: string
value:
$ref: '#/components/schemas/CategoryBucket'
FeedStatusesEntry:
type: object
properties:
key:
type: string
value:
type: string
CategoryBucket:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/NewsItem'
NewsItem:
type: object
properties:
source:
type: string
minLength: 1
description: Source feed name.
title:
type: string
minLength: 1
description: Article headline.
link:
type: string
description: Article URL.
publishedAt:
type: integer
format: int64
description: 'Publication time, as Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
isAlert:
type: boolean
description: Whether this article triggered an alert condition.
threat:
$ref: '#/components/schemas/ThreatClassification'
location:
$ref: '#/components/schemas/GeoCoordinates'
locationName:
type: string
description: Human-readable location name.
importanceScore:
type: integer
format: int32
description: |-
Composite importance score. The base 0-100 score uses severity × 55% +
source tier × 20% + corroboration × 15% + recency × 10%, then may add an
18-point diplomacy/flashpoint boost and 4 points per entity-level
corroborating source, capped at five sources. The final score can exceed
100; with current boosts it is approximately capped at 138.
corroborationCount:
type: integer
format: int32
description: |-
Number of distinct sources that reported the same story in this digest
cycle. "Same story" is determined by edit-tolerant story-identity
clustering (headlines describing one event with different wording,
ordering, source suffixes, truncation, or morphology corroborate each
other) — not exact-title matching. See shared/story-identity.js.
storyMeta:
$ref: '#/components/schemas/StoryMeta'
snippet:
type: string
description: |-
Cleaned article description from the RSS/Atom <description> /
<content:encoded> / <summary> / <content> tag: HTML-stripped,
entity-decoded, whitespace-normalised, clipped to 400 chars. Empty string
when unavailable or indistinguishable from the headline — consumers must
fall back to the headline for display/LLM grounding in that case.
tickers:
type: array
items:
type: string
maxItems: 8
description: |-
Equity ticker symbols mentioned by the story, extracted at ingest from
cashtags ($AAPL) and the curated company dictionary
(shared/stocks.json). Uppercase symbols, deduplicated, capped at 8.
Empty when no tracked ticker is mentioned. See shared/ticker-extract.js.
maxItems: 8
credibilityScore:
type: integer
format: int32
description: |-
Credibility score (0-100), distinct from importance_score. Measures
source reliability / truthfulness, not newsworthiness. The base score
uses source tier × 30% + propaganda risk × 50% + independent
corroboration × 20%. High propaganda-risk sources (state-controlled
media) are capped at 40 so a highly newsworthy RT/TASS story still
scores low. Third-party bias/factuality ratings are reserved and not
currently applied. See docs/methodology/news-credibility.mdx.
required:
- source
- title
description: NewsItem represents a single news article from RSS feed aggregation.
ThreatClassification:
type: object
properties:
level:
type: string
enum:
- THREAT_LEVEL_UNSPECIFIED
- THREAT_LEVEL_LOW
- THREAT_LEVEL_MEDIUM
- THREAT_LEVEL_HIGH
- THREAT_LEVEL_CRITICAL
description: ThreatLevel represents the assessed threat level of a news event.
category:
type: string
description: Event category.
confidence:
type: number
maximum: 1
minimum: 0
format: double
description: Confidence score (0.0 to 1.0).
source:
type: string
description: |-
Classification source — "keyword", "keyword-historical-downgrade", or
"llm".
description: ThreatClassification represents an AI-assessed threat level for a news item.
GeoCoordinates:
type: object
properties:
latitude:
type: number
maximum: 90
minimum: -90
format: double
description: Latitude in decimal degrees (-90 to 90).
longitude:
type: number
maximum: 180
minimum: -180
format: double
description: Longitude in decimal degrees (-180 to 180).
description: GeoCoordinates represents a geographic location using WGS84 coordinates.
StoryMeta:
type: object
properties:
firstSeen:
type: integer
format: int64
description: 'Epoch ms when the story first appeared in any digest cycle.. Warning: Values > 2^53 may lose precision in JavaScript'
mentionCount:
type: integer
format: int32
description: Total number of digest cycles in which this story appeared.
sourceCount:
type: integer
format: int32
description: |-
Number of unique sources reporting this story in the CURRENT digest
cycle; 1 for unclustered items.
phase:
type: string
enum:
- STORY_PHASE_UNSPECIFIED
- STORY_PHASE_BREAKING
- STORY_PHASE_DEVELOPING
- STORY_PHASE_SUSTAINED
- STORY_PHASE_FADING
description: StoryPhase represents the lifecycle stage of a tracked news story.
description: StoryMeta carries cross-cycle persistence data attached to each news item.
DigestCoverage:
type: object
properties:
state:
type: string
description: |-
complete | partial | stale | unavailable.
complete: every configured category had at least one completed eligible
feed and the build did not hit the global deadline.
partial: content exists, but a category had no completed feed or the
build hit the global deadline.
stale: accepted older content is served after a failed or gate-held attempt
(durable last-good serving, #7084).
unavailable: no eligible content could be served.
attemptedAt:
type: string
description: ISO 8601 time of the latest build attempt (attempt identity).
itemsServed:
type: integer
format: int32
description: Items served in this response, after every gate.
publisherCount:
type: integer
format: int32
description: Distinct publishers among the served items (normalized, this cycle only).
feedTotal:
type: integer
format: int32
description: |-
Eligible feeds configured for this variant+language, and how many
completed (with or without items).
feedCompleted:
type: integer
format: int32
categoryTotal:
type: integer
format: int32
description: Configured categories, and how many had at least one completed feed.
categoryCompleted:
type: integer
format: int32
categoryStates:
type: object
additionalProperties:
type: string
description: 'Per-category state: ok (a feed completed) | missing (none did).'
droppedFeedCap:
type: integer
format: int32
description: |-
Per-gate drop counts, named by gate position in the pipeline:
feed cap, undated-item, freshness floor, category cap.
droppedUndated:
type: integer
format: int32
droppedFreshness:
type: integer
format: int32
droppedCategoryCap:
type: integer
format: int32
servedStale:
type: boolean
description: |-
True when accepted older content is replayed after a failed or gate-held
attempt (#7084); counts still describe the served body.
staleAgeSeconds:
type: integer
format: int32
description: Content age since acceptance, seconds (0 when fresh, at most 21600).
staleReason:
type: string
description: 'Closed stale reason: empty-rebuild | build-error | gate-held (empty when fresh).'
itemsConsidered:
type: integer
format: int32
description: Items ranked before the category cap (served count on old replays).
publishersConsidered:
type: integer
format: int32
description: Distinct publishers among those ranked items.
description: |-
Content vs attempt state for one digest response (#7085). generated_at
keeps the CONTENT identity (when the served items were produced);
attempted_at keeps the latest BUILD identity — the two diverge when
stale content is served after a failed or gate-held attempt (#7084).
CategoryStatesEntry:
type: object
properties:
key:
type: string
value:
type: string
ListCountryHeadlinesRequest:
type: object
properties:
countryCodes:
type: array
items:
type: string
description: ISO 3166-1 alpha-2 codes. Repeated query parameter, at most 250 countries.
maxItems: 250
minItems: 1
required:
- countryCodes
description: ListCountryHeadlinesRequest selects countries from the full English RSS pool.
ListCountryHeadlinesResponse:
type: object
properties:
countries:
type: object
additionalProperties:
$ref: '#/components/schemas/CountryHeadlineBucket'
description: Requested country codes with matching headlines; absent countries had no match.
state:
type: string
description: complete | partial | unavailable. A failed revocation read is unavailable.
feedTotal:
type: integer
format: int32
description: Configured full-variant feeds reachable from the English digest.
feedCached:
type: integer
format: int32
description: Feeds whose parsed cache was available, including cached empty feeds.
readAt:
type: string
description: Time the caches were read; article freshness is determined by published_at.
description: ListCountryHeadlinesResponse describes cache availability independently of country matches.
CountriesEntry:
type: object
properties:
key:
type: string
value:
$ref: '#/components/schemas/CountryHeadlineBucket'
CountryHeadlineBucket:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/CountryHeadline'
maxItems: 5
description: CountryHeadlineBucket contains at most five distinct article URLs.
CountryHeadline:
type: object
properties:
source:
type: string
description: 'Publisher name: trusted origin publisher or registered feed name.'
title:
type: string
description: Headline that names the requested country.
link:
type: string
description: HTTPS article URL.
publishedAt:
type: integer
format: int64
description: 'Publisher publication time in Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
description: CountryHeadline is a dated article from a configured RSS feed, before dashboard category caps.
ListMediaPerspectiveRequest:
type: object
properties:
subjectCountry:
type: string
maxLength: 2
minLength: 2
description: ISO2.
outletCountries:
type: array
items:
type: string
maxItems: 30
description: ISO2, at most 30.
maxItems: 30
audience:
type: string
description: domestic, international or diaspora.
"windowHours":
"type": "integer"
"format": "int32"
"description": "24, 48, 72 or 96."
"enum":
- 0
- 24
- 48
- 72
- 96
outletRegions:
type: array
items:
type: string
maxItems: 5
description: UN M49 region slugs, e.g. northern-europe.
maxItems: 5
required:
- subjectCountry
ListMediaPerspectiveResponse:
type: object
properties:
subjectCountry:
type: string
windowHours:
type: integer
format: int32
groups:
type: array
items:
$ref: '#/components/schemas/MediaPerspectiveGroup'
noCoverageCountries:
type: array
items:
type: string
unattributedCount:
type: integer
format: int32
description: No outlet profile or multi-publisher feed.
state:
type: string
description: complete, partial or unavailable.
feedTotal:
type: integer
format: int32
feedCached:
type: integer
format: int32
readAt:
type: string
MediaPerspectiveGroup:
type: object
properties:
homeCountry:
type: string
audience:
type: string
outletCount:
type: integer
format: int32
description: Publisher families.
headlineCount:
type: integer
format: int32
description: Before the 20-headline cap.
framing:
$ref: '#/components/schemas/MediaPerspectiveFramingCounts'
headlines:
type: array
items:
$ref: '#/components/schemas/MediaPerspectiveHeadline'
maxItems: 20
MediaPerspectiveFramingCounts:
type: object
properties:
favorable:
type: integer
format: int32
neutral:
type: integer
format: int32
critical:
type: integer
format: int32
hostile:
type: integer
format: int32
unlabeled:
type: integer
format: int32
method:
type: string
description: e.g. llm-headline-stance.
model:
type: string
promptVersion:
type: string
MediaPerspectiveHeadline:
type: object
properties:
title:
type: string
englishTitle:
type: string
description: Machine translation unless English; untrusted.
titleLanguage:
type: string
outlet:
type: string
publisherFamily:
type: string
tier:
type: integer
format: int32
ownershipClass:
type: string
stateAffiliated:
type: string
propagandaRisk:
type: string
framing:
type: string
description: favorable, neutral, critical or hostile.
publishedAt:
type: integer
format: int64
description: 'Warning: Values > 2^53 may lose precision in JavaScript'
link:
type: string
ListNewsPoolRequest:
type: object
properties:
languages:
type: array
items:
type: string
maxItems: 8
description: Content languages (ISO 639-1), at most 8. Empty means en.
maxItems: 8
editions:
type: array
items:
type: string
maxItems: 8
description: Digest editions, e.g. full, tech, finance. Empty means full.
maxItems: 8
category:
type: string
maxLength: 32
description: One category key within the selected editions.
ListNewsPoolResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/NewsPoolItem'
cells:
type: array
items:
$ref: '#/components/schemas/NewsPoolCell'
state:
type: string
description: complete, partial, stale or unavailable.
generatedAt:
type: string
NewsPoolItem:
type: object
properties:
item:
$ref: '#/components/schemas/NewsItem'
language:
type: string
description: ISO 639-1 content language of the outlet. Titles are untranslated.
editions:
type: array
items:
type: string
description: Editions that carry this article, in catalog order.
category:
type: string
NewsPoolCell:
type: object
properties:
edition:
type: string
language:
type: string
state:
type: string
description: |-
English digest cell: complete or partial (a fresh build), stale (a
last-good replay), or missing. Other languages: complete (every feed
cached), partial (some), or missing (none).
items:
type: integer
format: int32
description: Items this cell contributed after the language and category filters.
staleAgeSeconds:
type: integer
format: int32
generatedAt:
type: string
ListSourceItemsRequest:
type: object
properties:
editions:
type: array
items:
type: string
maxItems: 8
description: |-
Digest editions to look for each source in, in order, e.g. full, tech.
Empty means full.
maxItems: 8
category:
type: string
maxLength: 32
minLength: 1
description: One category key within the selected editions.
sources:
type: array
items:
type: string
maxItems: 24
minItems: 1
description: |-
Catalog source names, at most 24, each at most 120 characters. Order and
duplicates do not matter.
maxItems: 24
minItems: 1
lang:
type: string
maxLength: 8
description: |-
ISO 639-1 language code of a supported digest language (en, fr, ar, etc.);
empty means en. Unsupported codes are rejected with 400. Only sources this
language's digest fetches are read.
required:
- category
- sources
ListSourceItemsResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/NewsItem'
maxItems: 72
sources:
type: array
items:
$ref: '#/components/schemas/SourceItemsState'
maxItems: 24
generatedAt:
type: string
SourceItemsState:
type: object
properties:
source:
type: string
state:
type: string
description: |-
found (a cached parse), missing (no healthy cached parse), or unplaced
(no requested edition's digest in this language fetches the source in
the category).
edition:
type: string
description: Edition whose cached parse was read; empty unless found.
items:
type: integer
format: int32
ListLabelChangesRequest:
type: object
properties:
storyId:
type: string
maxLength: 64
description: Story identity hash (64 hex characters). Empty lists changes across all stories.
limit:
type: integer
maximum: 200
minimum: 0
format: int32
description: Maximum changes returned, newest first. 0 uses the default of 50; at most 200.
description: ListLabelChangesRequest selects recent corroboration label changes, optionally for one story.
ListLabelChangesResponse:
type: object
properties:
changes:
type: array
items:
$ref: '#/components/schemas/LabelChange'
state:
type: string
description: ok | unavailable. Unavailable means the log could not be read, not that it is empty.
retentionDays:
type: integer
format: int32
description: Retention window in days.
counts:
$ref: '#/components/schemas/LabelCounts'
description: ListLabelChangesResponse lists changes from the last seven days, newest first.
LabelChange:
type: object
properties:
storyId:
type: string
description: Story identity hash; empty for a correction that names no story.
field:
type: string
description: corroboration (a label moved) | correction (an accepted reader report).
previous:
type: string
description: 'Previous state: single-publisher | corroborated; empty for a correction.'
next:
type: string
description: 'New state: single-publisher | corroborated; empty for a correction.'
previousPublishers:
type: integer
format: int32
description: Publisher families behind the previous label; 0 for a correction.
nextPublishers:
type: integer
format: int32
description: Publisher families behind the new label; 0 for a correction.
at:
type: integer
format: int64
description: 'Time the change was recorded, Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
trigger:
type: string
description: 'What recorded it: digest (automatic) | report (an accepted error report).'
reason:
type: string
description: Plain-language reason, in English.
sources:
type: array
items:
$ref: '#/components/schemas/LabelChangePublisher'
title:
type: string
description: Story headline when the change was recorded.
link:
type: string
description: |-
Representative article URL. Empty when it failed the publisher link gate,
was revoked after the change was recorded, or the revocation set could not
be read.
credibilityScore:
type: integer
format: int32
description: Story CRED score 0-100 when the change was recorded; -1 when unknown.
description: |-
LabelChange records one story moving between single-publisher and corroborated
coverage, or one correction a reviewer accepted from a reader report.
LabelChangePublisher:
type: object
properties:
name:
type: string
description: Curated publisher name, or the feed label when no family is curated.
tier:
type: integer
format: int32
description: Declared source tier 1-4; 0 when no feed label declares one.
description: LabelChangePublisher is one publisher family behind the new label.
LabelCounts:
type: object
properties:
at:
type: integer
format: int64
description: 'When the digest counted, Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
stories:
type: integer
format: int32
description: Stories counted.
corroborated:
type: integer
format: int32
description: Two or more publisher families, not all tier 4.
singlePublisher:
type: integer
format: int32
description: One publisher family.
tier4Only:
type: integer
format: int32
description: Two or more families, every one a declared tier-4 outlet.
unknown:
type: integer
format: int32
description: No evidence to judge.
description: LabelCounts is how many stories in the latest full English digest carry each label.
SubmitErrorReportRequest:
type: object
properties:
message:
type: string
maxLength: 2000
minLength: 10
description: What is wrong, in the reader's words.
storyId:
type: string
maxLength: 64
description: Story identity hash the report concerns, when known (64 hex characters).
url:
type: string
maxLength: 2048
description: Article or WorldMonitor URL the report concerns, when known.
contact:
type: string
maxLength: 320
description: Optional email for a reply. Never published.
website:
type: string
description: 'Honeypot. Leave empty: a filled value is accepted and discarded.'
description: SubmitErrorReportRequest is a reader's report that a WorldMonitor label or story is wrong. Stored for review; never applied automatically.
SubmitErrorReportResponse:
type: object
properties:
status:
type: string
description: received | queue-full.
reportId:
type: string
description: Report id, empty unless received.
description: SubmitErrorReportResponse acknowledges a stored report.
ListErrorReportsRequest:
type: object
properties:
status:
type: string
maxLength: 16
description: pending (default) | reviewed.
description: ListErrorReportsRequest selects reports for review. Requires the X-Trust-Review-Key header.
ListErrorReportsResponse:
type: object
properties:
reports:
type: array
items:
$ref: '#/components/schemas/ErrorReport'
state:
type: string
description: ok | unavailable.
description: ListErrorReportsResponse lists reports, oldest pending first or newest reviewed first.
ErrorReport:
type: object
properties:
id:
type: string
description: Report id.
status:
type: string
description: pending | accepted | rejected.
message:
type: string
description: Reader's message.
storyId:
type: string
description: Story identity hash, if given.
url:
type: string
description: URL, if given.
contact:
type: string
description: Reply email, if given.
createdAt:
type: integer
format: int64
description: 'Submission time, Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
reviewedAt:
type: integer
format: int64
description: 'Review time, Unix epoch milliseconds; 0 while pending.. Warning: Values > 2^53 may lose precision in JavaScript'
publicNote:
type: string
description: Operator's public note, published with an accepted report.
description: ErrorReport is one stored report as an operator sees it.
ReviewErrorReportRequest:
type: object
properties:
reportId:
type: string
maxLength: 64
minLength: 1
description: Report id.
decision:
type: string
maxLength: 16
description: accept | reject.
publicNote:
type: string
maxLength: 500
description: 'Public note. Required to accept: it is what the label log publishes.'
description: ReviewErrorReportRequest accepts or rejects one report. Requires the X-Trust-Review-Key header.
ReviewErrorReportResponse:
type: object
properties:
report:
$ref: '#/components/schemas/ErrorReport'
description: ReviewErrorReportResponse returns the reviewed report.
SearchFactChecksRequest:
type: object
properties:
claim:
type: string
maxLength: 300
description: The claim or headline, up to 300 characters.
description: SearchFactChecksRequest names the claim to look up published fact-checks for.
SearchFactChecksResponse:
type: object
properties:
factChecks:
type: array
items:
$ref: '#/components/schemas/FactCheck'
state:
type: string
description: ok | unavailable | not-configured. Only ok means the search ran; an empty list is then no published fact-check found.
caveat:
type: string
description: Fixed reminder that ratings are the fact-checkers' own and never change the coverage result.
description: SearchFactChecksResponse lists published fact-checks of claims similar to the one searched.
FactCheck:
type: object
properties:
publisher:
type: string
description: The fact-checker's name as it publishes it.
site:
type: string
description: The IFCN-allowlisted domain the link belongs to.
rating:
type: string
description: The fact-checker's own rating, verbatim. WorldMonitor does not rate claims.
reviewedAt:
type: string
description: When the fact-check was published, ISO 8601.
url:
type: string
description: Link to the fact-check.
title:
type: string
description: The fact-check's headline; empty when the feed gives none.
claimReviewed:
type: string
description: 'The claim the fact-checker rated: similar to the claim searched, not necessarily the same.'
description: FactCheck is one rating an IFCN-verified fact-checker published about a similar claim, cited with attribution.
SearchClaimHeadlinesRequest:
type: object
properties:
claim:
type: string
maxLength: 300
description: The claim or headline, up to 300 characters. Empty returns only the counts.
description: SearchClaimHeadlinesRequest names the claim to search fresh headlines for.
SearchClaimHeadlinesResponse:
type: object
properties:
headlines:
type: array
items:
$ref: '#/components/schemas/ClaimHeadline'
searchedHeadlines:
type: integer
format: int32
description: Fresh headlines searched.
searchedFeeds:
type: integer
format: int32
description: Feeds those headlines came from.
feedTotal:
type: integer
format: int32
description: Configured full-variant English feeds.
feedCached:
type: integer
format: int32
description: Feeds whose parsed cache was available.
state:
type: string
description: complete | partial | unavailable. Unavailable searched nothing.
readAt:
type: string
description: When the feed caches were read, ISO 8601.
description: SearchClaimHeadlinesResponse holds the headlines that share the claim's words, for building its coverage card.
ClaimHeadline:
type: object
properties:
source:
type: string
description: Registered feed name.
title:
type: string
link:
type: string
description: Article URL; empty when the ingest gate removed it.
publishedAt:
type: integer
format: int64
description: 'Publication time in Unix epoch milliseconds.. Warning: Values > 2^53 may lose precision in JavaScript'
description: ClaimHeadline is one fresh headline from a configured feed.