commafeed-api

CommaFeed REST API Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "commafeed-api" with this command: npx skills add biggora/claude-plugins-registry/biggora-claude-plugins-registry-commafeed-api

CommaFeed REST API Skill

Interact with a self-hosted CommaFeed RSS reader instance via its REST API.

Environment Variables (REQUIRED)

Before making any API calls, ensure these environment variables are set:

Variable Description Example

COMMAFEED_HOST

CommaFeed instance URL (with protocol, no trailing slash) https://commafeed.example.com

COMMAFEED_USER

CommaFeed username admin

COMMAFEED_PASS

CommaFeed password secretpass

export COMMAFEED_HOST="https://commafeed.example.com" export COMMAFEED_USER="admin" export COMMAFEED_PASS="your-password"

If these are not set, ask the user to provide them before proceeding.

Authentication

All requests use HTTP Basic Auth:

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/get" | jq .

Every request pattern below assumes:

  • Base URL: $COMMAFEED_HOST/rest

  • Auth: -u "$COMMAFEED_USER:$COMMAFEED_PASS"

  • Content-Type: application/json (for POST requests with JSON body)

Helper alias for examples:

CF="curl -s -u $COMMAFEED_USER:$COMMAFEED_PASS"

API Endpoints

Categories

Method Path Description

GET /rest/category/get

Get root category tree (all categories + subscriptions)

POST /rest/category/add

Add a new category

POST /rest/category/modify

Rename or move a category

POST /rest/category/delete

Delete a category

POST /rest/category/collapse

Collapse/expand a category in the UI

GET /rest/category/entries

Get entries for a category

GET /rest/category/entriesAsFeed

Get category entries as RSS/Atom XML

POST /rest/category/mark

Mark all entries in a category as read

GET /rest/category/unreadCount

Get unread count per subscription

Get category tree (all subscriptions)

Returns the full tree: root category with nested children and feed subscriptions.

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/get" | jq .

Response — Category object:

{ "id": "all", "name": "All", "children": [ { "id": "10", "parentId": "all", "name": "Tech", "children": [], "feeds": [ { "id": 42, "name": "Hacker News", "feedUrl": "https://news.ycombinator.com/rss", "feedLink": "https://news.ycombinator.com", "iconUrl": "/rest/feed/favicon/42", "unread": 15, "categoryId": "10", "position": 0, "newestItemTime": "2026-03-07T10:30:00Z", "errorCount": 0, "lastRefresh": "2026-03-07T10:00:00Z", "nextRefresh": "2026-03-07T10:15:00Z" } ], "expanded": true, "position": 0 } ], "feeds": [], "expanded": true, "position": 0 }

Add a category

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"name": "Technology", "parentId": "all"}'
"$COMMAFEED_HOST/rest/category/add" | jq .

Request body — AddCategoryRequest :

  • name (string, required, max 128 chars) — category name

  • parentId (string, optional) — parent category ID, omit for root level

Response: category ID (integer).

Modify a category

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": 10, "name": "Tech News", "parentId": "all", "position": 0}'
"$COMMAFEED_HOST/rest/category/modify"

Request body — CategoryModificationRequest :

  • id (integer, required) — category ID

  • name (string) — new name

  • parentId (string) — new parent category ID

  • position (integer) — position in parent

Delete a category

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": 10}'
"$COMMAFEED_HOST/rest/category/delete"

Request body — IDRequest :

  • id (integer, required) — category ID

Get category entries

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=all&readType=unread&limit=20&order=desc" | jq .

Query parameters:

  • id (required) — category ID, "all" for all feeds, or "starred" for starred entries

  • readType (required) — all or unread

  • limit (integer, default 20, max 1000) — entries per page

  • offset (integer, default 0) — pagination offset

  • order (string, default desc ) — desc or asc

  • newerThan (long) — Unix timestamp in ms, only entries newer than this

  • keywords (string) — search filter

  • tag (string) — filter by tag

  • excludedSubscriptionIds (string) — comma-separated subscription IDs to exclude

Response — Entries object:

