{
  "openapi": "3.0.3",
  "info": {
    "title": "Free News API",
    "version": "1.0.0",
    "description": "Free News API provides authenticated access to news articles, article details, publisher lookup, author lookup, available languages by country, and available topics.\n\nAuthentication is performed using an API key sent in the `x-api-key` header.\n\n## Getting started\n1. Obtain your API key\n2. Send it in the `x-api-key` request header\n3. Call the endpoints below\n\n## Pagination\nThe `/news` endpoint supports both offset pagination and cursor pagination.\n- Use `offset` for simple page-based access\n- Use `cursor` for efficient deep navigation\n- Do not send both at the same time\n\n## Search\nThe `/news` endpoint currently supports:\n- `in_title` for title-only search\n\nRemoved search parameters:\n- `q` has been removed\n- `in_subtitle` has been removed\n- `in_body` has been removed\n\nRequests that still include `q`, `in_subtitle`, or `in_body` return `400 Bad Request` with a field-specific error message.\n\nSearch behavior for `in_title`:\n- Up to 5 tokens are processed\n- Single-character tokens are rejected\n- Two-character tokens may require additional filters or a narrow date range\n\n## Rate limits and quotas\nResponses may include daily and monthly quota headers indicating limits, remaining requests, and reset times."
  },
  "servers": [
    {
      "url": "https://api.freenewsapi.io/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "News",
      "description": "Endpoints for listing news articles and retrieving full article details."
    },
    {
      "name": "Lookup",
      "description": "Endpoints for searching publishers, authors, languages, and topics."
    }
  ],
  "paths": {
    "/news": {
      "get": {
        "tags": [
          "News"
        ],
        "summary": "List news articles",
        "description": "Returns a lightweight list of news articles.\n\nSupports:\n- publication date filters\n- language, country, topic, publisher, and author filters\n- title-only search using `in_title`\n- recent or archive ordering\n- offset or cursor pagination\n\nRemoved search parameters:\n- `q` has been removed\n- `in_subtitle` has been removed\n- `in_body` has been removed\n\nRequests that still include `q`, `in_subtitle`, or `in_body` return `400 Bad Request` with a field-specific error message.\n\nBehavior notes:\n- `in_title` searches only in the article title\n- `offset` and `cursor` are mutually exclusive\n- high offset values may return a warning recommending cursor pagination",
        "parameters": [
          {
            "$ref": "#/components/parameters/published_after"
          },
          {
            "$ref": "#/components/parameters/published_before"
          },
          {
            "$ref": "#/components/parameters/language"
          },
          {
            "$ref": "#/components/parameters/country"
          },
          {
            "$ref": "#/components/parameters/topic"
          },
          {
            "$ref": "#/components/parameters/publisher_uuid"
          },
          {
            "$ref": "#/components/parameters/author_uuid"
          },
          {
            "$ref": "#/components/parameters/in_title"
          },
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/in_subtitle"
          },
          {
            "$ref": "#/components/parameters/in_body"
          },
          {
            "$ref": "#/components/parameters/order_by"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "News articles returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-API-Warning": {
                "description": "Present when offset pagination is becoming inefficient and cursor pagination is recommended.",
                "schema": {
                  "type": "string"
                },
                "example": "High offset detected. Offset pagination will be blocked after 10000. Consider using cursor pagination."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewsListResponse"
                },
                "examples": {
                  "recent_with_language_country": {
                    "summary": "GET https://api.freenewsapi.io/v1/news?language=en&country=us&order_by=recent",
                    "value": {
                      "data": [
                        {
                          "uuid": "dcc8e6d4-1464-4baa-9b63-c6f92287c0da",
                          "title": "Billy Idol thrilled to be inducted into Rock and Roll Hall of Fame: 'I can't believe it'",
                          "published_at": "2026-04-14T07:32:47.000Z",
                          "publisher": "Yahoo"
                        },
                        {
                          "uuid": "3305e809-dbee-4827-af99-6b6219c86997",
                          "title": "Liverpool targets famous Champions League comeback against PSG",
                          "published_at": "2026-04-14T07:24:37.000Z",
                          "publisher": "WRAL"
                        },
                        {
                          "uuid": "b242b814-4397-4c88-a707-23bf168ce65f",
                          "title": "Selena Gomez supports Demi Lovato on opening night of tour",
                          "published_at": "2026-04-14T07:24:25.000Z",
                          "publisher": "Yahoo"
                        },
                        {
                          "uuid": "7ce2c458-1a38-45fb-ba45-3306affce14c",
                          "title": "Barcelona ask UEFA to inspect Metropolitano pitch ahead of decisive Champions League tie",
                          "published_at": "2026-04-14T07:20:00.000Z",
                          "publisher": "Yahoo Sports"
                        },
                        {
                          "uuid": "d0df8333-8d96-4b35-99c6-5db42b9d9757",
                          "title": "Tormentil: Yellow wildflower that could be a breakthrough against drug-resistant infections",
                          "published_at": "2026-04-14T07:17:18.000Z",
                          "publisher": "The Eastleigh Voice"
                        },
                        {
                          "uuid": "2a53fa1b-0c49-438f-b368-6b7e4ffc6db2",
                          "title": "Shades of Ferguson but Carrick needs a response",
                          "published_at": "2026-04-14T07:11:49.000Z",
                          "publisher": "Yahoo Sports"
                        },
                        {
                          "uuid": "4148a527-5119-4d23-ac47-301714e1aff0",
                          "title": "Jorginho expresses ‘regret’ over hotel security incident involving Chappell Roan: ‘It was ultimately a misunderstanding’",
                          "published_at": "2026-04-14T07:06:00.000Z",
                          "publisher": "The Independent"
                        },
                        {
                          "uuid": "05397dd3-a8a9-478e-ad6f-2b2e7f75f101",
                          "title": "Eric Swalwell's exit helps Democrats in California governor's race",
                          "published_at": "2026-04-14T07:01:00.000Z",
                          "publisher": "USA Today"
                        },
                        {
                          "uuid": "083a873e-1e5e-42af-bbd1-75e49478f74b",
                          "title": "Artemis II crew returns to Earth. Rewatch historic moment",
                          "published_at": "2026-04-14T07:00:42.000Z",
                          "publisher": "Yahoo"
                        },
                        {
                          "uuid": "09e88a9c-06b7-44aa-9964-dd76b3789125",
                          "title": "Barcelona squad named for Atlético 2nd leg",
                          "published_at": "2026-04-14T07:00:00.000Z",
                          "publisher": "Yahoo Sports"
                        }
                      ],
                      "meta": {
                        "page_size": 10,
                        "returned": 10,
                        "has_more": true,
                        "order_by": "recent",
                        "filters": {
                          "published_after": null,
                          "published_before": null,
                          "language": "en",
                          "country": "US",
                          "topic": null,
                          "publisher_uuid": null,
                          "author_uuid": null,
                          "in_title": null
                        },
                        "offset": 0,
                        "next_offset": 10,
                        "next_cursor": "eyJ2IjoxLCJvcmRlcl9ieSI6InJlY2VudCIsInNpZyI6IjYzMTE0NTM4OWUyZTViN2YxNDJiMDMyZGY2YjQ3ZDBkYTkxZWIyYzhmN2MyZDliOTU2ZDlhOWJlY2RkOTBlZGUiLCJsYXN0X3B1Ymxpc2hlZF9hdCI6IjIwMjYtMDQtMTRUMDc6MDA6MDAuMDAwWiIsImxhc3RfaWQiOjE0Mjg0MDl9"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_offset": {
                    "value": {
                      "error": "Invalid offset"
                    }
                  },
                  "invalid_order_by": {
                    "value": {
                      "error": "Invalid order_by"
                    }
                  },
                  "offset_cursor_conflict": {
                    "value": {
                      "error": "Cannot use offset and cursor together"
                    }
                  },
                  "short_token_too_broad": {
                    "value": {
                      "error": "Short-token search is too broad without strong filters"
                    }
                  },
                  "removed_q": {
                    "summary": "Removed q search parameter",
                    "value": {
                      "error": "Search using the 'q' field has been removed."
                    }
                  },
                  "removed_in_body": {
                    "summary": "Removed in_body search parameter",
                    "value": {
                      "error": "Search using the 'in_body' field has been removed."
                    }
                  },
                  "removed_in_subtitle": {
                    "summary": "Removed in_subtitle search parameter",
                    "value": {
                      "error": "Search using the 'in_subtitle' field has been removed."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    },
    "/details": {
      "get": {
        "tags": [
          "News"
        ],
        "summary": "Get article details",
        "description": "Returns the full details of a single article identified by UUID.",
        "parameters": [
          {
            "$ref": "#/components/parameters/details_uuid"
          }
        ],
        "responses": {
          "200": {
            "description": "Article details returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewsDetailsResponse"
                },
                "examples": {
                  "details": {
                    "summary": "GET https://api.freenewsapi.io/v1/details?uuid=dcc8e6d4-1464-4baa-9b63-c6f92287c0da",
                    "value": {
                      "data": {
                        "uuid": "dcc8e6d4-1464-4baa-9b63-c6f92287c0da",
                        "title": "Billy Idol thrilled to be inducted into Rock and Roll Hall of Fame: 'I can't believe it'",
                        "thumbnail": "https://s.yimg.com/ny/api/res/1.2/HdFfGGwj1B4EAtcmFyl1gQ--/YXBwaWQ9aGlnaGxhbmRlcjt3PTEyNDI7aD02OTk7Y2Y9d2VicA--/https://media.zenfs.com/en/cover_media_us_articles_275/be1a6baa6561f63ef32b5c76542dc185",
                        "publisher": "Yahoo",
                        "authors": [
                          "Cover Media"
                        ],
                        "topics": [
                          "entertainment"
                        ],
                        "countries": [
                          "US"
                        ],
                        "languages": [
                          "en"
                        ],
                        "published_at": "2026-04-14T07:32:47.000Z",
                        "original_url": "https://www.yahoo.com/entertainment/music/articles/billy-idol-thrilled-inducted-rock-073247115.html",
                        "incipit": "Billy Idol has expressed his delight at being inducted into the Rock and Roll Hall of Fame. On Monday, officials at the Rock and Roll Hall of Fame Foundation announced that the English rock star was among...",
                        "body": "Billy Idol has expressed his delight at being inducted into the Rock and Roll Hall of Fame. On Monday, officials at the Rock and Roll Hall of Fame Foundation announced that the English rock star was among those to be selected for the class of 2026 under the performer category. Idol, real name William Broad, will be joined by Phil Collins, Iron Maiden, Joy Division/New Order, Oasis, Sade, the late Luther Vandross, and Wu-Tang Clan. Speaking to Billboard following the news, Billy noted that he was thrilled to be given the nod this year, having been nominated once before. \"It's really exciting. I can't believe it. It's incredible. It's just fantastic to think that something I was doing for the sheer love of the scene we were in back in the '70s, the punk rock scene,\" he exclaimed. \"We were doing it for the love. We had no idea it was going to explode and lead to me doing this for 50 years. So it's all really incredible and something I just couldn't have imagined when I was starting out.\" The White Wedding hitmaker went on to emphasise just how much the honour means to him. \"It's just been fantastic, being part of this musical revolution we really believed in and to be pushing the culture along. It's been really fun, and a dream come true. And then this is just icing on the cake, just... wow, what an honour! I almost can't put it into words. To be able to have your peers vote you in and that, it's pretty special,\" the 70-year-old added. Billy dropped his ninth studio album, Dream Into It, in April 2025. To be eligible for induction, an individual artist or band must have released its first commercial recording at least 25 years prior to the year of nomination. The 2026 Rock & Roll Hall of Fame Induction ceremony will be held on 14 November at the Peacock Theater in Los Angeles."
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_uuid": {
                    "value": {
                      "error": "Missing uuid"
                    }
                  },
                  "invalid_uuid": {
                    "value": {
                      "error": "Invalid uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "404": {
            "description": "Article not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Not found"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    },
    "/publishers": {
      "get": {
        "tags": [
          "Lookup"
        ],
        "summary": "Search publishers",
        "description": "Search publishers by display name.\n\nBehavior notes:\n- the search string must be at least 2 characters long\n- up to 5 tokens are used\n- only tokens with 2 or more characters are considered\n- all tokens must match the publisher name",
        "parameters": [
          {
            "$ref": "#/components/parameters/lookup_q"
          },
          {
            "$ref": "#/components/parameters/lookup_offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Publishers returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                },
                "examples": {
                  "publishers": {
                    "summary": "GET https://api.freenewsapi.io/v1/publishers?q=new%20york",
                    "value": {
                      "data": [
                        {
                          "uuid": "ffc1026d-73b9-4618-9c90-e8431383b678",
                          "name": "ABC7 New York"
                        },
                        {
                          "uuid": "4e678bca-dfd4-47c6-adec-6d23ca879083",
                          "name": "amNewYork"
                        },
                        {
                          "uuid": "02bb53e3-5750-43b0-99a0-94570dc8cded",
                          "name": "City & State New York"
                        },
                        {
                          "uuid": "bd2bafdf-c052-4988-acc3-4aa0ec5ae46a",
                          "name": "Crain's New York"
                        },
                        {
                          "uuid": "c7d7d200-9c41-49e8-b743-d817e51f9958",
                          "name": "Crain's New York Business"
                        },
                        {
                          "uuid": "daca34a2-1429-469d-bebc-9bf6c8cb8f93",
                          "name": "Federal Reserve Bank of New York"
                        },
                        {
                          "uuid": "526a6c69-60c7-48f1-8e9a-832dbb1794d4",
                          "name": "FOX 5 New York"
                        },
                        {
                          "uuid": "f000eb93-6245-4aa5-9efd-dbd35357dd61",
                          "name": "Hudson Yards New York"
                        },
                        {
                          "uuid": "ba5a91b3-356f-45a3-a313-560fff9bec11",
                          "name": "hudsonyardsnewyork.com"
                        },
                        {
                          "uuid": "050d6883-235a-498a-84df-855655115a36",
                          "name": "La Voce di New York"
                        }
                      ],
                      "meta": {
                        "q": "new york",
                        "offset": 0,
                        "page_size": 10,
                        "returned": 10,
                        "has_more": true,
                        "next_offset": 10,
                        "tokens": [
                          "new",
                          "york"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "short_q": {
                    "value": {
                      "error": "q must be at least 2 characters"
                    }
                  },
                  "invalid_offset": {
                    "value": {
                      "error": "Invalid offset"
                    }
                  },
                  "no_valid_tokens": {
                    "value": {
                      "error": "q must contain at least one token with 2 or more characters"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    },
    "/authors": {
      "get": {
        "tags": [
          "Lookup"
        ],
        "summary": "Search authors",
        "description": "Search authors by display name.\n\nBehavior notes:\n- the search string must be at least 2 characters long\n- up to 5 tokens are used\n- only tokens with 2 or more characters are considered\n- all tokens must match the author name",
        "parameters": [
          {
            "$ref": "#/components/parameters/lookup_q"
          },
          {
            "$ref": "#/components/parameters/lookup_offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Authors returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                },
                "examples": {
                  "authors": {
                    "summary": "GET https://api.freenewsapi.io/v1/authors?q=Robert%20Fisk",
                    "value": {
                      "data": [
                        {
                          "uuid": "4042249f-e2b8-4df9-aea1-bcfd1eb13103",
                          "name": "Robert Fisk"
                        }
                      ],
                      "meta": {
                        "q": "Robert Fisk",
                        "offset": 0,
                        "page_size": 10,
                        "returned": 1,
                        "has_more": false,
                        "next_offset": null,
                        "tokens": [
                          "robert",
                          "fisk"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "short_q": {
                    "value": {
                      "error": "q must be at least 2 characters"
                    }
                  },
                  "invalid_offset": {
                    "value": {
                      "error": "Invalid offset"
                    }
                  },
                  "no_valid_tokens": {
                    "value": {
                      "error": "q must contain at least one token with 2 or more characters"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    },
    "/languages": {
      "get": {
        "tags": [
          "Lookup"
        ],
        "summary": "List available languages for a country",
        "description": "Returns the languages currently available for a given country.",
        "parameters": [
          {
            "$ref": "#/components/parameters/languages_country"
          }
        ],
        "responses": {
          "200": {
            "description": "Languages returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LanguagesResponse"
                },
                "examples": {
                  "languages": {
                    "summary": "GET https://api.freenewsapi.io/v1/languages?country=us",
                    "value": {
                      "data": [
                        "en",
                        "es-419"
                      ],
                      "meta": {
                        "country": "US",
                        "returned": 2
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_country": {
                    "value": {
                      "error": "Missing country"
                    }
                  },
                  "invalid_country": {
                    "value": {
                      "error": "Invalid country"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    },
    "/topics": {
      "get": {
        "tags": [
          "Lookup"
        ],
        "summary": "List available topics",
        "description": "Returns all currently available topics.\n\nTopic availability may change over time and may differ by country.",
        "responses": {
          "200": {
            "description": "Topics returned successfully.",
            "headers": {
              "X-RateLimit-Limit-Day": {
                "description": "Daily request quota limit for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Remaining daily requests for the authenticated user, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Day": {
                "description": "Daily quota reset time, when a daily quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit-Month": {
                "description": "Monthly request quota limit for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Month": {
                "description": "Remaining monthly requests for the authenticated user, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Reset-Month": {
                "description": "Monthly quota reset time, when a monthly quota applies.",
                "schema": {
                  "type": "string"
                }
              },
              "X-API-Warning": {
                "description": "Warning that topic availability may vary over time and across countries.",
                "schema": {
                  "type": "string"
                },
                "example": "Topic availability may change over time and may differ by country."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicsResponse"
                },
                "examples": {
                  "topics": {
                    "summary": "GET https://api.freenewsapi.io/v1/topics",
                    "value": {
                      "data": [
                        "arts-design",
                        "baseball",
                        "basketball",
                        "beauty",
                        "business",
                        "celebrities",
                        "combat sports",
                        "cricket",
                        "cycling",
                        "digital currencies",
                        "economy",
                        "education",
                        "energy",
                        "entertainment",
                        "environment",
                        "fashion",
                        "finance",
                        "food",
                        "football",
                        "gadgets",
                        "gaming",
                        "geology",
                        "golf",
                        "health",
                        "higher education",
                        "hockey",
                        "home",
                        "internet security",
                        "jobs",
                        "medicine",
                        "mental health",
                        "mobile",
                        "motor sports",
                        "movies",
                        "music",
                        "neuroscience",
                        "nutrition",
                        "online education",
                        "outdoors",
                        "paleontology",
                        "personal finance",
                        "physics",
                        "politics",
                        "public health",
                        "robotics",
                        "rugby",
                        "science",
                        "shopping",
                        "soccer",
                        "social sciences",
                        "space",
                        "sports",
                        "sports betting",
                        "technology",
                        "tennis",
                        "theater",
                        "travel",
                        "tv",
                        "vehicles",
                        "virtual reality",
                        "water sports",
                        "wildlife",
                        "world"
                      ],
                      "meta": {
                        "returned": 63,
                        "warning": "Topic availability may change over time and may differ by country."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedResponse"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenResponse"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsResponse"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "published_after": {
        "name": "published_after",
        "in": "query",
        "description": "Include only articles published at or after this datetime.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "published_before": {
        "name": "published_before",
        "in": "query",
        "description": "Include only articles published at or before this datetime.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "language": {
        "name": "language",
        "in": "query",
        "description": "Filter by language code.",
        "schema": {
          "type": "string"
        },
        "example": "en"
      },
      "country": {
        "name": "country",
        "in": "query",
        "description": "Filter by country code.",
        "schema": {
          "type": "string"
        },
        "example": "US"
      },
      "topic": {
        "name": "topic",
        "in": "query",
        "description": "Filter by topic.",
        "schema": {
          "type": "string"
        },
        "example": "world"
      },
      "publisher_uuid": {
        "name": "publisher_uuid",
        "in": "query",
        "description": "Filter by publisher identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "author_uuid": {
        "name": "author_uuid",
        "in": "query",
        "description": "Filter by author identifier.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "q": {
        "name": "q",
        "in": "query",
        "description": "Removed. Broad search using the `q` field is no longer supported on `/news`. Passing this parameter returns `400 Bad Request` with: `Search using the 'q' field has been removed.`",
        "schema": {
          "type": "string"
        },
        "deprecated": true
      },
      "in_title": {
        "name": "in_title",
        "in": "query",
        "description": "Search only in the article title. This is currently the only supported search parameter on `/news`.",
        "schema": {
          "type": "string"
        }
      },
      "in_subtitle": {
        "name": "in_subtitle",
        "in": "query",
        "description": "Removed. Subtitle or incipit search is no longer supported on `/news`. Passing this parameter returns `400 Bad Request` with: `Search using the 'in_subtitle' field has been removed.`",
        "schema": {
          "type": "string"
        },
        "deprecated": true
      },
      "in_body": {
        "name": "in_body",
        "in": "query",
        "description": "Removed. Article body search is no longer supported on `/news`. Passing this parameter returns `400 Bad Request` with: `Search using the 'in_body' field has been removed.`",
        "schema": {
          "type": "string"
        },
        "deprecated": true
      },
      "order_by": {
        "name": "order_by",
        "in": "query",
        "description": "Ordering mode. Use `recent` for newest articles first, or `archive` for stable archive traversal.",
        "schema": {
          "type": "string",
          "enum": [
            "recent",
            "archive"
          ],
          "default": "recent"
        }
      },
      "offset": {
        "name": "offset",
        "in": "query",
        "description": "Offset pagination. Cannot be used together with `cursor`. Maximum value: 10000.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 0
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Cursor pagination token. Cannot be used together with `offset`.",
        "schema": {
          "type": "string"
        }
      },
      "details_uuid": {
        "name": "uuid",
        "in": "query",
        "required": true,
        "description": "Article UUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "lookup_q": {
        "name": "q",
        "in": "query",
        "required": true,
        "description": "Search string. Must be at least 2 characters long.",
        "schema": {
          "type": "string",
          "minLength": 2
        },
        "example": "reuters"
      },
      "lookup_offset": {
        "name": "offset",
        "in": "query",
        "description": "Offset pagination. Maximum value: 10000.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 0
      },
      "languages_country": {
        "name": "country",
        "in": "query",
        "required": true,
        "description": "Country code.",
        "schema": {
          "type": "string"
        },
        "example": "US"
      }
    },
    "responses": {
      "UnauthorizedResponse": {
        "description": "Missing or invalid API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "missing": {
                "value": {
                  "error": "Missing API key"
                }
              },
              "invalid": {
                "value": {
                  "error": "Invalid API key"
                }
              }
            }
          }
        }
      },
      "ForbiddenResponse": {
        "description": "Access denied.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "disabled": {
                "value": {
                  "error": "API key disabled"
                }
              },
              "expired": {
                "value": {
                  "error": "API key expired"
                }
              },
              "ip_not_allowed": {
                "value": {
                  "error": "IP not allowed"
                }
              }
            }
          }
        }
      },
      "TooManyRequestsResponse": {
        "description": "Rate limit or quota exceeded.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseExtended"
            },
            "examples": {
              "rate_limit": {
                "value": {
                  "error": "Too Many Requests",
                  "retry_after_ms": 724
                }
              },
              "daily_quota": {
                "value": {
                  "error": "Daily quota exceeded"
                }
              },
              "monthly_quota": {
                "value": {
                  "error": "Monthly quota exceeded"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "NewsItem": {
        "type": "object",
        "description": "Lightweight representation of a news article returned by the list endpoint.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the article."
          },
          "title": {
            "type": "string",
            "description": "Title of the article."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication datetime of the article."
          },
          "publisher": {
            "type": "string",
            "nullable": true,
            "description": "Name of the publisher, if available."
          }
        },
        "required": [
          "uuid",
          "title",
          "published_at",
          "publisher"
        ]
      },
      "NewsListResponse": {
        "type": "object",
        "description": "Paginated response returned by the news listing endpoint.",
        "properties": {
          "data": {
            "type": "array",
            "description": "List of news articles for the current page.",
            "items": {
              "$ref": "#/components/schemas/NewsItem"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/NewsListMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "NewsListMeta": {
        "type": "object",
        "description": "Metadata describing the current page of news results.",
        "properties": {
          "page_size": {
            "type": "integer",
            "example": 10,
            "description": "Maximum number of items returned per page."
          },
          "returned": {
            "type": "integer",
            "description": "Number of items returned in the current response."
          },
          "has_more": {
            "type": "boolean",
            "description": "Indicates whether more results are available."
          },
          "order_by": {
            "type": "string",
            "enum": [
              "recent",
              "archive"
            ],
            "description": "Ordering mode used for the response."
          },
          "filters": {
            "$ref": "#/components/schemas/NewsFilters"
          },
          "offset": {
            "type": "integer",
            "nullable": true,
            "description": "Offset used for offset-based pagination, when applicable."
          },
          "next_offset": {
            "type": "integer",
            "nullable": true,
            "description": "Offset to request the next page when using offset pagination."
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Cursor token for requesting the next page."
          },
          "warning": {
            "type": "string",
            "nullable": true,
            "description": "Optional warning message, typically returned for high offset usage."
          }
        },
        "required": [
          "page_size",
          "returned",
          "has_more",
          "order_by",
          "filters"
        ]
      },
      "NewsFilters": {
        "type": "object",
        "description": "Filters used in the request.",
        "properties": {
          "published_after": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Lower publication date filter."
          },
          "published_before": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Upper publication date filter."
          },
          "language": {
            "type": "string",
            "nullable": true,
            "description": "Language filter used in the request."
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Country filter used in the request."
          },
          "topic": {
            "type": "string",
            "nullable": true,
            "description": "Topic filter used in the request."
          },
          "publisher_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Publisher filter used in the request."
          },
          "author_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Author filter used in the request."
          },
          "in_title": {
            "type": "string",
            "nullable": true,
            "description": "Title-only search term used in the request."
          }
        }
      },
      "NewsDetailsResponse": {
        "type": "object",
        "description": "Response returned by the article details endpoint.",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/NewsDetails"
          }
        },
        "required": [
          "data"
        ]
      },
      "NewsDetails": {
        "type": "object",
        "description": "Full representation of a single news article.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the article."
          },
          "title": {
            "type": "string",
            "description": "Title of the article."
          },
          "thumbnail": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL of the article thumbnail image, if available."
          },
          "publisher": {
            "type": "string",
            "nullable": true,
            "description": "Name of the publisher, if available."
          },
          "authors": {
            "type": "array",
            "description": "List of article authors. May be empty when no author is available.",
            "items": {
              "type": "string"
            }
          },
          "topics": {
            "type": "array",
            "description": "Topics associated with the article.",
            "items": {
              "type": "string"
            }
          },
          "countries": {
            "type": "array",
            "description": "Countries associated with the article.",
            "items": {
              "type": "string"
            }
          },
          "languages": {
            "type": "array",
            "description": "Languages associated with the article.",
            "items": {
              "type": "string"
            }
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication datetime of the article."
          },
          "original_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Original URL of the article on the publisher website, if available."
          },
          "incipit": {
            "type": "string",
            "nullable": true,
            "description": "Short introduction or summary of the article."
          },
          "body": {
            "type": "string",
            "nullable": true,
            "description": "Full extracted body of the article."
          }
        },
        "required": [
          "uuid",
          "title",
          "thumbnail",
          "publisher",
          "authors",
          "topics",
          "countries",
          "languages",
          "published_at",
          "original_url",
          "incipit",
          "body"
        ]
      },
      "LookupItem": {
        "type": "object",
        "description": "Single lookup item returned by publisher or author search.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier of the entity."
          },
          "name": {
            "type": "string",
            "description": "Display name of the entity."
          }
        },
        "required": [
          "uuid",
          "name"
        ]
      },
      "LookupResponse": {
        "type": "object",
        "description": "Paginated response returned by publisher and author lookup endpoints.",
        "properties": {
          "data": {
            "type": "array",
            "description": "List of matching results.",
            "items": {
              "$ref": "#/components/schemas/LookupItem"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/LookupMeta"
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "LookupMeta": {
        "type": "object",
        "description": "Metadata describing the current lookup response.",
        "properties": {
          "q": {
            "type": "string",
            "description": "Original search string used for the lookup."
          },
          "offset": {
            "type": "integer",
            "description": "Offset used for the current page."
          },
          "page_size": {
            "type": "integer",
            "example": 10,
            "description": "Maximum number of results returned per page."
          },
          "returned": {
            "type": "integer",
            "description": "Number of results returned in the current response."
          },
          "has_more": {
            "type": "boolean",
            "description": "Indicates whether more results are available."
          },
          "next_offset": {
            "type": "integer",
            "nullable": true,
            "description": "Offset to request the next page."
          },
          "tokens": {
            "type": "array",
            "description": "Normalized search tokens used for matching.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "q",
          "offset",
          "page_size",
          "returned",
          "has_more",
          "next_offset",
          "tokens"
        ]
      },
      "LanguagesResponse": {
        "type": "object",
        "description": "Response returned by the languages endpoint for a given country.",
        "properties": {
          "data": {
            "type": "array",
            "description": "List of available language codes for the requested country.",
            "items": {
              "type": "string"
            }
          },
          "meta": {
            "type": "object",
            "description": "Metadata describing the language lookup response.",
            "properties": {
              "country": {
                "type": "string",
                "description": "Country code used for the lookup."
              },
              "returned": {
                "type": "integer",
                "description": "Number of languages returned."
              }
            },
            "required": [
              "country",
              "returned"
            ]
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "TopicsResponse": {
        "type": "object",
        "description": "Response returned by the topics endpoint.",
        "properties": {
          "data": {
            "type": "array",
            "description": "List of currently available topics.",
            "items": {
              "type": "string"
            }
          },
          "meta": {
            "type": "object",
            "description": "Metadata describing the topics response.",
            "properties": {
              "returned": {
                "type": "integer",
                "description": "Number of topics returned."
              },
              "warning": {
                "type": "string",
                "description": "Warning that topic availability may vary over time and by country."
              }
            },
            "required": [
              "returned",
              "warning"
            ]
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard error response.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrorResponseExtended": {
        "type": "object",
        "description": "Extended error response used when additional retry information is available.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "retry_after_ms": {
            "type": "integer",
            "nullable": true,
            "description": "Milliseconds to wait before retrying the request, when applicable."
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your personal API key."
      }
    }
  }
}
