{
    "documentation_version": 1,
    "base_url": "https://c7dev.com",
    "instructions_url": "https://c7dev.com/api_instructions",
    "selection": {
        "method": "GET",
        "parameter": "api",
        "required": false,
        "description": "Omit api for the full suite, or use an endpoint name for its instructions only.",
        "example_url": "https://c7dev.com/api_instructions?api=media_api"
    },
    "instructions": [
        "Choose an endpoint by its description, then use its documented HTTP method and parameter location.",
        "URL-encode GET query values. Preserve identifiers such as VAT numbers and registration codes as strings.",
        "For JSON APIs, require HTTP success and result=true before using returned data. Read error_message on failure.",
        "Do not fabricate missing data or treat null as zero or false. Warnings may indicate incomplete or older data.",
        "Do not blindly retry invalid input or access errors. Temporary service failures may be retried with bounded backoff.",
        "Responses prohibit browser caching. Inspect cached, timestamps and X-API-Version when those fields are available."
    ],
    "authentication": {
        "documentation": "Public; no token is required to read these instructions.",
        "restricted_endpoints": "Supply credentials provided by the API operator when access control requires them.",
        "token_locations": [
            "Authorization: Bearer YOUR_ACCESS_TOKEN",
            "X-Access-Token: YOUR_ACCESS_TOKEN",
            "access_token query or form parameter"
        ],
        "domain": "Send domain as a query or form parameter when the client token is restricted to registered domains. Access may also be restricted by IP.",
        "ai_generate": "Requires both access_token and domain in the form body."
    },
    "json_response_envelope": {
        "result": "boolean; request succeeded",
        "error": "boolean; request failed",
        "error_message": "string; empty on success",
        "server_time": "integer; Unix timestamp in seconds"
    },
    "errors": {
        "400": "Missing or invalid input.",
        "403": "Access denied; check token, registered domain and IP permissions.",
        "404": "Unknown API selected for instructions.",
        "405": "Unsupported method for the instructions endpoint.",
        "500": "Processing failed.",
        "503": "Service temporarily unavailable."
    },
    "apis": [
        {
            "name": "feedreader_api",
            "method": "GET",
            "path": "/feedreader_api",
            "description": "Read up to five RSS, Atom or RDF feeds and public Facebook or Instagram profiles, and return entries as normalized JSON results.",
            "instructions_url": "https://c7dev.com/api_instructions?api=feedreader_api",
            "request": {
                "parameter_location": "query",
                "parameters": {
                    "url": {
                        "type": "string_or_array",
                        "required": true,
                        "description": "Public HTTP(S) RSS, Atom or RDF feed URL, or a Facebook Page or Instagram profile URL. Send one as url or up to five unique URLs as url[] query values. Duplicate URLs are removed before applying the limit. URL-encode each complete value, including any feed query string.",
                        "minItems": 1,
                        "maxItems": 5,
                        "items": {
                            "type": "string",
                            "maxLength": 8192
                        }
                    },
                    "limit": {
                        "type": "integer",
                        "required": false,
                        "description": "Number of latest posts per social URL.",
                        "default": 25,
                        "minimum": 1,
                        "maximum": 50
                    },
                    "after": {
                        "type": "string",
                        "required": false,
                        "description": "next cursor from a previous response, to read older posts. Use with a single Facebook or Instagram URL.",
                        "maxLength": 1024
                    },
                    "debug": {
                        "type": "string",
                        "required": false,
                        "description": "Set to 1 for request diagnostics; omit for ordinary requests.",
                        "enum": [
                            "0",
                            "1"
                        ]
                    }
                }
            },
            "response": {
                "format": "application/json",
                "response_fields": [
                    "url",
                    "final_url",
                    "http_code",
                    "results",
                    "response",
                    "cached",
                    "fetched_at",
                    "cache_expires_at",
                    "retry_after",
                    "facebook",
                    "instagram",
                    "sources"
                ],
                "item_fields": [
                    "item_html",
                    "url",
                    "title",
                    "text",
                    "image_url",
                    "time_publicated",
                    "id",
                    "source",
                    "images",
                    "links"
                ],
                "headers": {
                    "X-API-Version": "feedreader_api_v13"
                }
            },
            "details": {
                "Access": "Requires an access token authorized for feedreader_api",
                "URL": "Required public HTTP(S) feed, Facebook Page or Instagram profile URL. Use url for one or url[] for up to five unique URLs; duplicates are removed before the limit and mixed sources or multiple profiles on the same network are supported",
                "Social URLs": "Facebook and Instagram are detected from each URL and read through the Meta Graph API. Only url selects sources; Instagram requires a public business or creator account",
                "Timeline": "Multiple URLs return entries newest first and per-URL details in sources. A post shared to Facebook and Instagram within seven days appears once, from Instagram",
                "Paging": "next in a source's facebook or instagram response is the cursor for older posts. Pass it as after with that profile URL alone",
                "Returns": "results with item_html, url, title, text, image_url and time_publicated. Social posts also have id, source, images and links",
                "Errors": "error and error_message, plus the upstream URL, HTTP status, headers and body in response, capped at 100 KiB of original response data. Social reads report each network in facebook and instagram instead",
                "Caching": "Feed responses are cached for 30 minutes across clients; cached requests do not contact the source. Facebook and Instagram posts are read on every request",
                "Refresh": "Expired feeds use ETag or Last-Modified when available; HTTP 304 retains the entries for another 30 minutes",
                "Reddit": "Uncached feeds share upstream rate limits, with a 60-second fallback when rate headers are absent; cached feeds remain available",
                "Limits": "Up to five unique URLs, 20 seconds per unique URL (100 seconds for five), 40 MiB downloaded/decompressed per feed, five redirects and the latest 25 posts per social URL, up to 50 with limit"
            },
            "notes": [
                "Requires an access token authorized for feedreader_api, using Authorization: Bearer TOKEN, X-Access-Token, or access_token. Include domain when required by the client configuration.",
                "GET with a single feed URL returns every entry in source order. No feed result filtering, database writes or feed deduplication is performed.",
                "Pass up to five unique URLs as url[]=URL1&url[]=URL2, including a mixture of feeds and social profiles or multiple profiles on the same network. URLs are trimmed and fragments removed, then duplicates are removed while preserving the first occurrence. Distinct paths and query strings on the same domain remain separate sources. The five-URL limit, pagination restrictions and time budget apply after duplicate removal. A single remaining URL keeps the single-source response shape, including when sent as url[]. Empty lists, more than five unique URLs, nested arrays and invalid URLs return HTTP 400 before any source is read. Comma-separated URLs are not supported; encode commas and query strings as part of each URL.",
                "Multiple URLs return one results timeline sorted newest first, with matching Facebook/Instagram posts combined as described below. url is the list of requested URLs, final_url is empty and sources contains one entry per URL in request order, with that source's response fields except results. Read sources for individual errors, diagnostics and social pagination cursors. A successful source, including an empty feed, keeps HTTP 200 and error=false even when other sources fail. If every source fails, error=true and error_message contains all reasons; HTTP 429 is used when retry_after is positive, otherwise HTTP 424. http_code is 200 on success or the first source's code when all fail; response is null and upstream diagnostics are in sources.",
                "For multiple URLs, cached is true only when every source was cached, fetched_at is the latest source fetch timestamp, cache_expires_at is the earliest source expiry or null if any source is uncached, and retry_after is the longest source delay. Individual cache timestamps and retry delays remain available in sources.",
                "error=false and error_message=\"\" indicate success; results contains the entries. The normal result/error/server_time envelope is also returned.",
                "debug=1 adds a fresh XML runtime self-test in debug, even when the feed response is cached. It reports PHP/libxml versions and the results of parsing a fixed XML sample; it does not expose configuration, credentials or filesystem contents.",
                "Feed responses, including upstream errors, are cached for 30 minutes across clients. cached reports cache reuse; fetched_at and cache_expires_at are UTC timestamps and remain unchanged on cache hits. A cached request does not contact the upstream server.",
                "HTTP 429 rate limits from any source honor Retry-After as seconds or an HTTP date. If that delay exceeds 30 minutes, the cached rate-limit response is retained until the delay expires. retry_after counts down on cache hits; a longer source delay is never shortened to the normal cache lifetime.",
                "After expiry, feeds with ETag or Last-Modified validators are checked conditionally. If the source returns HTTP 304 Not Modified, the API returns HTTP 200 with the previous entries, http_code=304 and cached=false, and starts a new 30-minute cache period. fetched_at records the latest successful fetch or revalidation. Validators are sent only to the exact feed URL that supplied them.",
                "Reddit feed cache entries are shared across equivalent subreddit URL spellings. Uncached Reddit feeds share rate limits derived from Retry-After and X-Ratelimit headers. A conservative 60-second interval is used when those headers are absent. Authenticated Data API quotas are not applied to RSS.",
                "Local Reddit cooldowns return HTTP 429 and retry_after with a Retry-After header. They are not cached for 30 minutes; retry after the indicated delay. Cached feeds remain available during cooldowns. Upstream HTTP 429 responses retain their diagnostics and are cached like other upstream responses.",
                "Each result preserves the sample contract: item_html is the original entry XML, url is its resolved HTTP(S) link, title and text are plain text, image_url is a resolved image URL, and time_publicated is a Unix timestamp or 0 when unavailable.",
                "Images use direct feed media fields first, then fall back to img elements, video posters and image-file URLs in content, descriptions, summaries and the original entry XML. Shared filters skip emoji, icons, logos, avatars, tracking pixels, placeholders, hidden elements and candidates with a declared width or height below 100 pixels. Only HTTP(S) image URLs are returned; image files are not downloaded to measure unknown dimensions.",
                "Relative links are resolved against the final feed URL and xml:base. title is limited to 255 characters and image_url to 1000 characters. Missing strings are empty.",
                "Single-feed retrieval and parsing failures return HTTP 424 Failed Dependency, error=true, an explanatory error_message, results=[], and the last available upstream response. HTTP 424 preserves JSON diagnostics through gateways that replace HTTP 502 bodies with HTML. http_code retains the upstream status, including 502 when returned by the source. Invalid input returns HTTP 400; when no request completed, response is null.",
                "On failure, response contains url, http_code, headers, headers_encoding, body, body_encoding, truncated and transport_error. headers is the raw HTTP status/header block. Headers and body together preserve at most 102400 bytes of original response data; truncated identifies omitted data.",
                "body_encoding and headers_encoding are utf-8 or base64. Decode base64 to recover original non-UTF-8 bytes. JSON escaping and base64 may make the encoded JSON larger than the original response limit.",
                "Successful responses have response=null. Challenge pages, access denials, rate limits, empty responses and invalid feed XML produce specific error messages. An empty valid feed succeeds with results=[].",
                "Feeds are limited to 40 MiB of transfer and decompressed data, 32 KiB of response headers per request and five redirects. Each source URL has a 20-second budget shared by its upstream requests and redirects, including Meta Page resolution and token fallback. The total request budget is 20 seconds per unique URL, up to 100 seconds for five URLs. Requests verify TLS and accept only public Internet addresses, including after redirects.",
                "The parser rejects XML document types and entity declarations and repairs known formatting defects: adjacent namespace declarations and scripts appended after the closing feed element.",
                "A Facebook Page or Instagram profile URL in url or url[] reads public posts through the Meta Graph API instead of a feed. Facebook URLs include profile.php?id=ID, /people/NAME/ID and /NAME-ID links. Instagram requires a profile URL. Bare usernames and IDs are not accepted. Only url selects sources; the former facebook and instagram request parameters are ignored.",
                "Social reads return the latest posts from each social URL, 25 by default or up to 50 with limit, newest first, including posts without text or images. item_html is the escaped post text with line breaks followed by its images, url is the post permalink, title is the first line of the text, text is plain text and image_url is the first image. id is the post ID on its network, source is facebook or instagram, images lists every photo or video preview, and links maps each network where the post appears to its permalink.",
                "A Facebook and an Instagram post published within seven days of each other count as one post when one text contains the other and both have at least 20 characters after removing links, hashtags, mentions and punctuation, or when their first images match by perceptual hash. The Instagram copy is returned because Facebook reduces images to 720 pixels. links.facebook keeps the Facebook permalink.",
                "Instagram posts come from Meta Business Discovery, which reads only public business and creator accounts. Personal and age-gated accounts are not available. Video posts return their preview image. Facebook Pages are read with the Meta permissions of the API operator. A Page that cannot be read reports the Meta error message.",
                "Each social source response adds facebook and instagram, each with url (profile URL), http_code (Meta response status, 0 without a response), error_message and next, or null when that network was not requested. For multiple URLs these fields are inside sources. Social reads are not cached: every request reads Meta, cached=false and cache_expires_at=null. A single-source response echoes url and sets final_url to the profile URL. A failing social URL returns error=true, its Meta error in error_message and http_code, and response=null.",
                "next is the cursor for older posts of that profile, or an empty string at the end. Pass it as after with that profile's URL alone to read the next page, and stop when next is empty or a page has no posts. after with multiple URLs including a social URL returns HTTP 400. limit and after apply only to Facebook and Instagram. Every page is a new Meta request and is not cached, so store the pages you read. Meta returns about 600 Facebook posts per year at most.",
                "Social image URLs are signed Meta CDN URLs that expire. Download images that must be kept, or request the API again for current URLs. An unconfigured social reader returns HTTP 503 for a single URL; multi-URL requests report it as a source failure and keep any working sources."
            ],
            "examples": [
                {
                    "method": "GET",
                    "url": "https://c7dev.com/feedreader_api?url=https%3A%2F%2Ffeeds.bbci.co.uk%2Fnews%2Frss.xml"
                },
                {
                    "method": "GET",
                    "url": "https://c7dev.com/feedreader_api?url%5B0%5D=https%3A%2F%2Fwww.facebook.com%2FNASA&url%5B1%5D=https%3A%2F%2Fwww.instagram.com%2Fnasa%2F"
                },
                {
                    "method": "GET",
                    "url": "https://c7dev.com/feedreader_api?url=https%3A%2F%2Fwww.instagram.com%2Fnasa%2F&limit=50"
                },
                {
                    "method": "GET",
                    "url": "https://c7dev.com/feedreader_api?url%5B0%5D=https%3A%2F%2Ffeeds.bbci.co.uk%2Fnews%2Frss.xml&url%5B1%5D=https%3A%2F%2Fwww.instagram.com%2Fnasa%2F"
                }
            ]
        }
    ],
    "result": true,
    "error": false,
    "error_message": "",
    "server_time": 1794514537
}