{ "name": "All", "entries": [ { "id": "feed/42:entry/abc123", "guid": "https://example.com/article-1", "title": "Article Title", "content": "<p>Article HTML content...</p>", "author": "John Doe", "date": "2026-03-07T09:00:00Z", "insertedDate": "2026-03-07T09:05:00Z", "url": "https://example.com/article-1", "feedId": "42", "feedName": "Example Feed", "feedUrl": "https://example.com/rss", "feedLink": "https://example.com", "iconUrl": "/rest/feed/favicon/42", "read": false, "starred": false, "markable": true, "tags": [], "categories": "tech, news", "rtl": false, "enclosureUrl": null, "enclosureType": null, "mediaThumbnailUrl": null } ], "timestamp": 1741339200000, "hasMore": true, "offset": 0, "limit": 20, "errorCount": 0, "ignoredReadStatus": false }

Get unread counts

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/unreadCount" | jq .

Response — array of UnreadCount :

[ {"feedId": 42, "unreadCount": 15}, {"feedId": 55, "unreadCount": 3} ]

Mark category as read

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": "all", "olderThan": 1741339200000, "read": true}'
"$COMMAFEED_HOST/rest/category/mark"

Request body — MarkRequest :

  • id (string, required) — category ID or "all"

  • read (boolean) — true to mark read, false for unread

  • olderThan (long) — timestamp, mark only entries older than this

  • insertedBefore (long) — mark only entries inserted before this

  • keywords (string) — filter by keywords

Collapse/expand category

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": 10, "collapse": true}'
"$COMMAFEED_HOST/rest/category/collapse"

Feed Subscriptions

Method Path Description

POST /rest/feed/subscribe

Subscribe to a feed

POST /rest/feed/unsubscribe

Unsubscribe from a feed

POST /rest/feed/modify

Modify subscription (rename, move, filter)

GET /rest/feed/get/{id}

Get subscription details

POST /rest/feed/fetch

Fetch feed info by URL (preview before subscribing)

GET /rest/feed/refreshAll

Queue all feeds for refresh

GET /rest/feed/entries

Get entries for a specific feed

GET /rest/feed/entriesAsFeed

Get feed entries as RSS/Atom XML

POST /rest/feed/mark

Mark feed entries as read

GET /rest/feed/favicon/{id}

Get feed favicon

GET /rest/feed/export

Export all subscriptions as OPML

POST /rest/feed/import

Import subscriptions from OPML file

Subscribe to a feed

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "url": "https://example.com/rss", "title": "Example Blog", "categoryId": 10 }'
"$COMMAFEED_HOST/rest/feed/subscribe" | jq .

Request body — SubscribeRequest :

  • url (string, required) — feed URL

  • title (string, required) — display name

  • categoryId (integer) — target category ID

Response: subscription ID (integer).

Unsubscribe from a feed

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": 42}'
"$COMMAFEED_HOST/rest/feed/unsubscribe"

Modify a subscription

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "id": 42, "name": "New Feed Name", "categoryId": 10, "position": 0, "filter": "title.contains("important")", "pushNotificationsEnabled": false, "autoMarkAsReadAfterDays": 30 }'
"$COMMAFEED_HOST/rest/feed/modify"

Request body — FeedModificationRequest :

  • id (integer, required) — subscription ID

  • name (string) — new display name

  • categoryId (integer) — move to a different category

  • position (integer) — position in category

  • filter (string) — CEL expression to auto-mark entries as read

  • pushNotificationsEnabled (boolean) — enable push notifications

  • autoMarkAsReadAfterDays (integer) — auto-mark read after N days (null to disable)

Get subscription details

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/feed/get/42" | jq .

Response — Subscription object:

{ "id": 42, "name": "Hacker News", "message": null, "errorCount": 0, "lastRefresh": "2026-03-07T10:00:00Z", "nextRefresh": "2026-03-07T10:15:00Z", "feedUrl": "https://news.ycombinator.com/rss", "feedLink": "https://news.ycombinator.com", "iconUrl": "/rest/feed/favicon/42", "unread": 15, "categoryId": "10", "position": 0, "newestItemTime": "2026-03-07T10:30:00Z", "filter": null, "pushNotificationsEnabled": false, "autoMarkAsReadAfterDays": null }

Fetch feed info (preview)

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"url": "https://example.com/rss"}'
"$COMMAFEED_HOST/rest/feed/fetch" | jq .

Request body — FeedInfoRequest :

  • url (string, required, 1–4096 chars) — feed URL to probe

Response — FeedInfo : title, url, link for the discovered feed.

Refresh all feeds

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/feed/refreshAll"

Note: Returns 429 Too Many Requests if called too frequently.

