# RSS Feed Reader: RSS, Atom & JSON Feeds, Keyword Alerts (`rookdev/rss-feed-monitor`) Actor

Read any RSS, Atom or JSON feed, or paste a website and its feed is found. Get every item, or schedule it to get only new items since the last run, filtered by keywords, with one-line summaries ready for Slack.

- **URL**: https://apify.com/rookdev/rss-feed-monitor.md
- **Developed by:** [Rook Dev](https://apify.com/rookdev) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 feed items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## RSS Feed Reader: RSS, Atom & JSON Feeds, Keyword Alerts

**Get every item from any RSS, Atom or JSON feed as clean rows, or schedule it and get only the new items since the last run, filtered by your keywords, with one-line alerts ready for Slack.**

- **Any feed, or just the website.** RSS 2.0, RSS 1.0 (RDF), Atom and JSON Feed. Paste a website instead and the Actor finds the feed it links to, or (for a bare domain) tries `/feed`, `/rss.xml`, `/feed.xml`, `/atom.xml` and `/index.xml`.
- **Monitoring built in.** Turn on *Only new items since the last run*, schedule it, and you pay only for items you have not received before. Feeds drop old items all the time, so nothing is ever reported as "removed" and an item that briefly disappears does not come back as new.
- **Keyword alerts that make sense.** Whole-word, any-case matching on title, description and categories: `AI` finds "AI-powered" but not "said". Add exclusions, a "published within N days" filter, and pay only for the items that match.
- **One story, one row.** Stable ids even for feeds that change their item ids (the BBC adds a counter such as `#0` or `#4` to the same story), so you are not alerted or charged twice. A site that is down for maintenance, or a feed that moves, never makes old items come back as new.
- **Alerts out of the box.** Every row has a one-line `summary`, and the run's status message lists the first new items, so the built-in Slack integration posts "New in BBC News: …" with no extra tools.

It reads only the feeds themselves: one request per feed (a website adds its home page and the usual feed locations). No browser and no proxies, so runs take seconds and cost little.

### Sample output

```json
{
  "status": "new",
  "summary": "New in BBC News: Google value plunges by $500bn as AI fears rattle Wall Street https://www.bbc.co.uk/news/articles/cm9qzdqpxy48o?at_medium=RSS&at_campaign=rss",
  "feedUrl": "https://feeds.bbci.co.uk/news/technology/rss.xml",
  "feedTitle": "BBC News",
  "itemId": "https://www.bbc.co.uk/news/articles/cm9qzdqpxy48o",
  "title": "Google value plunges by $500bn as AI fears rattle Wall Street",
  "url": "https://www.bbc.co.uk/news/articles/cm9qzdqpxy48o?at_medium=RSS&at_campaign=rss",
  "publisher": null,
  "publisherUrl": null,
  "publishedAt": "2026-10-29T21:52:13Z",
  "updatedAt": null,
  "description": "Google spooked investors so badly that its stock hit a six-month low, after it revealed its AI search summaries were affecting ad revenue.",
  "categories": [],
  "imageUrl": "https://ichef.bbci.co.uk/ace/standard/240/cpsprodpb/3304/live/1c4d6e00-d3d4-11f1-b441-2b33b063138f.jpg",
  "firstSeenAt": "2026-10-29T22:30:00Z",
  "scrapedAt": "2026-10-29T22:30:00Z"
}
```

A real row from the BBC Technology feed, monitored with the keyword `AI`. Dates are converted to UTC ISO 8601 whatever the feed uses (`Thu, 29 Oct 2026 21:52:13 GMT`, `+0200`, `CEST`, ISO 8601).

### Who uses it

- **PR and communications teams:** media monitoring of news sites and trade press for your brand, clients or competitors, as Slack alerts.
- **Marketers and content teams:** every new post on competitor and industry blogs, in one sheet, every morning.
- **Analysts and investors:** press releases, regulators' and central banks' news feeds, filtered by company names or topics.
- **Developers and newsletter builders:** clean, de-duplicated JSON from hundreds of feeds for an aggregator, a search index or an LLM pipeline.
- **AI agents:** a narrow, predictable tool for "what is new on these sites about X?"; works through the Apify MCP server.

### How to use it

1. Paste feeds or websites into **Feed URLs or websites**, one per line, for example `https://feeds.bbci.co.uk/news/technology/rss.xml` or `example.com/blog`. For news coverage of a company or topic, follow the news sites' own feeds and add your company or topic as keywords.
2. Optionally add **Only items mentioning** (keywords), **Skip items mentioning** and **Published within the last N days**.
3. Click **Start**. Download the results as JSON, CSV or Excel, or read them through the API.

**To monitor:** turn on **Only new items since the last run**, save the input as a task and add a schedule (hourly or daily). The first run returns every current item marked `new` (or, with **Start quietly**, just records them for the price of the feed check); after that you get only new items. Connect the task to Slack, email, Google Sheets, Make, Zapier or n8n to get alerts.

#### Input examples

All items from two feeds:

```json
{ "feeds": ["https://feeds.bbci.co.uk/news/technology/rss.xml", "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml"] }
```

Hourly keyword alerts from news sites and a competitor's blog, starting quietly:

```json
{
  "feeds": ["https://feeds.bbci.co.uk/news/business/rss.xml", "competitor.com/blog"],
  "keywords": ["acquisition", "Acme Corp", "regulat*"],
  "excludeKeywords": ["podcast", "sponsored"],
  "onlyNew": true,
  "skipExistingOnFirstRun": true
}
```

#### Inputs

| Input | What it does | Default |
| --- | --- | --- |
| `feeds` | Feed URLs (RSS, RDF, Atom, JSON Feed) or websites, one per line | required |
| `keywords` | Keep only items whose title, description or categories mention any of these (whole words, any case, `*` for any ending) | all items |
| `excludeKeywords` | Drop items that mention any of these | none |
| `publishedWithinDays` | Keep only items published in the last N days (0 = any date) | 0 |
| `onlyNew` | Monitoring: only items not received before | off |
| `skipExistingOnFirstRun` | Monitoring: the first run records today's items without returning them | off |
| `reportUpdates` | Monitoring: also return known items whose title or updated date changed (`changed`, with the previous values) | off |
| `maxItemsPerFeed` | Newest N matching items kept per feed (changing it keeps the monitoring memory) | 200 |
| `includeContent` | Add the summary as plain text (about 1,000 characters) | on |
| `stateStoreName`, `maxConcurrency` | Advanced: monitoring memory name, feeds read in parallel | defaults work |

#### Which inputs work

| You enter | What happens |
| --- | --- |
| A feed URL, with or without `.xml`, for example `https://feeds.bbci.co.uk/news/rss.xml` | That feed is read |
| A bare domain, for example `example.com` | The feed its home page links to (`<link rel="alternate">`; comment feeds only if nothing else is linked); if the page links none, `/feed`, `/rss.xml`, `/feed.xml`, `/atom.xml`, `/index.xml` |
| A page, for example `https://example.com/blog` | The feed the page links to |
| A news.google.com link | Refused with a free `invalid_input` row: Google's terms allow its news feeds for personal, non-commercial use only |

Inputs that cannot be used produce a free row with `status: invalid_input`, `not_found` or `error` and a plain-English `error`. The Actor never guesses around trouble: a home page that answers with an error (403, 503), or a feed URL that answers with a web page (a maintenance page), is an error row, not a reason to read some other feed. When monitoring, a website whose page links no feed on one run (a maintenance page that still answers 200) is read through the feed it linked before, never a guessed one.

The same feed entered twice, or a website together with its own feed, is read and charged once: a feed URL wins over a website, then the earlier input. The other input gets no row (`RUN_SUMMARY` lists it as `duplicate`) and is not counted as a problem. Both share one monitoring memory, because memory is kept per feed: if the feed URL fails on one run and the website reads the same feed, nothing is sent again.

### Output

One row per item: `status`, `summary`, `feedUrl`, `feedTitle`, `itemId`, `title`, `url`, `publisher` and `publisherUrl` (for feeds that name a source, such as news aggregators), `publishedAt`, `updatedAt`, `description`, `categories`, `imageUrl`, `firstSeenAt` (monitoring) and `scrapedAt`. `status` is `current` in a normal run and `new` (or `changed`, with `previousTitle` and `previousUpdatedAt`) when monitoring. Items come newest first. Author names and emails are never included. Inputs that produced no items get a free row with `status` `invalid_input`, `not_found`, `error` or `skipped` (not checked because your spending limit was reached or the run stopped early; one row for all of them, see the FAQ); an input that leads to a feed already read for another input gets no row.

A `RUN_SUMMARY` record in the run's key-value store lists every input with the feed that was read, its format, how it was found, and how many items it had and matched.

### Get alerts in Slack, Google Drive, Make, Zapier or n8n

1. Turn on monitoring, click **Save as a new task**, and add a schedule to the task.
2. On the task's **Integrations** tab, pick **Slack**, connect your workspace, choose the **Run succeeded** event and a channel, and paste this as the message:

```handlebars
*{{resource.statusMessage}}*
<https://console.apify.com/storage/datasets/{{resource.defaultDatasetId}}|Open all items>
```

The status message reads like *Checked 3 feed(s), saved 2 item row(s) (2 new). New in BBC News: Google value plunges by $500bn as AI fears rattle Wall Street https://www.bbc.co.uk/news/articles/…* so the alert itself has the headline and the link.

- **Google Drive:** the **Upload results to GDrive** integration saves each run's rows as CSV or JSON.
- **Make, Zapier, n8n:** use the Apify app's "Actor run finished" trigger and map the `summary`, `title` and `url` fields into a message, a sheet row or a CRM note.
- **Webhooks:** send the run to your own endpoint and read the dataset through the API.

### Pricing

Pay per event, no platform usage charges on top:

| Event | Price |
| --- | --- |
| Item returned | $0.50 per 1,000 items |
| Feed checked | $1.00 per 1,000 feeds |

Rows for inputs that could not be used are free. A feed check is charged after its rows are delivered, so if your spending limit stops the run before any of a feed's rows go out, that check is free.

- **One-off export:** 50 news and blog feeds with about 40 items each (2,000 items) cost about **$1.05**: $1.00 for the items and $0.05 for the checks.
- **Hourly keyword alerts:** 25 feeds checked every hour is 600 checks a day ($0.60); with about 20 matching new items a day ($0.01) that is about **$0.61 a day, about $18 a month**. Checked every 6 hours instead: about **$3.30 a month**. You never pay for items you already received (changing the max items per feed, or a site's maintenance page, does not re-send them) or for items that do not match your keywords.

Set a maximum cost per run in the run options and the Actor stops cleanly when it reaches it: a feed is read only when the limit still covers its check and one item ($0.0015), feeds it could not check share one free `skipped` row, and when monitoring, new items it could not deliver come on the next run. Rows it delivered are never charged twice.

### FAQ

**Is this allowed?** Feeds are published so that readers and other software can follow a site; the Actor reads only those feeds (plus, for a website input, the home page and the usual feed locations), one request at a time per feed, with no login. Author names and emails are left out. Feed content still belongs to its publisher: follow each publisher's terms for reuse (the BBC, for example, publishes its own terms for its feeds) and the terms of any service you send results to.

**Why are items never reported as removed?** A feed shows only the latest items, so items leave it all the time; that is not news. The Actor remembers each item until 30 days after it was last in the feed, so an item that drops out and comes back (or a feed that is briefly empty) is not reported again, however long the item has been listed.

**The BBC (or another site) lists the same story twice. Do I pay twice?** No. When a feed's item id is the article's address plus a counter while its link is that address with tracking parameters (the BBC uses `#0`, `#1`, … and the same story can appear as `#0` and `#4` in one feed), the counter is ignored, so one story is one row. Posts whose ids are anchors on the very page they link to (a live blog's updates) keep their own ids, even when every link carries `?utm_source=rss`. Items that share one id but link to different pages (deal-of-the-day and chart feeds reuse one) are told apart: the item first seen under that id keeps it, and each of the others gets the id plus its link. So an item you already received does not come again when it leaves and returns or is retitled, and a new item that reuses an old id is never missed. One trade-off: a page that moves to a new address while keeping its id is sent once more, because it looks exactly like a new item reusing the id (tracking tags and session ids in links are ignored). Ids made from links ignore `utm_` tracking parameters and http versus https.

**I follow several feeds of one site. Will a story in two of them come twice?** Yes, once per feed: each feed has its own memory, so a story the BBC lists in both News and Technology arrives from both. Follow the narrower feeds, or use keywords, if that is too noisy.

**How do keywords match?** Whole words or phrases in the title, description and categories, any case. `AI` matches "AI" and "AI-powered" but not "said" or "MAIN"; `regulat*` matches "regulation" and "regulators"; `machine learning` matches across line breaks. A straight apostrophe matches curly ones (`McDonald's` finds "McDonald’s"). When a feed's description holds only an image, the full content is searched instead. Keywords in languages written without spaces (Chinese, Japanese) match anywhere in the text. Changing keywords, exclusions or the date window starts a fresh monitoring memory, so a new filter does not hide items you have not received yet (turn on **Start quietly** to skip that fresh start's first batch). Changing the max items per feed keeps the memory: lowering it sends nothing again, and after a raise the older items it brings in (dated before the oldest item of the previous run) are recorded without being sent, while items published since the previous run still come.

**A website has several feeds. Which one is read?** The first feed its page links to (comment feeds only when the page links nothing else). To choose, paste that feed's URL. The `feedUrl` column and `RUN_SUMMARY` show which feed was used. If the home page or the linked feed is down, the run reports an error for that input rather than quietly switching to another feed, so a monitor never mistakes a different feed for new items. When monitoring, the Actor remembers which feed each website led to: if the page links no feed on a run (a maintenance page), that feed is read again. If the site starts linking a different feed, its first feed is missing for a run, or a feed URL redirects to a new address, the memory comes along (and back again), so items with the same ids are not sent again. Items with ids you have not received are new, even with **Start quietly** on: a site that switches to a genuinely different feed (say from its news feed to its podcast) sends that feed's current items once.

**What about broken feeds?** Common mistakes that feed readers forgive are repaired: HTML entities such as `&nbsp;`, unescaped `&`, control characters, Windows-1252 characters in a UTF-8 or Latin-1 feed (curly quotes, `é`), namespace prefixes used without being declared, a byte-order mark or a PHP warning before the XML, gzip, UTF-16 and Shift_JIS or GB2312 encodings. One item with a malformed link never costs the rest of the feed. Dates with `+02:00` offsets, `9:52 PM` times and zone names such as `CEST` or `SAST` are converted correctly; a zone name the Actor does not know leaves the date as written rather than guessing UTC. A feed that stamps every item with the same date (its build time) has those dates ignored, so a rebuild is never reported as updates. Documents that declare entities are refused (that blocks entity-expansion attacks), and a feed cut off mid-download is an error, never a short list.

**Why is the first monitoring run bigger?** Nothing has been seen yet, so every current item counts as new. Turn on **Start quietly** to skip that. Each saved task, and each combination of filters, keeps its own memory, and normal (non-monitoring) runs never touch it.

**Can it monitor Google News?** No. Google's terms allow its news feeds for personal, non-commercial use only, so this paid Actor does not read them: a news.google.com link gets a free `invalid_input` row, and a page that links or redirects to Google News is not followed there. Follow the news sites' own feeds instead (most publishers have them) and use keywords to pick out your company or topic. Feeds that name a source (`<source>` in RSS, common in aggregators) fill `publisher` and `publisherUrl`.

**Why did my run stop early?** Four limits can end a run before every input is checked, and none of them charges you for what was not checked: If one Apify account's runs keep producing nothing to charge (for example a list of dead sites run again and again), new runs from that account stop early for up to 24 hours, with a free row that says so; normal use never gets near this.

- *Your spending limit.* A feed is read only when the run's maximum cost still covers one feed check and one item ($0.0015); the rest share one free `skipped` row and come on the next run.
- *Many failures in a row.* After 50 feeds in a row fail (not found, errors, timeouts), the list or the sites are probably down, so the run stops and the rest share one free `skipped` row. A site that fails 10 times in a row is not called again in that run.
- *A safety limit.* A run that does a lot of work without returning anything you pay for (for example thousands of dead feeds, or keywords that match nothing in huge feeds) stops after a few minutes of such work, with one free `skipped` row. Runs that return items are never stopped by it.
- *Too many inputs.* A run checks at most 1,000 feeds or websites (the first ones entered); split longer lists across several tasks. Keyword and exclusion lists take up to 100 entries each.

The status message and `RUN_SUMMARY` (`stoppedEarly`, `notChecked`, `skippedBySpendingLimit`) say which one it was.

**Can it read feeds on my own network or server?** Only public ones. Addresses on private networks and the local machine (`localhost`, `127.0.0.1` or `127.1`, `10.x.x.x`, `192.168.x.x`, cloud metadata such as `169.254.169.254`, and names ending in `.local` or `.internal`) are refused with a free `invalid_input` row, whatever the spelling. The same check runs after the name is looked up and on every redirect, so a public URL that redirects to a private address gets a free `error` row instead. Publish the feed on a public address to monitor it.

**Can I use it from code or an AI agent?** Yes: through the Apify API, the Python and JavaScript clients, or the Apify MCP server. Inputs and outputs are stable and documented above.

### Support

Open an issue on the Issues tab with the feed or website you tried; I aim to answer within a day.

# Changelog

This Actor's version history is a separate document: https://apify.com/rookdev/rss-feed-monitor/changelog.md

# Actor input Schema

## `feeds` (type: `array`):

One per line. A feed URL (RSS 2.0, RSS 1.0/RDF, Atom or JSON Feed), for example https://feeds.bbci.co.uk/news/technology/rss.xml, is read as it is. A website or page (example.com or https://example.com/blog) is searched for the feed it links to; for a bare domain that links none, /feed, /rss.xml, /feed.xml, /atom.xml and /index.xml are tried. At most 1,000 per run (more are listed in one free row and not checked). Only public addresses are read: localhost, private networks and cloud metadata addresses are refused. Google News is not supported (its terms allow personal, non-commercial use only).

## `keywords` (type: `array`):

Keep only items whose title, description or categories contain any of these words or phrases. Whole words, any case: AI matches "AI-powered" but not "said". Add \* for any ending: regulat\* matches regulation and regulators. Up to 100 entries of up to 200 characters. Leave empty for all items.

## `excludeKeywords` (type: `array`):

Drop items whose title, description or categories contain any of these words or phrases (same matching as above), for example sponsored or podcast. Up to 100 entries of up to 200 characters.

## `publishedWithinDays` (type: `integer`):

Keep only items published (or, if they have no publish date, updated) in the last N days. Items without a readable date are left out when this is set. 0 means any date.

## `onlyNew` (type: `boolean`):

Turn on, save as a task and schedule it to get only items that appeared since the previous run (status new). Items that drop off the end of a feed are never reported as removed. The first run returns everything as new. Normal runs never touch this memory.

## `skipExistingOnFirstRun` (type: `boolean`):

Monitoring only: the first run records the items in each feed today without returning or charging for them (you pay only the feed check), so you get only new items from the second run on.

## `reportUpdates` (type: `boolean`):

Monitoring only: also return items you have already seen whose title or updated date changed (status changed, with the previous title and date). Off by default, because news feeds retitle stories often.

## `maxItemsPerFeed` (type: `integer`):

Keep only the newest N matching items of each feed, to cap costs. When monitoring, new items further down a long feed are skipped, not saved for later. Changing it keeps the monitoring memory: after a raise, the older items it brings in are recorded without being sent.

## `includeContent` (type: `boolean`):

Add the item's summary as plain text (HTML removed, cut to about 1,000 characters) in the description column. Turn off for lighter rows; keyword filters still read the full text.

## `stateStoreName` (type: `string`):

Key-value store that remembers which items you have already received (lowercase letters, digits and hyphens). Each saved task and each combination of filters keeps its own memory inside it, so the default works for most people.

## `maxConcurrency` (type: `integer`):

How many feeds to read at the same time. Each feed is a single request (a website adds a few), so the default is fine for hundreds of feeds.

## Actor input object example

```json
{
  "feeds": [
    "https://feeds.bbci.co.uk/news/technology/rss.xml",
    "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml"
  ],
  "publishedWithinDays": 0,
  "onlyNew": false,
  "skipExistingOnFirstRun": false,
  "reportUpdates": false,
  "maxItemsPerFeed": 20,
  "includeContent": true,
  "stateStoreName": "rss-feed-monitor-state",
  "maxConcurrency": 10
}
```

# Actor output Schema

## `results` (type: `string`):

One row per feed item

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "feeds": [
        "https://feeds.bbci.co.uk/news/technology/rss.xml",
        "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml"
    ],
    "maxItemsPerFeed": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("rookdev/rss-feed-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "feeds": [
        "https://feeds.bbci.co.uk/news/technology/rss.xml",
        "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml",
    ],
    "maxItemsPerFeed": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("rookdev/rss-feed-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "feeds": [
    "https://feeds.bbci.co.uk/news/technology/rss.xml",
    "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml"
  ],
  "maxItemsPerFeed": 20
}' |
apify call rookdev/rss-feed-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rookdev/rss-feed-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/U2Y8AWn6BMtUL5799/builds/8OhslMMws44sEs9lU/openapi.json
