This document describes the Fever-compatible API implemented by the internal/fever package in this repository.
- Path:
BASE_URL/fever/ - Methods: not restricted by the router; read requests are typically sent as
GET, write requests should be sent asPOST - Response format: JSON only
- Reported API version:
3
Fever authentication is enabled per user from the Miniflux integrations page.
Fever UsernameandFever Passwordare configured in Miniflux- Miniflux stores the Fever token as the MD5 hash of
username:password - Clients authenticate by sending that token as the
api_keyparameter - Token lookup is case-insensitive
Example:
api_key = md5("fever_username:fever_password")
Example shell command:
printf '%s' 'fever_username:fever_password' | md5sumAuthentication failure does not return HTTP 401. The middleware returns HTTP 200 with:
{
"api_version": 3,
"auth": 0
}On successful authentication, every response includes:
api_version: always3auth: always1last_refreshed_on_time: current server Unix timestamp at response time
The handler selects the first matching operation in this order:
groupsfeedsfaviconsunread_item_idssaved_item_idsitemsmark=itemmark=feedmark=group
If no selector is provided, the server returns the base authenticated response only.
For read operations, the selector must be present in the query string. For write operations, mark, as, id, and before are read from request form values, so they may come from the query string or a form body.
Returns:
groups: list of categoriesfeeds_groups: mapping of category IDs to feed IDs
Response shape:
{
"api_version": 3,
"auth": 1,
"last_refreshed_on_time": 1710000000,
"groups": [
{
"id": 1,
"title": "All"
}
],
"feeds_groups": [
{
"group_id": 1,
"feed_ids": "10,11"
}
]
}Notes:
groupsare Miniflux categoriesfeeds_groups.feed_idsis a comma-separated string- categories with no feeds are returned in
groupsbut have nofeeds_groupsentry
Returns:
feeds: list of feedsfeeds_groups: mapping of category IDs to feed IDs
Feed fields:
idfavicon_idtitleurlsite_urlis_sparklast_updated_on_time
Notes:
favicon_idis0when the feed has no iconis_sparkis always0in this implementationlast_updated_on_timeis the feed check time as a Unix timestamp
Returns:
favicons: list of favicon objects
Favicon fields:
iddata
Notes:
datais a data URL such asimage/png;base64,...
Returns:
unread_item_ids: comma-separated list of unread entry IDs
Response shape:
{
"api_version": 3,
"auth": 1,
"last_refreshed_on_time": 1710000000,
"unread_item_ids": "100,101,102"
}Returns:
saved_item_ids: comma-separated list of starred entry IDs
Returns:
items: list of entriestotal_items: total number of non-removed entries for the user
Item fields:
idfeed_idtitleauthorhtmlurlis_savedis_readcreated_on_time
The implementation always excludes entries whose status is removed.
The handler applies a fixed limit of 50 items.
Supported parameters:
since_id: returns entries withid > since_idwhen greater than0, and the oldest entries otherwise, ordered byid ASCmax_id: returns entries withid < max_idwhen greater than0, and the most recent entries otherwise (including0), ordered byid DESCwith_ids: comma-separated list of entry IDs to fetch, ordered byid ASC
Selector precedence inside ?items is:
since_idmax_idwith_ids- no item filter
Notes:
with_idsdoes not enforce the 50-ID maximum mentioned in older Fever documentation, but the 50-row limit still applies: a longer list returns its 50 lowest IDs- invalid
with_idsmembers are parsed as0and do not match normal entries - when
itemsis requested withoutsince_id,max_id, orwith_ids, the 50 oldest entries are returned, ordered byid ASC htmlis returned after Miniflux content rewriting and may include media-proxy-rewritten URLs
Example:
{
"api_version": 3,
"auth": 1,
"last_refreshed_on_time": 1710000000,
"total_items": 245,
"items": [
{
"id": 100,
"feed_id": 10,
"title": "Example entry",
"author": "Author",
"html": "<p>Content</p>",
"url": "https://example.org/post",
"is_saved": 0,
"is_read": 1,
"created_on_time": 1709990000
}
]
}Normal successful write operations return the base authenticated response:
{
"api_version": 3,
"auth": 1,
"last_refreshed_on_time": 1710000000
}Parameters:
mark=itemid=<entry_id>as=read|unread|saved|unsaved
Behavior:
as=read: marks the entry as readas=unread: marks the entry as unreadas=saved: toggles the starred flagas=unsaved: toggles the starred flag
Important:
savedandunsavedboth call the same toggle operation- sending
as=savedtwice will save, then unsave - sending
as=unsavedtwice will unsave, then save - if
id <= 0, the handler returns without writing a response body - if the entry does not exist or is already removed, the server returns the base response without an error
Parameters:
mark=feedas=readid=<feed_id>before=<unix_timestamp>
Behavior:
- marks unread entries in the feed as read when
published_at < before - the update runs asynchronously in a goroutine after the response is returned
Notes:
- if
id <= 0, the handler returns without writing a response body - if
beforeis missing or invalid, it is treated as Unix time0, which usually means nothing is marked as read
Parameters:
mark=groupas=readid=<group_id>before=<unix_timestamp>
Behavior:
id=0: marks all unread entries as read, ignoringbeforeid>0: marks unread entries in the matching category as read whenpublished_at < before- the update runs asynchronously in a goroutine after the response is returned
Notes:
- group IDs map to Miniflux category IDs
- if
id < 0, the handler returns without writing a response body - if
beforeis missing or invalid forid>0, it is treated as Unix time0, which usually means nothing is marked as read
Authentication failures:
- HTTP status:
200 - body:
{"api_version":3,"auth":0}
Internal errors:
- HTTP status:
500 - body:
{
"error_message": "..."
}This implementation is Fever-compatible, but it does not match every detail of historical Fever API docs.
- Responses are always JSON;
api=xmlis mentioned in code comments but is not implemented api_versionis3last_refreshed_on_timeis set to the current response time, not the timestamp of the most recently refreshed feed- the
KindlingandSparkssuper groups are not returned feeds[].is_sparkis always0as=savedandas=unsavedtoggle the saved flag instead of setting it absolutely
Fetch groups:
curl -s 'https://miniflux.example.com/fever/?api_key=TOKEN&groups'Fetch most recent items:
curl -s 'https://miniflux.example.com/fever/?api_key=TOKEN&items&max_id=0'Fetch items after a known ID:
curl -s 'https://miniflux.example.com/fever/?api_key=TOKEN&items&since_id=123'Mark an item as read:
curl -s -X POST 'https://miniflux.example.com/fever/' \
-d 'api_key=TOKEN' \
-d 'mark=item' \
-d 'as=read' \
-d 'id=123'Mark a feed as read before a timestamp:
curl -s -X POST 'https://miniflux.example.com/fever/' \
-d 'api_key=TOKEN' \
-d 'mark=feed' \
-d 'as=read' \
-d 'id=10' \
-d 'before=1710000000'Mark all items as read through the group endpoint:
curl -s -X POST 'https://miniflux.example.com/fever/' \
-d 'api_key=TOKEN' \
-d 'mark=group' \
-d 'as=read' \
-d 'id=0'