Get feed entries

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/feed/entries?id=42&readType=unread&limit=50&order=desc" | jq .

Query parameters (same pattern as category entries):

  • id (required) — subscription ID

  • readType (required) — all or unread

  • limit (integer, default 20, max 1000)

  • offset (integer, default 0)

  • order — desc or asc

  • newerThan (long) — Unix timestamp in ms

  • keywords (string) — search filter

Response: Entries object (same structure as category entries).

Mark feed as read

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": "42", "read": true}'
"$COMMAFEED_HOST/rest/feed/mark"

OPML Export

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/feed/export" -o subscriptions.opml

Response: OPML XML file.

OPML Import

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-F "file=@subscriptions.opml"
"$COMMAFEED_HOST/rest/feed/import"

Note: Uses multipart/form-data , not JSON.

Entries (individual entry operations)

Method Path Description

POST /rest/entry/mark

Mark a single entry as read/unread

POST /rest/entry/markMultiple

Mark multiple entries at once

POST /rest/entry/star

Star/unstar an entry

POST /rest/entry/tag

Set tags on an entry

GET /rest/entry/tags

Get all user tags

Mark entry as read/unread

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": "feed/42:entry/abc123", "read": true}'
"$COMMAFEED_HOST/rest/entry/mark"

Request body — MarkRequest :

  • id (string, required) — entry ID

  • read (boolean) — true = read, false = unread

Mark multiple entries

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "requests": [ {"id": "feed/42:entry/abc123", "read": true}, {"id": "feed/42:entry/def456", "read": true} ] }'
"$COMMAFEED_HOST/rest/entry/markMultiple"

Star/unstar an entry

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "id": "feed/42:entry/abc123", "feedId": 42, "starred": true }'
"$COMMAFEED_HOST/rest/entry/star"

Request body — StarRequest :

  • id (string, required) — entry ID

  • feedId (integer, required) — feed subscription ID

  • starred (boolean, required) — true to star, false to unstar

Tag an entry

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "entryId": 12345, "tags": ["important", "read-later"] }'
"$COMMAFEED_HOST/rest/entry/tag"

Request body — TagRequest :

  • entryId (integer, required) — entry ID

  • tags (array of strings, required) — tags to assign (replaces existing)

Get all user tags

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/entry/tags" | jq .

Response: array of tag strings.

User Profile & Settings

Method Path Description

GET /rest/user/profile

Get user profile

POST /rest/user/profile

Update user profile

POST /rest/user/profile/deleteAccount

Delete own account

GET /rest/user/settings

Get user settings

POST /rest/user/settings

Save user settings

Get profile

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/user/profile" | jq .

Response — UserModel :

{ "id": 1, "name": "admin", "email": "admin@example.com", "apiKey": "abc-123-def-456", "enabled": true, "admin": true }

Update profile

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "currentPassword": "old-pass", "newPassword": "new-pass", "newEmail": "new@example.com" }'
"$COMMAFEED_HOST/rest/user/profile"

Request body — ProfileModificationRequest :

  • currentPassword (string, required) — current password for verification

  • newPassword (string) — new password

  • newEmail (string) — new email

  • newApiKey (boolean) — true to regenerate API key

Get settings

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/user/settings" | jq .

Response — Settings :

{ "language": "en", "readingMode": "unread", "readingOrder": "desc", "showRead": true, "scrollMarks": true, "scrollSpeed": 400, "scrollMode": "if_needed", "customCss": "", "customJs": "", "entriesToKeepOnTopWhenScrolling": 1, "starIconDisplayMode": "always", "externalLinkIconDisplayMode": "always", "markAllAsReadConfirmation": true, "markAllAsReadNavigateToNextUnread": false, "customContextMenu": true, "mobileFooter": false, "unreadCountTitle": true, "unreadCountFavicon": true, "disablePullToRefresh": false, "primaryColor": null, "sharingSettings": { "email": false, "gmail": false, "facebook": false, "twitter": false, "tumblr": false, "pocket": false, "instapaper": false, "buffer": false } }

Settings enums:

  • readingMode : all , unread

  • readingOrder : asc , desc

  • scrollMode : always , never , if_needed

  • starIconDisplayMode / externalLinkIconDisplayMode : always , never , on_desktop , on_mobile

Save settings

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "language": "en", "readingMode": "unread", "readingOrder": "desc", "showRead": false, "scrollMarks": true }'
"$COMMAFEED_HOST/rest/user/settings"

