Skip to content
ThemeNord

Same themes as the MinusPod app

Default

Catppuccin

Dracula

Nord

Gruvbox

Solarized

Rose Pine

Kanagawa

Ayu

Other

Local Feeds

Local (archive-import) feeds: no upstream RSS, episode upload and edits, and bulk directory/upload import (#625)

Upload cover art for a local, recents or YouTube feed

Local, recents and YouTube feeds only (400 on a subscribed RSS feed, whose artwork comes from the upstream RSS on refresh). JPEG or PNG, detected from the file bytes rather than the client-supplied content type. Bound by the app’s default 10 MB request cap. A response under 1400x1400 still succeeds but carries a warning field, since podcast directories generally expect at least that.

  • slug (path, string, required): Podcast feed slug identifier

Request body (multipart/form-data, required)

Section titled “Request body (multipart/form-data, required)”
  • file (string (binary), required)
Status Description Body
200 Artwork uploaded object
400 Not a local, recents or YouTube feed, missing file, or not a JPEG/PNG image Error
404 Resource not found Error
  • message (string)
  • artworkUrl (string)
  • warning (string): Present when the image is smaller than 1400x1400 in either dimension.

Upload a single episode into a local feed

Local feeds only. episode_id is minted as s{season:02d}e{episode:02d}; season defaults to 1, episode defaults to one past the highest existing episode number in that season. 409 if that id already exists; use the bulk import commit with overwrite for that. Widened request cap: audio up to 1 GB, streamed to a temp file on the same volume as the episode’s final storage path, not buffered fully in memory.

  • slug (path, string, required): Podcast feed slug identifier

Request body (multipart/form-data, required)

Section titled “Request body (multipart/form-data, required)”
  • audio (string (binary), required): .mp3 only, up to 1 GB.
  • season (integer): Default 1.
  • episode (integer): Defaults to one past the highest existing episode number in this season.
  • title (string)
  • description (string)
  • publishedAt (string (date-time)): ISO 8601, timezone required. Defaults to the upload time.
  • artwork (string (binary)): Optional episode cover, JPEG or PNG, up to 10 MB.
Status Description Body
201 Episode created EpisodeDetail plus object
400 Not a local feed, no audio field, wrong extension, or unplayable audio Error
404 Resource not found Error
409 An episode with this season/episode already exists Error
413 Upload exceeds the configured local upload size limit UploadTooLarge

Includes every field of EpisodeDetail.

  • episodeNumber (integer)
  • seasonNumber (integer)
  • queued (boolean): Whether this upload was queued for auto-process (only possible when the feed already had at least one episode before this upload).

Bulk-edit local episodes

Local feeds only. Every entry is validated before any are applied (atomic): one invalid entry 400s the whole request with nothing written. Up to 500 entries per request. RSS is regenerated once at the end, not per entry.

  • slug (path, string, required): Podcast feed slug identifier

Array of:

  • episodeId (string, required): sNNeNN local episode id.

Includes every field of LocalEpisodeEditFields.

Status Description Body
200 Episodes updated object
400 Not a local feed, not a list, empty, over 500 entries, duplicate episodeId, or an invalid field on any entry Error
404 Feed not found, or an entry names an episodeId that does not exist Error
  • updated (integer)

Edit a local episode

Local feeds only. season/episode change only the display season_number/episode_number columns; the episode_id minted at upload time never changes.

  • slug (path, string, required): Podcast feed slug identifier
  • episode_id (path, string, required): Episode identifier: a 12-character MD5-hex string for a subscribed feed’s episode, or an sNNeNN id (e.g. s01e05) for a local feed’s.

LocalEpisodeEditFields

Status Description Body
200 Episode updated EpisodeDetail plus object
400 Not a local feed, or an invalid field Error
404 Resource not found Error

Includes every field of EpisodeDetail.

  • episodeNumber (integer)
  • seasonNumber (integer)

DELETE /feeds/{slug}/episodes/{episode_id}

Section titled “DELETE /feeds/{slug}/episodes/{episode_id}”

Delete a local episode

Local feeds only. Hard-deletes the row and its files. Unlike a subscribed feed’s episode delete, there is no upstream to rediscover it from, so it is not reset to ‘discovered’ for a future refresh to pick back up.

  • slug (path, string, required): Podcast feed slug identifier
  • episode_id (path, string, required): Episode identifier: a 12-character MD5-hex string for a subscribed feed’s episode, or an sNNeNN id (e.g. s01e05) for a local feed’s.
Status Description Body
200 Episode deleted object
400 Not a local feed Error
404 Resource not found Error
409 Episode is currently processing; cancel it first Error
  • deleted (integer)
  • episodeId (string)

POST /feeds/{slug}/episodes/{episode_id}/artwork

Section titled “POST /feeds/{slug}/episodes/{episode_id}/artwork”

Upload cover art for a single local episode

Local feeds only. JPEG or PNG, up to 10 MB, detected from the file bytes.

  • slug (path, string, required): Podcast feed slug identifier
  • episode_id (path, string, required): Episode identifier: a 12-character MD5-hex string for a subscribed feed’s episode, or an sNNeNN id (e.g. s01e05) for a local feed’s.

Request body (multipart/form-data, required)

Section titled “Request body (multipart/form-data, required)”
  • file (string (binary), required)
Status Description Body
200 Artwork uploaded object
400 Not a local feed, missing file, too large, or not a JPEG/PNG image Error
404 Resource not found Error
  • message (string)
  • episodeId (string)

Stage archive-import files ahead of scan/commit

Local feeds only. Multipart, repeated field “files”, saved under each file’s original basename into the feed’s staging area (<data>/import-staging/<slug>/) so the sNNeNN naming scheme can be parsed by a later scan. A basename that is empty, a dotfile, over 255 UTF-8 bytes, or contains a path separator/“..”/NUL is rejected per-file rather than failing the whole request. Widened request cap: up to 1 GB total, same as the single-episode upload.

  • slug (path, string, required): Podcast feed slug identifier

Request body (multipart/form-data, required)

Section titled “Request body (multipart/form-data, required)”
  • files (array of string (binary), required)
Status Description Body
200 Files staged object
400 Not a local feed, or no files field Error
404 Resource not found Error
409 An import is already running for this feed Error
413 Upload exceeds the configured local upload size limit UploadTooLarge
  • staged (array of string): Basenames successfully staged.
  • rejected (array of object)
  • rejected[].file (string)
  • rejected[].reason (string)

Dry-run a bulk archive import

Local feeds only. Scans the staging area and/or the user-managed import directory (<data>/import/<slug>/), applies the sNNeNN naming scheme and any JSON sidecars, synthesizes publish dates for entries that don’t have one, and returns the plan the UI renders for review. Nothing is written to disk or the database by this call.

  • slug (path, string, required): Podcast feed slug identifier

LocalImportRequest

Status Description Body
200 Dry-run plan LocalImportPlan
400 Not a local feed, or an invalid source/overwrite value Error
404 Resource not found Error

Commit a previously scanned import plan

Local feeds only. Re-scans the same source(s) server-side and compares the result’s hash against the client-echoed planHash; a mismatch means a file changed since the scan and 409s rather than committing a stale plan. Starts a background job (one import per feed at a time; a second commit while one is running also 409s) and returns immediately; poll import/status for progress. An empty feed’s very first commit never queues anything for auto-process regardless of settings; a later commit into a non-empty feed does, skipping the publish-date recency check.

  • slug (path, string, required): Podcast feed slug identifier
  • planHash (string, required): The planHash returned by the most recent import/scan call for this feed and source/overwrite combination.

Includes every field of LocalImportRequest.

Status Description Body
202 Import started object
400 Not a local feed, missing planHash, or an invalid source/overwrite value Error
404 Resource not found Error
409 planHash is stale (files changed since scan), an import is already running for this feed, or there is not enough free disk space for the plan’s importable bytes Error
  • message (string)

Poll a local feed’s background import job

Local feeds only. A slug with no import ever started reads as idle.

  • slug (path, string, required): Podcast feed slug identifier
Status Description Body
200 Import status LocalImportStatus
400 Not a local feed Error
404 Resource not found Error

Clear a local feed’s upload staging area

Local feeds only. Empties <data>/import-staging/<slug>/. The UI clears staging itself at the start of every new file selection, so this is mainly for wiping an abandoned upload attempt by hand.

  • slug (path, string, required): Podcast feed slug identifier
Status Description Body
200 Staging cleared object
400 Not a local feed Error
404 Resource not found Error
409 An import is already running for this feed Error
  • message (string)