Skip to content

API reference

Trackarr exposes three surfaces:

  1. Tracker endpointsapps/tracker (Go). Public, anonymous, BEP-spec'd. /announce over HTTP and UDP.
  2. REST APIapps/api (Nitro). Everything under /api/*. Session-cookie auth.
  3. Torznab + RSS — feed-style endpoints for *Arr clients and feed readers, keyed by passkey or Torznab API key.

The lists below are exhaustive against the route tree under apps/api/routes/api/. Auth labels: public (anonymous), user (any authenticated user), mod (canModerate permission), admin (admin role), passkey (announce-style, passkey in URL).

Tracker endpoints

The Go tracker speaks two protocols off the same backend.

HTTP announce (BEP 3) — GET /announce

GET /announce?info_hash=...&peer_id=...&port=...
            &uploaded=...&downloaded=...&left=...
            &event=started|completed|stopped&numwant=...&compact=1

Passkey is read from the path (/announce/PASSKEY) or the ?passkey= query parameter. Response is the standard bencoded peer list.

UDP announce (BEP 15) — :6969/udp

Stateless connect-then-announce. Passkey extracted from the BEP 41 URL_DATA option. See UDP Tracker for the wire format, connection-id HMAC scheme, and reverse-proxy caveats.

No /scrape, no wss://

The tracker does not currently implement a multi-hash scrape endpoint or the WebTorrent (WebSocket) announce path. Don't advertise a wss:// URL or a scrape URL in .torrent files — clients will hang.

Public (no auth)

MethodPathPurpose
GET/api/healthLiveness probe. Returns 200 { ok: true }.
GET/api/brandingSite title, tagline, logo URL, favicon URL, feature flags.
GET/api/runtime-configPublic Nuxt runtime config (announce URLs, etc.) for the static SPA.
GET/api/announcementOperator-set homepage banner (text + level).
GET/api/homepage-contentFeatured rails, custom blocks (operator-curated).
GET/api/categoriesHierarchical category tree.
GET/api/tagsTag master list (autocomplete source).
GET/api/upload-rulesPublic upload constraints (max size, allowed extensions, …).
GET/api/stats/publicSwarm counters (peers, seeders, torrents, users) + UDP toggle matrix.
GET/api/tracker-healthTracker availability matrix (HTTP up/down, UDP up/down).
GET/api/torrentsBrowse torrents (page, limit, category, tags, q, sort).
GET/api/torrents/:hashTorrent detail (metadata + swarm + comments).
GET/api/users/:idPublic profile (display name, role badges, redacts last-seen if opted out).
GET/api/users/:id/uploadsPaginated list of accepted torrents from this user.

Authentication

Zero-Knowledge: the password never leaves the browser. See the Zero-Knowledge Auth guide.

MethodPathAuthPurpose
GET/api/auth/powpublicIssue a Proof-of-Work challenge for the registration form.
POST/api/auth/registerpublicCreate a user — body: { username, salt, verifier, invite?, pow }.
GET/api/auth/challengepublicReturn { salt, challenge } keyed by username for the ZK login proof.
POST/api/auth/loginpublicVerify { username, proof, challenge } and open a sealed-cookie session.
POST/api/auth/logoutuserRevoke the current session.
GET/api/auth/statuspublicReturns current user + locale + theme (or null if anonymous).
PUT/api/auth/passworduserAtomic password rotation: prove current, ship new { salt, verifier }.
GET/api/auth/passkeypublicWebAuthn assertion options for first-factor passkey login.
POST/api/auth/passkeypublicVerify a WebAuthn assertion and open a session.

Two-factor (during sign-in)

MethodPathAuthPurpose
POST/api/auth/2fa/passkey-optionsuser (1FA)WebAuthn options for the second-factor step.
POST/api/auth/2fa/passkey-verifyuser (1FA)Verify the second-factor passkey, finalise the session.
POST/api/auth/2fa/verify-totpuser (1FA)Verify a 6-digit TOTP code (with optional trust_device).

Two-factor enrolment (logged in)

MethodPathAuthPurpose
GET/api/me/2fa/statususerTOTP enabled? Passkey list? Trust-device flag?
POST/api/me/2fa/totp/setupuserGenerate a TOTP secret + recovery codes.
POST/api/me/2fa/totp/enableuserConfirm with a 6-digit code → activates TOTP.
POST/api/me/2fa/totp/disableuserDisable TOTP (requires a fresh 6-digit code).
POST/api/me/2fa/recovery-codes/regenerateuserRotate the recovery code set.
POST/api/me/2fa/passkey/register-challengeuserWebAuthn attestation options to add a passkey.
POST/api/me/2fa/passkey/register-verifyuserVerify and store a new passkey.
DELETE/api/me/2fa/passkey/:iduserRemove a passkey by id.
GET/api/me/2fa/sessionsuserList trusted devices.
DELETE/api/me/2fa/sessions/:iduserRevoke a trusted device.
PUT/api/me/2fa/trust-devicesuserToggle the "trust this browser for 30 days" flag.

Profile (/me)

MethodPathAuthPurpose
GET/api/meuserFull profile snapshot (KPIs, role badges, bio, locale, theme).
PATCH/api/meuserUpdate display name, bio, locale, theme, last-seen privacy toggle.
GET/api/me/downloadsuser.torrent downloads + per-download HnR state.
GET/api/me/seedsuserActive seeds with live swarm stats.
GET/api/me/bonus-historyuserLedger of credited bonus points (paginated, oldest → newest).
GET/api/users/hnruserCurrent user's HnR violations (shortcut).

Notifications

The in-app inbox is always-on; external channels are opt-in per user.

MethodPathAuthPurpose
GET/api/me/notificationsuserPaginated inbox.
GET/api/me/notifications/unread-countuserBell-badge count.
GET/api/me/notifications/streamuserServer-Sent Events stream — live push to open tabs (Redis pub/sub fanout).
POST/api/me/notifications/:id/readuserMark a single row as read.
POST/api/me/notifications/read-alluserMark every row as read.
GET/api/me/notification-channelsuserChannels configured for this user (and their state).
PUT/api/me/notification-channels/:typeuserConfigure / update a channel (encrypted at rest).
DELETE/api/me/notification-channels/:typeuserDisable a channel.
POST/api/me/notification-channels/:type/testuserSend a test notification through this channel.
PUT/api/me/notification-routinguserMap {notification_type → channel_type} for fan-out.

See Notifications for the channel types (SMTP, Telegram, Discord, ntfy, Gotify, Pushover, Slack, Mattermost, webhook, Apprise, Web Push).

Torrents

MethodPathAuthPurpose
GET/api/torrentspublicList/browse with filters.
POST/api/torrentsuserUpload (multipart: .torrent + metadata + optional NFO).
POST/api/torrents/checkuserPre-flight infohash lookup before opening the upload form.
GET/api/torrents/:hashpublicDetail page payload.
PATCH/api/torrents/:hashuploader / modEdit title / description / tags / external IDs.
DELETE/api/torrents/:hashuploader / modSoft-delete.
GET/api/torrents/:hash/downloaduser.torrent with the user's passkey baked into the announce list.
PUT/api/torrents/:hash/tagsuploader / modReplace the tag set.
POST/api/torrents/:hash/commentsuserPost a comment.
DELETE/api/torrents/comments/:idauthor / modDelete a comment.
GET/api/torrents/:hash/moderation/messagesthread†Moderation chat — {status, messages}. 404 if not allowed.
POST/api/torrents/:hash/moderation/messagesthread†Reply without a status change.
GET/api/torrents/:hash/cross-seedsuserSibling torrents that share this content signature (up to 50).
GET/api/torrents/:hash/cross-seed-statsuserCross-seed KPI bundle (peer overlap + volume share). Memoised 30 s.
POST/api/torrents/:hash/favoriteuserStar (idempotent).
DELETE/api/torrents/:hash/favoriteuserUnstar (silent if not starred).
GET/api/debug/:hashmodRaw row + per-peer swarm dump.

thread = uploader of the row OR any staff member.

Favorites

MethodPathAuthPurpose
GET/api/me/favoritesuserPaginated catalogue, sort recent / name / seeders.

Follows (social graph)

MethodPathAuthPurpose
POST/api/users/:id/followuserSubscribe to a user (idempotent, refuses self-follow).
DELETE/api/users/:id/followuserUnsubscribe (silent if not following).
GET/api/me/followinguserPaginated cast list, sort recent / alpha.

The public /api/users/:id payload carries followersCount and viewerFollowing so the profile page renders the toggle state in one round-trip.

Reports (user-side)

MethodPathAuthPurpose
POST/api/reportsuserSubmit a report ({ target_type, target_id, reason, details? }). See Reports.
GET/api/me/reportsuserList the caller's filed reports + current status.
DELETE/api/me/reports/:iduserWithdraw a pending report (hard-delete; refused once staff has acted).

Upload requests (bounty board)

MethodPathAuthPurpose
GET/api/requestsuserPaginated list. Filters: status, mine, categoryId, search.
POST/api/requestsuserCreate. Reward (if any) debited atomically from bonus_points.
GET/api/requests/:iduserDetail + thread + fill-attempt history + viewer permissions.
PATCH/api/requests/:idrequesterEdit while requested. Reward bump-only.
DELETE/api/requests/:idrequesterCancel + refund. Only while requested.
POST/api/requests/:id/filluser (not requester)Propose a torrent ({ infoHash } or { torrentId }). Enforces uploader = caller, category match, per-user cap.
POST/api/requests/:id/validaterequesterAccept the fill + pay the filler.
POST/api/requests/:id/rejectrequesterBounce the fill; status → requested; filler attempts counter ticks.
POST/api/requests/:id/commentsuserAppend to the discussion (locked when validated/cancelled).
PATCH/api/requests/:id/comments/:cidauthor (15 min)Edit own comment within the grace window.
DELETE/api/requests/:id/comments/:cidauthor (15 min) / modSoft-delete (body hidden, row stays).

See Upload Requests for the full lifecycle, point ledger, and operator settings.

Anti-cheat (staff)

MethodPathAuthPurpose
GET/api/mod/anti-cheat/flagsmodPaginated queue. Filters: status, kind, userId.
PUT/api/mod/anti-cheat/flags/:idmodStamp a review verdict + optional note. See Anti-cheat.

Moderation

MethodPathAuthPurpose
GET/api/mod/dashboardmodCounters: pending uploads, pending reports, HnR violations, …
GET/api/mod/torrents/pendingmodPending upload queue.
POST/api/mod/torrents/:hash/approvemodMove row → accepted. Optional message.
POST/api/mod/torrents/:hash/request-changesmodMove row → changes_requested. Message required.
POST/api/mod/torrents/:hash/rejectmodMove row → rejected. Message required.
POST/api/mod/torrents/:hash/resetmodOnly path out of rejected. Message required.

Forum

MethodPathAuthPurpose
GET/api/forum/categoriespublicForum structure.
GET/api/forum/categories/:idpublicCategory + paginated topics.
POST/api/forum/categoriesadminCreate a category.
PUT/api/forum/categories/:idadminEdit a category.
DELETE/api/forum/categories/:idadminRemove a category.
POST/api/forum/topicsuserCreate a topic.
GET/api/forum/topics/:idpublicTopic + paginated posts.
DELETE/api/forum/topics/:idauthor / modDelete topic.
PUT/api/forum/topics/:id/pinmodToggle pin.
PUT/api/forum/topics/:id/lockmodToggle lock.
POST/api/forum/postsuserReply in a topic.
PATCH/api/forum/posts/:idauthor / modEdit a post.
DELETE/api/forum/posts/:idauthor / modDelete a post.
GET/api/forum/statspublicAggregate stats (topic count, post count, latest reply).

Bonus economy & shop

MethodPathAuthPurpose
GET/api/bonus/activepublicActive freeleech / silverleech / custom events.
GET/api/shop/itemsuserShop catalogue.
POST/api/shop/buyuserPurchase an item ({ item_id }). Transactional against users.bonus_points.

Invitations

MethodPathAuthPurpose
GET/api/invitesuserMy invite codes (remaining quota + outstanding codes).
POST/api/invitesuserGenerate a code (decrements users.invites_remaining).
DELETE/api/invites/:iduserRevoke an unused code.

Metadata lookup

Filename → external metadata (TMDb / IGDB / Open Library / Google Books). Locale-aware via the user's profile setting.

MethodPathAuthPurpose
GET/api/metadata/searchuserMulti-source search (auto-routes by category type).
GET/api/metadata/lookupuserResolve a known external id to a normalised payload.

A missing provider key returns 503 only on the routes that need that source — the others keep serving. See Metadata providers.

Torznab & RSS

Exposed for *Arr clients (Sonarr / Radarr / …) and feed readers.

MethodPathAuthPurpose
GET / HEAD/api/torznab/apitorznab keyNewznab/Torznab dispatcher (`?t=caps
GET/api/torznab/downloadtorznab keyDownload a .torrent keyed by r=<torznab-key>.
GET/api/rss/latestpublicRecent torrents (Atom feed).
GET/api/rss/category/:slugpublicCategory-scoped feed.

See Torznab integration for the *Arr-client wiring.

Admin

The admin surface is gated by the canAccessAdmin permission. Auth = admin below.

Users & roles

MethodPathPurpose
GET/api/admin/usersPaginated registry with KPI strip + filters.
POST/api/admin/users/:id/banBan (auto-banlist the last-known IP). Accepts an optional duration (days).
POST/api/admin/users/:id/unbanUnban (does not auto-remove the IP banlist row). Refuses a mod trying to lift an admin-issued ban.
PUT/api/admin/users/:id/roleDeprecated. Use the role-attach endpoints below.
GET/api/admin/users/:id/rolesList a user's roles.
POST/api/admin/users/:id/rolesAttach a role.
DELETE/api/admin/users/:id/roles/:roleIdDetach a role.
POST/api/admin/users/:id/bonus-pointsAdd or subtract bonus points with an audit-logged reason.
GET/api/admin/rolesRole catalogue.
POST/api/admin/rolesCreate a role.
PUT/api/admin/roles/:idEdit role (name, permissions, auto-assignment rules).
DELETE/api/admin/roles/:idRemove a role.
POST/api/admin/roles/recomputeRe-evaluate every user against auto-assignment rules.

See Roles & Permissions.

Settings, branding, system

MethodPathPurpose
GET/api/admin/settingsAll site settings (title, tagline, force-2FA scope, retention, request auto-validate timeout, request fill cap, …).
PUT/api/admin/settingsSave settings (any subset; missing keys are left untouched).
POST/api/admin/logoUpload the site logo (multipart).
POST/api/admin/faviconUpload the favicon (multipart).
GET/api/admin/statsLive aggregate stats (users, torrents, peers, DB size).
GET/api/admin/stats/historyTime-series for the admin charts.
GET/api/admin/system/versionCurrent version + commit + runtime label.
GET/api/admin/system/updateLatest release available on GitHub (queries TRACKARR_REPO).

See Branding.

Categories & tags

MethodPathPurpose
POST/api/admin/categoriesCreate a category.
PUT/api/admin/categories/:idEdit a category.
DELETE/api/admin/categories/:idRemove a category.
POST/api/admin/categories/seedSeed the default category tree (idempotent — skips existing rows).
POST/api/admin/tagsCreate a tag.
DELETE/api/admin/tags/:idDelete a tag (unbinds it from every torrent in the same transaction).

Upload rules

MethodPathPurpose
GET/api/admin/upload-rulesRead rules (NFO requirement, description min length, regex patterns).
PUT/api/admin/upload-rulesUpdate rules (atomic).

See Upload Rules.

Bonus rules & events

MethodPathPurpose
GET/api/admin/bonus-rulesRead all rules + tier sets.
PATCH/api/admin/bonus-rules/rule/:kindConfigure a rule (seeding, first_seeder, daily_login, …).
POST/api/admin/bonus-rules/tiers/seed-countAdd a seeder-count tier.
PATCH/api/admin/bonus-rules/tiers/seed-count/:idEdit a seeder-count tier.
DELETE/api/admin/bonus-rules/tiers/seed-count/:idRemove a tier.
POST/api/admin/bonus-rules/tiers/ageAdd a torrent-age tier.
PATCH/api/admin/bonus-rules/tiers/age/:idEdit an age tier.
DELETE/api/admin/bonus-rules/tiers/age/:idRemove an age tier.
GET/api/admin/bonus-eventsList scheduled events.
POST/api/admin/bonus-eventsCreate a Freeleech / Silverleech / custom event.
PATCH/api/admin/bonus-events/:idEdit an event.
DELETE/api/admin/bonus-events/:idCancel an event.
POST/api/admin/bonus-events/:id/togglePause / resume a running event.
GET/api/admin/shop/itemsShop catalogue (admin view).
POST/api/admin/shop/itemsAdd a shop item.
PATCH/api/admin/shop/items/:idEdit a shop item.
DELETE/api/admin/shop/items/:idRemove a shop item.

HnR

MethodPathPurpose
GET/api/admin/hnrList violations.
PUT/api/admin/hnr/:idMark exempt / cleared / unresolved.

See Hit-and-Run.

Banned IPs

MethodPathPurpose
GET/api/admin/banned-ipsList banlist entries.
POST/api/admin/banned-ipsAdd an IP banlist row.
DELETE/api/admin/banned-ips/:ipRemove an IP banlist row.

Invitations

MethodPathPurpose
GET/api/admin/invitesEvery invite code + usage state.
POST/api/admin/invites/generateBatch-generate codes (operator share link).
POST/api/admin/invites/grantAward invite quota to a user.
DELETE/api/admin/invites/:idRevoke a code.

See Invitations.

Reports

MethodPathPurpose
GET/api/admin/reportsQueue (paginated, filterable by target_type and status).
PUT/api/admin/reports/:idResolve a report. For targetType='user' + status='resolved', accepts banDuration (none / 1d / 7d / 1m / 1y / permanent) and banReason to ban the offender in the same transaction. See Reports.

Notification channels (server-side config)

MethodPathPurpose
GET/api/admin/notification-channelsList configured channels + capability matrix.
PUT/api/admin/notification-channels/:typeConfigure a channel (SMTP host, Discord token, VAPID keys, …).
POST/api/admin/notification-channels/:type/testSend a test through this channel (uses the admin's own user as recipient).

Torznab admin

MethodPathPurpose
GET/api/admin/torznabTorznab config + per-user key inventory.
PUT/api/admin/torznabToggle Torznab + edit limits.
GET/api/admin/torznab/usersActive user keys.
POST/api/admin/torznab/users/:id/blockRevoke a user's Torznab key.
POST/api/admin/torznab/users/:id/resetRotate a user's Torznab key.
GET/api/admin/torznab/blacklistQuery patterns currently blacklisted.
POST/api/admin/torznab/unblockLift a blacklist entry.
GET/api/admin/torznab/logsRecent Torznab requests with status + handler.
GET/api/admin/torznab/statsAggregate request counters by handler.

Panic Mode

MethodPathPurpose
GET/api/admin/panicEncryption state + last-activation timestamp.
POST/api/admin/panic/encryptActivate. Body: { confirmation: "ENCRYPT_ALL_DATA" }.
POST/api/admin/panic/restoreRestore. Body: { password }.

See Panic Mode. Activation is irreversible without the original password — operators are warned in-app.

Debug

MethodPathPurpose
GET/api/admin/debug/tracker-statusRaw tracker health + peer counter snapshot.
GET/api/admin/debug/redis-peersPeer hash sample for one info_hash.
GET/api/admin/debug/redis-all-peersFull SCAN over peers:*. Heavy — use sparingly.

Rate limits

The API enforces sliding windows in Redis. Limits are tuned in apps/api/utils/rateLimit.ts and are not env-driven today.

BucketLimitWindow
Public read100 req1 min
Mutations (POST/PUT/PATCH/DELETE)10 req1 min
Auth (/api/auth/*)5 req5 min
Tracker announce200 req1 min

Exceeding a bucket returns 429 Too Many Requests. Repeated offences within a short window add a temporary IP ban — see Security.

Error shape

Every error response uses h3's default shape:

json
{
  "url": "/api/example",
  "statusCode": 429,
  "statusMessage": "Too Many Requests",
  "message": "Rate limit exceeded",
  "data": {}
}

Common status codes:

CodeMeaning
400Validation failed (Zod body / query schema).
401Not authenticated (no session cookie).
403Authenticated but lacking the required permission/role.
404Resource not found, OR (deliberate) hidden — see Moderation thread.
409Conflict (e.g. duplicate info_hash on upload, role-rule collision).
429Rate limited.
500Server error — surface to the operator via LOG_LEVEL=error.

Released under the MIT License.