Server Info

Method Path Description

GET /rest/server/get

Get server information (no auth required)

GET /rest/server/proxy

Proxy an image through the server

Get server info

curl -s "$COMMAFEED_HOST/rest/server/get" | jq .

Response — ServerInfo :

{ "announcement": "", "version": "5.x.x", "gitCommit": "abc1234", "loginPageTitle": "CommaFeed", "allowRegistrations": false, "googleAnalyticsTrackingCode": null, "smtpEnabled": false, "demoAccountEnabled": false, "websocketEnabled": true, "websocketPingInterval": 15000, "treeMode": "unread" }

Proxy image

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/server/proxy?u=https://example.com/image.png"
-o proxied-image.png

Admin Endpoints

Require ADMIN role.

Method Path Description

GET /rest/admin/metrics

Get server metrics

GET /rest/admin/user/getAll

List all users

GET /rest/admin/user/get/{id}

Get user by ID

POST /rest/admin/user/save

Create or update a user

POST /rest/admin/user/delete

Delete a user

Get server metrics

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/admin/metrics" | jq .

List all users

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/admin/user/getAll" | jq .

Response: array of UserModel .

Get user by ID

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/admin/user/get/1" | jq .

Create / update user

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "name": "newuser", "password": "securepass123", "email": "user@example.com", "enabled": true, "admin": false }'
"$COMMAFEED_HOST/rest/admin/user/save"

Request body — AdminSaveUserRequest :

  • name (string, required) — username

  • password (string) — password (required for new users)

  • email (string) — email address

  • enabled (boolean, required) — account active

  • admin (boolean, required) — admin role

Delete user

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"id": 5}'
"$COMMAFEED_HOST/rest/admin/user/delete"

Registration & Password Reset

Method Path Description

POST /rest/user/register

Register new account (if allowed)

POST /rest/user/initialSetup

Create initial admin (first-run only)

POST /rest/user/passwordReset

Request password reset email

POST /rest/user/passwordResetCallback

Confirm password reset with token

Register

curl -s -X POST
-H "Content-Type: application/json"
-d '{ "name": "newuser", "password": "mypassword", "email": "user@example.com" }'
"$COMMAFEED_HOST/rest/user/register"

Request: name (3–32 chars), password , email (all required).

Common Patterns

List all feeds with unread counts

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/get" |
jq '[.. | .feeds? // empty | .[] | {id, name, unread, feedUrl}]'

Get all unread entries across all feeds

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=all&readType=unread&limit=100" |
jq '.entries[] | {title, url, feedName, date}'

Get starred entries

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=starred&readType=all&limit=50" |
jq '.entries[] | {title, url, starred, date}'

Search entries by keyword

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=all&readType=all&keywords=kubernetes&limit=50" |
jq '.entries[] | {title, url, feedName}'

Mark all entries as read

Get current timestamp

TS=$(date +%s)000 curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d "{"id": "all", "read": true, "olderThan": $TS}"
"$COMMAFEED_HOST/rest/category/mark"

Subscribe to a feed and put it in a category

1. Fetch feed info to verify URL

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{"url": "https://blog.example.com/feed"}'
"$COMMAFEED_HOST/rest/feed/fetch" | jq .

2. Subscribe

curl -s -X POST
-u "$COMMAFEED_USER:$COMMAFEED_PASS"
-H "Content-Type: application/json"
-d '{ "url": "https://blog.example.com/feed", "title": "Example Blog", "categoryId": 10 }'
"$COMMAFEED_HOST/rest/feed/subscribe" | jq .

Export OPML backup

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/feed/export" -o "commafeed-backup-$(date +%Y%m%d).opml"

Paginate through all entries

