RSSBox includes a small management API for third-party integrations. It is disabled by default and must be enabled explicitly.
Enable The API
Set these environment variables:
EXTERNAL_API_ENABLED=1
EXTERNAL_API_TOKEN=replace-with-a-long-random-token
When enabled, the API base path is /api/v1/.
If EXTERNAL_API_ENABLED is unset or not 1, all API endpoints return 404.
If the API is enabled but EXTERNAL_API_TOKEN is missing, all API endpoints return 503.
Authentication
Use a Bearer token:
Authorization: Bearer <your-token>
Missing or invalid tokens return 401.
MVP Endpoints
GET /api/v1/feedsGET /api/v1/feeds/{id}POST /api/v1/feedsPATCH /api/v1/feeds/{id}DELETE /api/v1/feeds/{id}POST /api/v1/feeds/{id}/refreshGET /api/v1/tagsPOST /api/v1/tagsPATCH /api/v1/tags/{id}DELETE /api/v1/tags/{id}POST /api/v1/feeds/{id}/tags
Exposed Feed Fields
The API only exposes minimal safe fields:
idnamefeed_urlslugtarget_languageupdate_frequencymax_postsfetch_articletranslate_titletranslate_contentsummarytranslation_displayfetch_statustranslation_statuslast_fetchlast_translatetags
Internal logs, etags, token counters, agent configuration, and other internal-only fields are not exposed.
For write operations only, you may also provide:
translator_option:"<content_type_id>:<agent_id>", used to configure the feed's translatorsummarizer_id: an existing validOpenAIAgentid used for summaries
These configuration fields are write-only and are not returned in API responses. This MVP still does not include an agent listing API, so integrations must obtain those ids from an existing admin or database workflow.
Curl Examples
List feeds:
curl -H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
http://localhost:8000/api/v1/feeds
Create a feed:
curl -X POST \
-H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"feed_url": "https://example.com/rss.xml",
"name": "Example Feed",
"update_frequency": 30,
"translate_title": true,
"translator_option": "12:34"
}' \
http://localhost:8000/api/v1/feeds
Patch a feed:
curl -X PATCH \
-H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Renamed Feed", "summary": true, "summarizer_id": 56}' \
http://localhost:8000/api/v1/feeds/1
Queue a refresh:
curl -X POST \
-H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
http://localhost:8000/api/v1/feeds/1/refresh
Replace a feed's tag set:
curl -X POST \
-H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"tag_ids": [1, 2]}' \
http://localhost:8000/api/v1/feeds/1/tags
Create a tag:
curl -X POST \
-H "Authorization: Bearer $EXTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Tech"}' \
http://localhost:8000/api/v1/tags
Local Verification Notes
- The refresh endpoint reuses the existing RSSBox update pipeline.
- In
DEBUG=0or other production-like settings, Django cache is configured to use Redis viaREDIS_URL. - After the main refresh work succeeds, RSSBox tries to warm feed and tag caches. If Redis is unavailable, you will see log messages such as
Failed to cache RSS ...orFailed to cache tag .... - Those cache errors do not roll back the core fetch, translation, summary, or database updates. The main refresh work finishes first.
- What remains incomplete is cache warm-up. If Redis stays unavailable, cache-backed RSS/tag output endpoints may fail until Redis is reachable again.
- For local API verification, either use
uv run dev/DEBUG=1so Django falls back to its local in-process cache, or run Redis and setREDIS_URLexplicitly.
MVP Limitations
- Feed
createandpatchonly save configuration. They do not fetch, translate, or summarize content automatically. - The
refreshendpoint only queues asynchronous work. A202response means accepted, not completed. - There is no pagination, filter management API, agent management API, digest API, or task status API in this MVP.
- AI weekly and digest APIs are explicitly out of scope.
Explicitly Out Of Scope
- AI weekly or digest API
- Unrelated refactors
- Frontend or admin redesign
- Large architecture changes