{
  "openapi": "3.1.0",
  "info": {
    "title": "EarlyWave API",
    "version": "1.1.0",
    "description": "Read your feeds, articles, folders, saved items and monitors, and the trends EarlyWave detects across every source it reads.\n\n**Authentication.** Send your key in the `Authorization` header: `Authorization: Bearer ew_live_…`. Create keys in EarlyWave › Settings › API & MCP. A key carries scopes: `rest` for this API, `mcp` for the MCP server.\n\n**Rate limit and monthly quota.** Two counters per account, shared by every key, REST and MCP together: a fixed one-minute window and a calendar-month quota (UTC). Pro: 60 requests a minute and 10,000 a month; Max: 300 a minute and 50,000 a month. Every response carries `X-RateLimit-*` (minute) and `X-Quota-*` (month) headers; over either limit you get `429` with `error.type = \"rate_limit\"` and a `Retry-After` header — `error.code` says which counter refused: `rate_limit_exceeded` for the minute, `quota_exceeded` for the month (it resets on the 1st).\n\n**Errors.** Always `{\"error\": {\"type\", \"code\", \"message\"}}`. `type` is one of `invalid_request` (400), `authentication` (401), `permission` (403), `not_found` (404), `rate_limit` (429), `server` (500).\n\n**Paging.** Lists take `limit` (1–100, default 20) and `offset`, and answer `has_more`.\n\n**Same data over MCP.** Each operation is also an MCP tool (`x-mcp-tool`) on `https://api.earlywave.ai/mcp`.",
    "contact": {
      "name": "EarlyWave",
      "url": "https://www.earlywave.ai/developers"
    }
  },
  "servers": [
    {
      "url": "https://api.earlywave.ai/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Trends",
      "description": "Stories detected across every source EarlyWave reads."
    },
    {
      "name": "Monitors",
      "description": "Your monitors and what they found."
    },
    {
      "name": "Feeds",
      "description": "Your subscriptions and the feed catalogue."
    },
    {
      "name": "Folders",
      "description": "Your feed folders and their articles."
    },
    {
      "name": "Articles",
      "description": "Articles of your feeds."
    },
    {
      "name": "Saved",
      "description": "Articles, pages and searches you saved."
    },
    {
      "name": "Discover",
      "description": "Recent articles and keywords across every source."
    }
  ],
  "paths": {
    "/feeds": {
      "get": {
        "operationId": "listFeeds",
        "summary": "List your subscribed feeds",
        "description": "Lists the RSS feeds the account is subscribed to, optionally filtered by a keyword (title, description, address) or a domain.",
        "tags": [
          "Feeds"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Keyword matched against title, description and feed address.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "description": "Domain the feed address contains, e.g. \"lemonde.fr\".",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List your subscribed feeds",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "find_feeds"
      }
    },
    "/feeds/discover": {
      "get": {
        "operationId": "discoverFeeds",
        "summary": "Search the feed catalogue",
        "description": "Searches every feed EarlyWave reads (not only your subscriptions), most-followed first.",
        "tags": [
          "Feeds"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Keyword (at least 2 characters) matched against the title, the description and the publisher's domain.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Feed language code, e.g. \"fr\".",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 10
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Publisher country, ISO alpha-2 (\"FR\") or alpha-3 (\"FRA\").",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 3
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search the feed catalogue",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedDiscoveryList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "discover_feeds"
      }
    },
    "/feeds/{feed_id}": {
      "get": {
        "operationId": "getFeed",
        "summary": "Get one of your feeds",
        "description": "Details of a feed you are subscribed to, with its 24-hour and 7-day article counts.",
        "tags": [
          "Feeds"
        ],
        "parameters": [
          {
            "name": "feed_id",
            "in": "path",
            "required": true,
            "description": "Feed ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get one of your feeds",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedDetail"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_feed"
      }
    },
    "/feeds/{feed_id}/items": {
      "get": {
        "operationId": "listFeedItems",
        "summary": "List a feed's articles",
        "description": "Articles of one of your feeds, newest first.",
        "tags": [
          "Feeds"
        ],
        "parameters": [
          {
            "name": "feed_id",
            "in": "path",
            "required": true,
            "description": "Feed ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a feed's articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedItemList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_feed_items"
      }
    },
    "/categories": {
      "get": {
        "operationId": "listFolders",
        "summary": "List your folders",
        "description": "Your feed folders, with the number of feeds in each.",
        "tags": [
          "Folders"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List your folders",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_categories"
      }
    },
    "/categories/{category_id}/items": {
      "get": {
        "operationId": "listFolderItems",
        "summary": "List a folder's articles",
        "description": "Articles from the feeds of one of your folders, newest first.",
        "tags": [
          "Folders"
        ],
        "parameters": [
          {
            "name": "category_id",
            "in": "path",
            "required": true,
            "description": "Folder ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a folder's articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderItemList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_category_items"
      }
    },
    "/items": {
      "get": {
        "operationId": "listItems",
        "summary": "List all your articles",
        "description": "Articles from all your feeds, newest first.",
        "tags": [
          "Folders"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List all your articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_all_items"
      }
    },
    "/articles/search": {
      "get": {
        "operationId": "searchArticles",
        "summary": "Search your articles",
        "description": "Articles of your feeds whose title, description, summary or keywords contain the query, newest first.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Text to search for.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search your articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleSearchList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "search_articles"
      }
    },
    "/articles/{article_id}": {
      "get": {
        "operationId": "getArticle",
        "summary": "Get an article",
        "description": "One article from your feeds, with its text (up to 10,000 characters), summary and keywords.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "name": "article_id",
            "in": "path",
            "required": true,
            "description": "Article ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get an article",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Article"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_article"
      }
    },
    "/trends": {
      "get": {
        "operationId": "listTrends",
        "summary": "List trends",
        "description": "Stories EarlyWave detects across every source it reads, strongest signal first. Filter by category, stage, the country a story is about, the country of its publishers, reach, or how recently it started.",
        "tags": [
          "Trends"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Words the trend title contains.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Comma-separated: ai, tech, business, economy, crypto, cyber, geopolitics, politics, energy, climate, health, science, space, society, sports, cinema, people, music, world.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            }
          },
          {
            "name": "stage",
            "in": "query",
            "required": false,
            "description": "Comma-separated: emerging, accelerating, breakout.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Country the story is about, ISO alpha-2 (e.g. \"FR\").",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 2
            }
          },
          {
            "name": "publisher_country",
            "in": "query",
            "required": false,
            "description": "Country with at least 2 sources covering it, ISO alpha-2.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 2
            }
          },
          {
            "name": "reach",
            "in": "query",
            "required": false,
            "description": "Comma-separated: local, national, international, global.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "since_hours",
            "in": "query",
            "required": false,
            "description": "Only stories that started within this many hours (1–720).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 720
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "signal (default), recent (last activity) or sources.",
            "schema": {
              "default": "signal",
              "type": "string",
              "enum": [
                "signal",
                "recent",
                "sources"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List trends",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrendList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_trends"
      }
    },
    "/trends/{trend_id}": {
      "get": {
        "operationId": "getTrend",
        "summary": "Get a trend",
        "description": "A trend with its summary, countries, languages, entities, keywords and its 10 latest articles.",
        "tags": [
          "Trends"
        ],
        "parameters": [
          {
            "name": "trend_id",
            "in": "path",
            "required": true,
            "description": "Trend ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a trend",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrendDetail"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_trend"
      }
    },
    "/trends/{trend_id}/articles": {
      "get": {
        "operationId": "listTrendArticles",
        "summary": "List a trend's articles",
        "description": "Every article of a trend with its source (title, site, country), newest or oldest first.",
        "tags": [
          "Trends"
        ],
        "parameters": [
          {
            "name": "trend_id",
            "in": "path",
            "required": true,
            "description": "Trend ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "latest (default) or oldest first.",
            "schema": {
              "default": "latest",
              "type": "string",
              "enum": [
                "latest",
                "oldest"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a trend's articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrendArticleList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_trend_articles"
      }
    },
    "/trends/{trend_id}/coverage": {
      "get": {
        "operationId": "getTrendCoverage",
        "summary": "Get where a trend is covered",
        "description": "Publisher countries and languages of a trend (sources = distinct sites) and its last 7 days hour by hour.",
        "tags": [
          "Trends"
        ],
        "parameters": [
          {
            "name": "trend_id",
            "in": "path",
            "required": true,
            "description": "Trend ID.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get where a trend is covered",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrendCoverage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_trend_coverage"
      }
    },
    "/monitors": {
      "get": {
        "operationId": "listMonitors",
        "summary": "List your monitors",
        "description": "Your monitors (archived ones excluded), with their counts and next check.",
        "tags": [
          "Monitors"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List your monitors",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_monitors"
      }
    },
    "/monitors/{monitor_id}/results": {
      "get": {
        "operationId": "getMonitorResults",
        "summary": "Get a monitor's results",
        "description": "What a monitor found over the last days (newest first), with its sources and the current answers to its questions.",
        "tags": [
          "Monitors"
        ],
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "description": "Monitor ID (from list_monitors / GET /monitors).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Period in days (1–90, default 30).",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": 1,
              "maximum": 90
            }
          },
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Only results containing this text.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a monitor's results",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResults"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (or not yours).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_monitor_results"
      }
    },
    "/saved": {
      "get": {
        "operationId": "listSaved",
        "summary": "List your saved items",
        "description": "Articles, pages and searches you saved, newest first.",
        "tags": [
          "Saved"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "article, url or search; all when omitted.",
            "schema": {
              "type": "string",
              "enum": [
                "article",
                "url",
                "search"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List your saved items",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_saved"
      }
    },
    "/discover": {
      "get": {
        "operationId": "discoverItems",
        "summary": "Search all recent articles",
        "description": "Recent articles from every source EarlyWave reads (not only your feeds), by keywords or latest first.",
        "tags": [
          "Discover"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Comma-separated keywords; latest articles when omitted.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Article language code, e.g. \"en\".",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 10
            }
          },
          {
            "name": "hours_back",
            "in": "query",
            "required": false,
            "description": "Look-back window in hours (1–168, default 24).",
            "schema": {
              "default": 24,
              "type": "integer",
              "minimum": 1,
              "maximum": 168
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Results to skip, for paging (at most 5000).",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 5000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search all recent articles",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoverItemList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "discover_items"
      }
    },
    "/discover/keywords": {
      "get": {
        "operationId": "discoverKeywords",
        "summary": "Top keywords",
        "description": "The most frequent keywords, entities, themes or places in recent articles.",
        "tags": [
          "Discover"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "main_keywords, entities, themes, locations or all (default).",
            "schema": {
              "default": "all",
              "type": "string",
              "enum": [
                "main_keywords",
                "entities",
                "themes",
                "locations",
                "all"
              ]
            }
          },
          {
            "name": "hours_back",
            "in": "query",
            "required": false,
            "description": "Look-back window in hours (1–168, default 24).",
            "schema": {
              "default": 24,
              "type": "integer",
              "minimum": 1,
              "maximum": 168
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100, default 20).",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Top keywords",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Unix time (seconds) when the minute window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Requests allowed this calendar month (-1 on a contract without a monthly limit).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Requests left this month.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Reset": {
                "description": "Unix time (seconds) of the 1st of next month, when the monthly quota resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Identifier of the request, to quote when reporting a problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the `rest` scope, or the account does not include API access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (`rate_limit_exceeded`, the minute window) or monthly quota exceeded (`quota_exceeded`, resets on the 1st); `Retry-After` says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "discover_top_keywords"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key with the `rest` scope (`ew_live_…`)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "authentication",
                  "permission",
                  "not_found",
                  "rate_limit",
                  "server"
                ],
                "description": "Stable error family."
              },
              "code": {
                "type": "string",
                "description": "Finer reason, e.g. `trend_not_found`, `missing_api_key`."
              },
              "message": {
                "type": "string"
              },
              "details": {}
            },
            "required": [
              "type",
              "code",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "description": "Every error has this shape."
      },
      "Feed": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "feed_url": {
            "type": "string"
          },
          "website_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "description": {
            "type": "string"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Publisher country, ISO 3166-1 alpha-2."
          },
          "subscribers": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "items_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "latest_fetch": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "title",
          "feed_url",
          "website_url",
          "description",
          "language",
          "country",
          "subscribers",
          "items_count",
          "latest_fetch"
        ],
        "additionalProperties": false
      },
      "FeedDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "feed_url": {
            "type": "string"
          },
          "website_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "description": {
            "type": "string"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Publisher country, ISO 3166-1 alpha-2."
          },
          "subscribers": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "items_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "latest_fetch": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feed_broken": {
            "type": "boolean"
          },
          "items_count_24h": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "items_count_7d": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "title",
          "feed_url",
          "website_url",
          "description",
          "language",
          "country",
          "subscribers",
          "items_count",
          "latest_fetch",
          "feed_broken",
          "items_count_24h",
          "items_count_7d"
        ],
        "additionalProperties": false
      },
      "FeedList": {
        "type": "object",
        "properties": {
          "feeds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feed"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "feeds",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "FeedDiscoveryList": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "feeds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feed"
            }
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "query",
          "feeds",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "ArticleSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "preview": {
            "type": "string",
            "description": "Summary or description, up to 500 characters."
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "published": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feed_id": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "preview",
          "image_url",
          "author",
          "published",
          "feed_id"
        ],
        "additionalProperties": false
      },
      "Article": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "preview": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "Article text, up to 10,000 characters."
          },
          "keywords": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "published": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feed_id": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "preview",
          "content",
          "keywords",
          "image_url",
          "author",
          "language",
          "published",
          "feed_id"
        ],
        "additionalProperties": false
      },
      "FeedItemList": {
        "type": "object",
        "properties": {
          "feed_id": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArticleSummary"
            }
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "feed_id",
          "items",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "ArticleSearchList": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "articles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArticleSummary"
            }
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "query",
          "articles",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "Folder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "feed_count": {
            "type": "integer"
          },
          "is_frozen": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "feed_count",
          "is_frozen"
        ],
        "additionalProperties": false
      },
      "FolderList": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Folder"
            }
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "categories",
          "total"
        ],
        "additionalProperties": false
      },
      "FolderItemList": {
        "type": "object",
        "properties": {
          "category": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArticleSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "category",
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "ItemList": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArticleSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "Trend": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "The trend page on earlywave.ai."
          },
          "status": {
            "type": "string"
          },
          "stage": {
            "type": "string",
            "description": "emerging | accelerating | breakout"
          },
          "category": {
            "type": "string"
          },
          "reach": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "local | national | international | global (null = not computed yet)."
          },
          "subject_countries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Countries the story is about (alpha-2)."
          },
          "publisher_countries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Countries with at least 2 publishing sources (alpha-2)."
          },
          "item_count": {
            "type": "integer",
            "description": "Articles."
          },
          "source_count": {
            "type": "integer",
            "description": "Distinct sources (domains)."
          },
          "signal_score": {
            "type": "number"
          },
          "velocity_1h": {
            "type": "number",
            "description": "Articles in the last hour."
          },
          "velocity_24h": {
            "type": "number",
            "description": "Articles in the last 24 hours."
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "Story start: earliest trusted article."
          },
          "earliest_item_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "When EarlyWave grouped the story."
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "status",
          "stage",
          "category",
          "reach",
          "subject_countries",
          "publisher_countries",
          "item_count",
          "source_count",
          "signal_score",
          "velocity_1h",
          "velocity_24h",
          "started_at",
          "earliest_item_at",
          "first_seen_at",
          "last_activity_at"
        ],
        "additionalProperties": false
      },
      "TrendDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "The trend page on earlywave.ai."
          },
          "status": {
            "type": "string"
          },
          "stage": {
            "type": "string",
            "description": "emerging | accelerating | breakout"
          },
          "category": {
            "type": "string"
          },
          "reach": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "local | national | international | global (null = not computed yet)."
          },
          "subject_countries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Countries the story is about (alpha-2)."
          },
          "publisher_countries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Countries with at least 2 publishing sources (alpha-2)."
          },
          "item_count": {
            "type": "integer",
            "description": "Articles."
          },
          "source_count": {
            "type": "integer",
            "description": "Distinct sources (domains)."
          },
          "signal_score": {
            "type": "number"
          },
          "velocity_1h": {
            "type": "number",
            "description": "Articles in the last hour."
          },
          "velocity_24h": {
            "type": "number",
            "description": "Articles in the last 24 hours."
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "Story start: earliest trusted article."
          },
          "earliest_item_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "When EarlyWave grouped the story."
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time"
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "regions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "publisher_languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "top_entities": {},
          "top_keywords": {},
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "published": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "id",
                "title",
                "url",
                "published"
              ],
              "additionalProperties": false
            },
            "description": "The 10 most recently attached articles; all of them: /trends/{trend_id}/articles."
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "status",
          "stage",
          "category",
          "reach",
          "subject_countries",
          "publisher_countries",
          "item_count",
          "source_count",
          "signal_score",
          "velocity_1h",
          "velocity_24h",
          "started_at",
          "earliest_item_at",
          "first_seen_at",
          "last_activity_at",
          "summary",
          "regions",
          "publisher_languages",
          "top_entities",
          "top_keywords",
          "sources"
        ],
        "additionalProperties": false
      },
      "TrendList": {
        "type": "object",
        "properties": {
          "trends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Trend"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "trends",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "TrendArticle": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "preview": {
            "type": "string",
            "description": "Summary or description, up to 500 characters."
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "published": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feed_id": {
            "type": "integer"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "type": "object",
            "properties": {
              "feed_id": {
                "type": "integer"
              },
              "title": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "website_url": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "country": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Alpha-2."
              }
            },
            "required": [
              "feed_id",
              "title",
              "website_url",
              "country"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "preview",
          "image_url",
          "author",
          "published",
          "feed_id",
          "language",
          "source"
        ],
        "additionalProperties": false
      },
      "TrendArticleList": {
        "type": "object",
        "properties": {
          "trend_id": {
            "type": "integer"
          },
          "articles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TrendArticle"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "trend_id",
          "articles",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "TrendCoverage": {
        "type": "object",
        "properties": {
          "trend_id": {
            "type": "integer"
          },
          "total_articles": {
            "type": "integer"
          },
          "total_sources": {
            "type": "integer"
          },
          "first_article_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "peak_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "country": {
                  "type": "string",
                  "description": "Publisher country, alpha-2."
                },
                "sources": {
                  "type": "integer"
                },
                "articles": {
                  "type": "integer"
                },
                "first_article_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "peak_hour": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": [
                "country",
                "sources",
                "articles",
                "first_article_at",
                "peak_hour"
              ],
              "additionalProperties": false
            },
            "description": "Every publisher country, most sources first."
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "language": {
                  "type": "string"
                },
                "sources": {
                  "type": "integer"
                },
                "articles": {
                  "type": "integer"
                }
              },
              "required": [
                "language",
                "sources",
                "articles"
              ],
              "additionalProperties": false
            }
          },
          "series": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string",
                "format": "date-time",
                "description": "Start of the first hourly bucket."
              },
              "step_minutes": {
                "type": "integer"
              },
              "articles": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "sources": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "Distinct sources publishing in the hour."
              },
              "new_sources": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "Sources seen for the first time in the story in the hour."
              }
            },
            "required": [
              "start",
              "step_minutes",
              "articles",
              "sources",
              "new_sources"
            ],
            "additionalProperties": false,
            "description": "The last 7 days, hour by hour (168 buckets)."
          }
        },
        "required": [
          "trend_id",
          "total_articles",
          "total_sources",
          "first_article_at",
          "peak_at",
          "countries",
          "languages",
          "series"
        ],
        "additionalProperties": false
      },
      "Monitor": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "form": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "results_count": {
            "type": "integer"
          },
          "articles_count": {
            "type": "integer"
          },
          "last_check_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_check_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_result_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "conversation_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "cadence": {},
          "delivery_mode": {
            "type": "string"
          },
          "calm_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "form",
          "status",
          "icon",
          "results_count",
          "articles_count",
          "last_check_at",
          "next_check_at",
          "last_result_at",
          "created_at",
          "updated_at",
          "conversation_ref",
          "cadence",
          "delivery_mode",
          "calm_since"
        ],
        "additionalProperties": false
      },
      "MonitorList": {
        "type": "object",
        "properties": {
          "monitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Monitor"
            }
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "monitors",
          "total"
        ],
        "additionalProperties": false
      },
      "MonitorResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "title": {
            "type": "string"
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "event_date": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "fields": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "confidence": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "cluster_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "sources_count": {
            "type": "integer"
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "hidden_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feedback": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "item_id": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "url": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "title": {
                  "type": "string"
                },
                "publisher": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "published_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "excerpt": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "provenance": {
                  "type": "string"
                }
              },
              "required": [
                "item_id",
                "url",
                "title",
                "publisher",
                "published_at",
                "excerpt",
                "provenance"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id",
          "kind",
          "type",
          "title",
          "summary",
          "event_date",
          "fields",
          "confidence",
          "cluster_id",
          "sources_count",
          "first_seen_at",
          "updated_at",
          "hidden_at",
          "feedback",
          "sources"
        ],
        "additionalProperties": false
      },
      "MonitorResults": {
        "type": "object",
        "properties": {
          "monitor": {
            "$ref": "#/components/schemas/Monitor"
          },
          "period_days": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MonitorResult"
            }
          },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "changed_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "question",
                "answer",
                "changed_at"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "monitor",
          "period_days",
          "total",
          "limit",
          "has_more",
          "results",
          "answers"
        ],
        "additionalProperties": false
      },
      "SavedEntry": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "article",
              "url",
              "search"
            ]
          },
          "id": {
            "type": "integer"
          },
          "source_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "title": {
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview": {
            "type": "string"
          },
          "saved_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "type",
          "id",
          "source_id",
          "title",
          "url",
          "preview",
          "saved_at"
        ],
        "additionalProperties": false
      },
      "SavedList": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "saved": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SavedEntry"
            }
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "type",
          "saved",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "DiscoverItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview": {
            "type": "string"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "published": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "feed": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "site_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "icon_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "id",
                  "title",
                  "site_url",
                  "icon_url"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "match_source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where the query matched (keywords, title, description); null without a query."
          }
        },
        "required": [
          "id",
          "title",
          "url",
          "preview",
          "image_url",
          "author",
          "language",
          "published",
          "feed",
          "match_source"
        ],
        "additionalProperties": false
      },
      "DiscoverItemList": {
        "type": "object",
        "properties": {
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "hours_back": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiscoverItem"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "Page size used."
          },
          "offset": {
            "type": "integer",
            "description": "Results skipped."
          },
          "has_more": {
            "type": "boolean",
            "description": "True when another page exists (call again with offset + limit)."
          }
        },
        "required": [
          "query",
          "language",
          "hours_back",
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "additionalProperties": false
      },
      "KeywordList": {
        "type": "object",
        "properties": {
          "hours_back": {
            "type": "integer"
          },
          "type": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "keyword": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "types": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "required": [
                "keyword",
                "count",
                "types"
              ],
              "additionalProperties": false
            }
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "hours_back",
          "type",
          "keywords",
          "total"
        ],
        "additionalProperties": false
      }
    }
  }
}