OFFSET=0 LIMIT=100 while true; do RESPONSE=$(curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=all&readType=all&limit=$LIMIT&offset=$OFFSET")

COUNT=$(echo "$RESPONSE" | jq '.entries | length') HAS_MORE=$(echo "$RESPONSE" | jq '.hasMore')

echo "$RESPONSE" | jq '.entries[] | {title, date, feedName}'

if [ "$HAS_MORE" = "false" ] || [ "$COUNT" -eq 0 ]; then break fi

OFFSET=$((OFFSET + LIMIT)) done

Get entries by tag

curl -s -u "$COMMAFEED_USER:$COMMAFEED_PASS"
"$COMMAFEED_HOST/rest/category/entries?id=all&readType=all&tag=important&limit=50" |
jq '.entries[] | {title, url, tags}'

Node.js Example

const COMMAFEED_HOST = process.env.COMMAFEED_HOST; const COMMAFEED_USER = process.env.COMMAFEED_USER; const COMMAFEED_PASS = process.env.COMMAFEED_PASS;

const AUTH = 'Basic ' + Buffer.from(${COMMAFEED_USER}:${COMMAFEED_PASS}).toString('base64');

async function cfApi(method, path, body = null) { const url = ${COMMAFEED_HOST}/rest${path}; const options = { method, headers: { 'Authorization': AUTH, 'Content-Type': 'application/json', }, }; if (body) options.body = JSON.stringify(body); const res = await fetch(url, options); if (!res.ok) throw new Error(CommaFeed API ${res.status}: ${await res.text()}); const text = await res.text(); return text ? JSON.parse(text) : null; }

// Get all subscriptions const tree = await cfApi('GET', '/category/get'); console.log(tree);

// Get unread entries const entries = await cfApi('GET', '/category/entries?id=all&readType=unread&limit=20'); for (const e of entries.entries) { console.log([${e.feedName}] ${e.title} — ${e.url}); }

// Subscribe to a feed const subId = await cfApi('POST', '/feed/subscribe', { url: 'https://example.com/rss', title: 'Example Feed', }); console.log('Subscribed, ID:', subId);

// Star an entry await cfApi('POST', '/entry/star', { id: entries.entries[0].id, feedId: parseInt(entries.entries[0].feedId), starred: true, });

Python Example

import os import requests

COMMAFEED_HOST = os.environ["COMMAFEED_HOST"] COMMAFEED_USER = os.environ["COMMAFEED_USER"] COMMAFEED_PASS = os.environ["COMMAFEED_PASS"]

AUTH = (COMMAFEED_USER, COMMAFEED_PASS) HEADERS = {"Content-Type": "application/json"}

def cf_api(method, path, json=None): url = f"{COMMAFEED_HOST}/rest{path}" resp = requests.request(method, url, auth=AUTH, headers=HEADERS, json=json) resp.raise_for_status() return resp.json() if resp.text else None

Get category tree

tree = cf_api("GET", "/category/get") for cat in tree["children"]: print(f"Category: {cat['name']}") for feed in cat["feeds"]: print(f" {feed['name']} — unread: {feed['unread']}")

Get unread entries

entries = cf_api("GET", "/category/entries?id=all&readType=unread&limit=20") for e in entries["entries"]: print(f"[{e['feedName']}] {e['title']}")

Subscribe to a feed

sub_id = cf_api("POST", "/feed/subscribe", { "url": "https://example.com/rss", "title": "Example Feed", }) print(f"Subscribed, ID: {sub_id}")

Export OPML

resp = requests.get(f"{COMMAFEED_HOST}/rest/feed/export", auth=AUTH) with open("backup.opml", "w") as f: f.write(resp.text)

Error Handling

Code Meaning

200 Success

400 Bad request (missing/invalid fields)

401 Not authorized (wrong credentials)

403 Forbidden (insufficient role — need ADMIN)

404 Resource not found (wrong feed/entry/category ID)

429 Too many requests (refreshAll rate limit)

500 Server error

Implementation Notes

  • Always read COMMAFEED_HOST , COMMAFEED_USER , COMMAFEED_PASS from environment variables — never hardcode

  • Authentication is HTTP Basic Auth, not API key headers

  • The /rest/server/get endpoint does not require authentication

  • Entry IDs follow the format feed/{feedId}:entry/{guid} — preserve them as strings

  • Timestamps are in milliseconds (Unix epoch) for newerThan / olderThan parameters

  • OPML import uses multipart/form-data , all other POST endpoints use application/json

  • The readType parameter is required for entry listing endpoints

  • Maximum limit is 1000 entries per request — use offset

  • hasMore for pagination
  • id=all means all feeds, id=starred means starred entries in category endpoints

  • Tags replace the full tag list on an entry — send the complete desired set

  • CEL filter expressions on subscriptions auto-mark non-matching entries as read

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

test-mobile-app

No summary provided by upstream source.

Repository SourceNeeds Review
General

youtube-search

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

gemini-cli

No summary provided by upstream source.

Repository SourceNeeds Review