{
  "name": "rss-parse",
  "summary": "Fetches an RSS, Atom or RSS 1.0 feed and returns its channel metadata and a normalised list of items -- id, title, link, summary, content, author, dates and categories -- with every date in ISO 8601 UTC.",
  "rationale": "It needs the network and normalises three feed formats that say the same things in different tags and two different date formats, behind an XXE-safe XML parser. One call replaces the three-parser, RFC-822-date, entity-decoding scraper an agent would otherwise carry.",
  "family": "feeds",
  "price_usd": "0.002",
  "free": false,
  "timeout_ms": 8000,
  "max_timeout_seconds": 29,
  "input_schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "url": {
        "type": "string",
        "maxLength": 2048,
        "format": "uri",
        "description": "Absolute http(s) URL of the RSS 2.0, Atom or RSS 1.0 (RDF) feed, up to 2048 characters; up to 5 redirects are followed and a DTD is refused."
      },
      "limit": {
        "default": 50,
        "description": "Maximum number of items returned, 1 to 1000 (default 50), counted after the since filter; a longer feed is cut and reported as truncated.",
        "type": "integer",
        "minimum": 1,
        "maximum": 1000
      },
      "since": {
        "description": "ISO 8601 timestamp with Z or an offset; when set, only items whose published (or else updated) date is at or after it are kept, and undated items are dropped.",
        "type": "string",
        "format": "date-time",
        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      }
    },
    "required": [
      "url"
    ],
    "additionalProperties": false
  },
  "input_example": {
    "url": "https://grist.tools/samples/web/fieldnotes/feed.xml",
    "limit": 10
  },
  "output_example": {
    "url": "https://grist.tools/samples/web/fieldnotes/feed.xml",
    "source_url": "https://grist.tools/samples/web/fieldnotes/feed.xml",
    "final_url": "https://grist.tools/samples/web/fieldnotes/feed.xml",
    "http_status": 200,
    "format": "rss",
    "feed": {
      "title": "Field Notes",
      "link": "https://grist.tools/samples/web/fieldnotes/index.html",
      "description": "Short notes on frost, rain and wind from a small test garden.",
      "language": "en",
      "updated": "2026-08-25T06:15:00Z",
      "generator": "Hand-written sample"
    },
    "items": [
      {
        "id": "fieldnotes-rain-gauge",
        "title": "Reading a rain gauge by hand",
        "link": "https://grist.tools/samples/web/fieldnotes/notes/rain-gauge.html",
        "summary": "How the daily rain reading is taken & written down.",
        "content": "<p>The gauge is read once a day at eight in the morning.</p>",
        "author": "Field Notes Editors",
        "published": "2026-08-25T06:15:00Z",
        "updated": null,
        "categories": [
          "rain",
          "method"
        ]
      },
      {
        "id": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
        "title": "The first frost of the season",
        "link": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
        "summary": "A light ground frost on the lower beds, measured at dawn.",
        "content": null,
        "author": "Field Notes Editors",
        "published": "2026-08-24T06:30:00Z",
        "updated": null,
        "categories": [
          "frost"
        ]
      }
    ],
    "count": 2,
    "total": 2,
    "truncated": false,
    "fetched_at": "2026-09-01T12:00:00.000Z"
  },
  "errors": [
    "invalid_input",
    "blocked_target",
    "unreachable_target",
    "upstream_status",
    "upstream_timeout",
    "unsupported_content_type",
    "too_large",
    "unprocessable",
    "internal"
  ]
}