{
  "openapi": "3.1.0",
  "info": {
    "title": "Crypto News Aggregator",
    "description": "Real-time crypto news aggregation across major RSS sources with trending topics, per-coin filtering, full-text search, and keyword sentiment scoring. Pay-per-call over the MPP protocol on Tempo (USDC.e).",
    "version": "1.0.0"
  },
  "servers": [{ "url": "https://cryptonews.ivan-tempo.xyz" }],
  "paths": {
    "/api/news/latest": {
      "get": {
        "operationId": "getLatest",
        "summary": "Recent headlines",
        "description": "Freshest headlines aggregated across all indexed crypto RSS feeds, deduped and sorted newest first.",
        "parameters": [
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }, "description": "Number of articles to return." }
        ],
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.01",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 10000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "List of recent articles." },
          "402": { "description": "Payment required." }
        }
      }
    },
    "/api/news/trending": {
      "get": {
        "operationId": "getTrending",
        "summary": "Trending topics (24h)",
        "description": "Top coins and keywords by frequency across headlines from the last 24 hours.",
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.01",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 10000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "Trending coins and keywords." },
          "402": { "description": "Payment required." }
        }
      }
    },
    "/api/news/coin": {
      "get": {
        "operationId": "getCoinNews",
        "summary": "News by coin",
        "description": "Articles mentioning a specific coin by ticker or name in the headline or description.",
        "parameters": [
          { "name": "coin", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Coin ticker or name, e.g. BTC or bitcoin." },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30 }, "description": "Number of articles to return." }
        ],
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.01",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 10000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "Articles for the requested coin." },
          "400": { "description": "Missing coin parameter." },
          "402": { "description": "Payment required." }
        }
      }
    },
    "/api/news/sentiment": {
      "get": {
        "operationId": "getSentiment",
        "summary": "Coin sentiment score",
        "description": "Aggregate bullish/bearish score for a coin using a keyword heuristic over recent headlines (no LLM). Returns a score in [-100, 100] plus a term breakdown.",
        "parameters": [
          { "name": "coin", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Coin ticker or name, e.g. BTC or ethereum." }
        ],
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.02",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 20000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "Sentiment score and breakdown." },
          "400": { "description": "Missing coin parameter." },
          "402": { "description": "Payment required." }
        }
      }
    },
    "/api/news/search": {
      "get": {
        "operationId": "searchNews",
        "summary": "Full-text search",
        "description": "Full-text search across article headlines and descriptions. All terms must match; title matches rank higher.",
        "parameters": [
          { "name": "query", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Search query." },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30 }, "description": "Number of articles to return." }
        ],
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.01",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 10000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "Matching articles." },
          "400": { "description": "Missing query parameter." },
          "402": { "description": "Payment required." }
        }
      }
    },
    "/api/news/feeds": {
      "get": {
        "operationId": "getFeeds",
        "summary": "Indexed sources",
        "description": "List of indexed RSS sources with per-feed status: article count, last update, and health.",
        "x-payment-info": {
          "authMode": "paid",
          "protocols": ["mpp"],
          "price": "0.01",
          "currency": "USDC.e",
          "currencyAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "network": "tempo",
          "chainId": 4217,
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "feePayer": true,
          "gasAbstracted": true
        },
        "x-mpp": {
          "price": 10000,
          "token": "USDC.e",
          "tokenAddress": "0x20C000000000000000000000b9537d11c60E8b50",
          "recipient": "0x0d509f743bc6fc907d5f63d8b0dae1fca8d80897",
          "network": "tempo",
          "feePayer": true
        },
        "responses": {
          "200": { "description": "Source list with status." },
          "402": { "description": "Payment required." }
        }
      }
    }
  }
}
