BackIssue
Reference

API reference

API reference

The complete HTTP endpoint list. For the why — API keys, how access is clamped to your role, CORS, client tips — read Building on the API first; this page is the map of what's there.

Everything lives under /api. It is the same API the web UI runs on, so any screen in the app is a live example of these endpoints in action.

Conventions

  • Base URL — your install, e.g. http://backissue.local:8787. All paths below are relative to it.
  • Auth — send X-Api-Key: bi_… or Authorization: Bearer bi_… on every request (the browser UI uses a session cookie instead; both resolve to a user). See Building on the API.
  • Request bodies — JSON, with Content-Type: application/json. Query strings are used for filters on GET endpoints.
  • Responses — JSON. Lists return a JSON array; single resources return an object.
  • Errors{ "error": "…" } with a meaningful status: 400 (bad input), 401 (missing/invalid key), 403 (your role lacks the permission), 404 (not found or hidden from your role), 502 (an upstream like ComicVine or an indexer failed).

How permissions are assigned

Every call resolves to one required permission. Most follow a default rule, and the tables below only call out the endpoint's effective permission:

  • GET (reading) needs library.view.
  • Writes (POST/PATCH/DELETE) need library.manage.
  • Download actions — searching sources, queueing grabs, retrying, cancelling — need downloads.grab.
  • Admin areas (settings, users, plugins, jobs, logs) need their specific permission.
  • /api/auth/* is self-service: any signed-in user can call it for their own account.

A request acts as its user: it can do exactly what the account's role allows. The core permissions:

KeyGrantsTier
library.viewBrowse series, issues, releases, the queueviewer
downloads.grabSearch sources, queue downloads, cancel queued itemstrusted
library.manageAdd/remove volumes and issues, scan, tag, import, fix matchestrusted
library.restrictedSee and read series flagged mature/restrictedtrusted
settings.manageChange settings and indexers, run connection testsadmin
users.manageManage accounts, roles, and permissionsadmin
plugins.manageEnable/disable plugins, restart the appadmin
system.jobsRun jobs, schedules, and maintenance toolsadmin
system.logsView and clear logsadmin

Discover what a key can do

GET /api/auth/me returns the key's user and its resolved permission list — a client can read that to decide which features to offer.

Account & auth

Self-service — any signed-in user, for their own account. A few are public (no key needed) because the sign-in screen calls them.

MethodEndpointAccessDescription
GET/api/auth/mepublicCurrent user and resolved permissions, or open-mode/login state
GET/api/auth/providerspublicExternal SSO buttons and whether password login is enabled
POST/api/auth/registerpublicCreate an account (only when registration is enabled)
POST/api/auth/loginpublicPassword sign-in; starts a session cookie
POST/api/auth/logoutauthedEnd the current session
POST/api/auth/logout-othersauthedRevoke every other session for this account
GET/api/auth/profileauthedThis account's profile
POST/api/auth/passwordauthedChange password
POST/api/auth/emailauthedSet the account's email
GET/api/auth/apikeyauthedWhether a key exists (never returns the key itself)
POST/api/auth/apikeyauthedGenerate/replace the key — returns it once
DELETE/api/auth/apikeyauthedRevoke the key immediately

GET /api/auth/me

json
{
  "openMode": false,
  "registration": false,
  "user": {
    "id": 3,
    "username": "darragh",
    "role": "admin",
    "permissions": ["*"]
  }
}

permissions is ["*"] for admin; otherwise the explicit list your role resolves to. In open mode (zero accounts) openMode is true and the user is a synthetic local admin.

Collection & series

Your tracked series and their issues. Reads need library.view; changes need library.manage. Series flagged restricted return 404 to roles without library.restricted.

MethodEndpointAccessDescription
GET/api/collectionlibrary.viewTracked series; ?filter=, ?search=, ?sort=
GET/api/collection/{id}library.viewOne series with issues, owned/missing counts, folder location
GET/api/serieslibrary.viewAll series (matched + catalog); ?search=
GET/api/series/{id}/issueslibrary.viewIssues for a series
GET/api/issue/{cvIssueId}library.viewOne issue by ComicVine issue id
POST/api/collection/add-cvlibrary.manageAdd a series by ComicVine volume — body { "comicvineId": 12345 }
POST/api/collection/{id}/cvlibrary.manageRe-point a series at a different ComicVine volume
POST/api/cv/matchlibrary.manageMatch an unmatched series to ComicVine
POST/api/collection/{id}/aliaseslibrary.manageSet search aliases for a series
POST/api/collection/{id}/metadatalibrary.manageRefresh a series' metadata
POST/api/issue/{cvId}/metadatalibrary.manageRefresh one issue's metadata
POST/api/collection/{id}/restrictedlibrary.manageFlag/unflag a series as mature/restricted
POST/api/collection/{id}/monitorlibrary.manageToggle automation (auto-download) for a series
POST/api/collection/{id}/followlibrary.viewToggle your personal follow (pull list)
POST/api/collection/bulklibrary.manageBulk action across selected series
POST/api/collection/{id}/deletelibrary.manageUntrack a series (files on disk are left alone)

POST /api/collection/add-cv — adds the volume, follows it for you, and (when auto-download is on and your role allows it) queues every missing issue:

bash
curl -X POST http://backissue.local:8787/api/collection/add-cv \
  -H "X-Api-Key: bi_…" -H "Content-Type: application/json" \
  -d '{"comicvineId": 18166}'
# → { "seriesId": 42, "cvId": 18166, "queued": 12 }

ComicVine lookup

Search and read ComicVine data on demand (the source of truth for comic metadata). Upstream failures surface as 502.

MethodEndpointAccessDescription
GET/api/cv/search?q=library.viewSearch ComicVine volumes
GET/api/cv/volume/{id}library.viewOne volume by id (used when pasting a CV link)
GET/api/cv/arcslibrary.viewStory arcs (for building reading lists)
GET/api/cvlibrary.viewState of a running ComicVine sync, if any

Files, folders & import

Attribute files on disk to series, and reorganize the library. Import and library-wide tools are gated tighter than ordinary edits.

MethodEndpointAccessDescription
GET/api/scan-folderlibrary.viewPreview the files in a folder
GET/api/tag-fileslibrary.viewState of a running tag-files pass
POST/api/collection/{id}/scanlibrary.manageIndex a series' own folder and attribute its files
POST/api/collection/{id}/pathlibrary.managePin the folder for a series
POST/api/collection/{id}/refilelibrary.manageRename/move a series' files to the naming scheme
POST/api/collection/{id}/taglibrary.manageWrite ComicInfo tags into a series' files
POST/api/collection/{id}/cleanuplibrary.manageRemove stray/duplicate files for a series
POST/api/collection/{id}/refreshlibrary.manageRe-scan and refresh a series
GET/api/importlibrary.manageImport candidates awaiting review
POST/api/import/scanlibrary.manageScan an import folder for candidates
POST/api/import/runlibrary.manageImport confirmed candidates
POST/api/import/candidate/{id}/matchlibrary.manageMatch a candidate to a series
POST/api/import/candidate/{id}/confirmlibrary.manageConfirm a candidate
POST/api/import/candidate/{id}/skiplibrary.manageSkip a candidate
GET/api/library/refile-plansystem.jobsPreview a library-wide reorganize
POST/api/library/refilesystem.jobsRun the library-wide reorganize
GET/api/library/refile-statussystem.jobsProgress of a running reorganize
POST/api/naming/previewsettings.managePreview filenames for a naming template

Downloads, search & queue

Finding and grabbing issues. Anything that touches a source or the queue's grabs needs downloads.grab.

MethodEndpointAccessDescription
GET/api/statuslibrary.viewCounts, followed count, version, and live crawl/queue state
GET/api/queuelibrary.viewThe download queue and in-flight pack grabs
GET/api/wantedlibrary.viewMissing issues on followed series
GET/api/historylibrary.viewImport history (newest first, paged)
GET/api/history/failedlibrary.viewFailed downloads
GET/api/sourceslibrary.viewEnabled download sources
GET/api/statslibrary.viewLibrary statistics
POST/api/downloaddownloads.grabQueue issues by internal id — { "issueIds": [1,2] }{ "queued": 2 }
POST/api/collection/{id}/downloaddownloads.grabQueue CV issues of a series — { "cvIssueIds": [ … ] }
POST/api/collection/{id}/redownloaddownloads.grabRe-grab owned issues of a series
POST/api/redownloaddownloads.grabRe-grab specific issues
POST/api/wanted/download-alldownloads.grabQueue every wanted issue
POST/api/searchdownloads.grabSearch all enabled sources for an issue
POST/api/search/grabdownloads.grabGrab a chosen result — { result, seriesId, cvIssueId }
POST/api/packs/searchdownloads.grabSearch sources for multi-issue packs
POST/api/packs/grabdownloads.grabGrab a pack — { result, seriesId }
POST/api/usenet/search · /api/usenet/grabdownloads.grabPer-issue usenet search/grab (legacy)
POST/api/torrent/search · /api/torrent/grab-packdownloads.grabPer-series torrent pack search/grab (legacy)
POST/api/queue/retry/{id}downloads.grabRetry a queued/failed item
POST/api/queue/cancel/{id}downloads.grabCancel a queued item
POST/api/grabs/{id}/canceldownloads.grabCancel an in-flight pack grab
POST/api/queue/pause · /resume · /clearlibrary.managePause, resume, or clear the queue
POST/api/retry-failed · /api/clear-failedlibrary.manageRetry or clear all failed downloads

POST /api/search takes a series/issue and returns ranked results from every enabled source; feed one back to /api/search/grab:

bash
curl -X POST http://backissue.local:8787/api/search \
  -H "X-Api-Key: bi_…" -H "Content-Type: application/json" \
  -d '{"seriesId": 42, "cvIssueId": 987654, "query": "Saga 1"}'

Releases

The weekly new-comics list.

MethodEndpointAccessDescription
GET/api/releaseslibrary.viewWeekly releases (with your-collection matches)
POST/api/releases/checklibrary.manageRefresh the releases list
POST/api/releases/downloaddownloads.grabQueue a release you don't own

Reading lists

Personal curation — each user manages their own; no files are touched, so library.view is enough for every verb.

MethodEndpointAccessDescription
GET/api/listslibrary.viewYour reading lists
POST/api/listslibrary.viewCreate a list
GET/api/lists/{id}library.viewOne list with items
PATCH/api/lists/{id}library.viewRename/reorder a list
DELETE/api/lists/{id}library.viewDelete a list
POST/api/lists/{id}/itemslibrary.viewAdd an issue to a list
DELETE/api/lists/{id}/items/{cvIssueId}library.viewRemove an issue from a list
POST/api/lists/import-arclibrary.viewCreate a list from a ComicVine story arc

Notifications

MethodEndpointAccessDescription
GET/api/notificationslibrary.viewYour in-app notifications
POST/api/notifications/readlibrary.manageMark notifications read

Live updates (SSE)

MethodEndpointAccessDescription
GET/api/eventslibrary.viewServer-Sent Events stream of what changed

Instead of polling, subscribe once and re-fetch only the domain that changed. Each event names a domain (status, queue, jobs, releases, notifications, …) mirroring the matching GET endpoint:

js
const es = new EventSource('/api/events'); // key via cookie/session in a browser
es.addEventListener('queue', () => refetch('/api/queue'));
es.addEventListener('status', () => refetch('/api/status'));

Header auth on the stream

EventSource can't set headers. From a browser served by the same origin the session cookie carries it; from a native client, use an SSE library that lets you add X-Api-Key.

Settings & connections — settings.manage

MethodEndpointAccessDescription
GET/api/settingssettings.manageAll settings
POST/api/settingssettings.manageUpdate settings
POST/api/indexers/testsettings.manageTest a Newznab/Torznab indexer
POST/api/clients/testsettings.manageTest a download client
POST/api/torznab/testsettings.manageTest a Torznab source
POST/api/torrent-client/testsettings.manageTest a torrent client
POST/api/cv/testsettings.manageTest the ComicVine connection

Connection tests are admin-only

Any endpoint ending in /test reaches an arbitrary host with the credentials you supply, so it requires settings.manage regardless of the resource.

Users, roles & permissions — users.manage

MethodEndpointAccessDescription
GET/api/usersusers.manageList accounts
POST/api/usersusers.manageCreate an account
PATCH/api/users/{id}users.manageUpdate an account (role, active, …)
DELETE/api/users/{id}users.manageDelete an account
GET/api/rolesusers.manageList roles
POST/api/rolesusers.manageCreate a custom role
PATCH/api/roles/{name}users.manageUpdate a role's permissions
DELETE/api/roles/{name}users.manageDelete a custom role
GET/api/permissionsusers.manageThe permission catalog (core + plugin-registered)

Plugins — plugins.manage

MethodEndpointAccessDescription
GET/api/pluginsplugins.manageInstalled plugins and their state
GET/api/plugins/catalogplugins.manageInstallable plugins
POST/api/plugins/installplugins.manageInstall a plugin
POST/api/plugins/uninstallplugins.manageUninstall a plugin
POST/api/plugins/{name}/enabledplugins.manageEnable/disable a plugin
GET/api/plugins/clientlibrary.viewClient assets plugins inject into the UI
POST/api/restartplugins.manageRestart the app

Jobs, schedules, tools & logs

MethodEndpointAccessDescription
GET/api/jobssystem.jobsRecent and running jobs
POST/api/jobs/clearsystem.jobsClear finished jobs
GET/api/schedulessystem.jobsScheduled tasks
POST/api/schedules/{key}system.jobsUpdate a schedule
POST/api/schedules/{key}/runsystem.jobsRun a scheduled task now
GET/api/toolssystem.jobsAvailable maintenance tools
POST/api/tools/{tool}system.jobsRun a tool (as a background job)
GET/api/logssystem.logsApplication logs
POST/api/logs/clearsystem.logsClear logs

Health

MethodEndpointAccessDescription
GET/healthzpublicLiveness probe (no /api prefix, no auth) — { "ok": true }

Plugin routes

Plugins register their own endpoints under the same /api tree, gated by the same permissions, so an API key reaches them too. Each declares an access tier — viewerlibrary.view, trustedlibrary.manage, adminplugins.manage — or its own registered permission (e.g. the Requests plugin's requests.create). What a plugin exposes is documented with that plugin; the rule of thumb is that anything its UI can do, a key with the right permission can do. See Plugin API for how routes are registered, and Building on the API for examples (Reader page images, OPDS, Requests).

This list tracks the app

Endpoints evolve with the app — this reference matches the current release. Pin your client to what you've tested and re-check on upgrades.