Files
sofarr/server/openapi.yaml
T
gronod 7690d959b3
CI / Security audit (push) Successful in 1m52s
Docs Check / Markdown lint (push) Successful in 1m37s
Build and Push Docker Image / build (push) Successful in 2m2s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 2m33s
CI / Swagger Validation & Coverage (push) Successful in 3m17s
Docs Check / Mermaid diagram parse check (push) Successful in 3m31s
CI / Tests & coverage (push) Successful in 4m5s
fix: blocklist-search lookup against queue cache instead of downloadClientRegistry
Fixes the root cause of the regression from v1.7.16. The v1.7.16 fix
correctly cast arrQueueId to String, but the lookup was performed
against downloadClientRegistry.getAllDownloads() which returns raw
download client data (qBittorrent, SABnzbd, etc.) that never has
arrQueueId populated.

The fix now looks up the queue record directly from the Sonarr/Radarr
queue cache where record.id is the numeric queue ID, using String()
casting on both sides to handle the DOM-dataset (string) vs API
response (number) type difference.

Resolves Gitea Issue #48
Closes #48
2026-05-24 22:48:17 +01:00

1949 lines
55 KiB
YAML

openapi: 3.1.0
info:
title: sofarr API
description: |
sofarr is a personal media download dashboard that aggregates download activity from SABnzbd, Sonarr, Radarr, qBittorrent, Transmission, and rTorrent, filters results by Emby/Jellyfin user identity, and presents a real-time personalized dashboard.
## Authentication
sofarr uses cookie-based authentication with Emby/Jellyfin. To authenticate:
1. Call POST /api/auth/login with username and password
2. The server sets an httpOnly signed cookie named `emby_user`
3. The server also sets a `csrf_token` cookie (readable by JS)
4. Subsequent requests must include the cookies and send the `X-CSRF-Token` header for state-changing operations (POST, PUT, PATCH, DELETE)
## Rate Limiting
To protect the system from resource exhaustion, rate limiters are enforced at different levels:
- **General API Limiter**: Enforces a limit of **300 requests per 15 minutes** per IP across all `/api/*` endpoints.
- *Exemption:* Requests starting with `/api/dashboard/cover-art` are completely exempted from this limit to avoid normal dashboard image browsing triggering blocks.
- **Login Rate Limiter**: Enforces a strict limit of **10 attempts per 15 minutes** per IP on `POST /api/auth/login`.
- *Exemption:* This limiter only tracks and counts *failed* login attempts (`skipSuccessfulRequests: true`). Successful logins do not count towards the lockout threshold.
- **Webhook Limiter**: Enforces a limit of **60 requests per minute** per IP on stateful webhook receiver endpoints (`/api/webhook/*`).
- **Health and Readiness Probes**: The public `/health` and `/ready` endpoints are mounted at the root directory level rather than under `/api/*` and are completely exempt from both rate limiting and authentication controls.
## SSE Streaming
Real-time updates are available via Server-Sent Events at GET /api/dashboard/stream.
version: 1.7.17
contact:
name: sofarr
license:
name: MIT
servers:
- url: https://sofarr.example.com
description: sofarr API (auto-detected from current URL)
tags:
- name: Health
description: Public health check endpoints
- name: Auth
description: Authentication and session management
- name: Dashboard
description: User dashboard and download data
- name: Status
description: Server status and metrics (admin-only)
- name: History
description: Download history
- name: Webhook
description: Webhook receivers for Sonarr/Radarr
- name: Sonarr
description: Sonarr API proxy
- name: Radarr
description: Radarr API proxy
- name: SABnzbd
description: SABnzbd API proxy
- name: Emby
description: Emby/Jellyfin API proxy
- name: Ombi
description: Ombi request management
security:
- CookieAuth: []
components:
securitySchemes:
CookieAuth:
type: apiKey
in: cookie
name: emby_user
description: |
httpOnly signed cookie containing user session. Set by POST /api/auth/login.
Format: JSON string with {id, name, isAdmin}.
Must be sent with every authenticated request along with X-CSRF-Token header for mutations.
CsrfToken:
type: apiKey
in: header
name: X-CSRF-Token
description: |
CSRF token from csrf_token cookie. Required for POST, PUT, PATCH, DELETE requests.
Obtain via GET /api/auth/csrf or from the response of POST /api/auth/login.
schemas:
NormalizedDownload:
type: object
description: Standardized download object from any client
properties:
id:
type: string
description: Client-specific unique ID
example: "abc123"
title:
type: string
description: Download title/name
example: "Show.Name.S01E01.1080p.WEB-DL"
type:
type: string
enum: [usenet, torrent]
description: Download type
example: "torrent"
client:
type: string
description: Client identifier
example: "qbittorrent"
instanceId:
type: string
description: Instance identifier
example: "qbittorrent-main"
instanceName:
type: string
description: Instance display name
example: "Main qBittorrent"
status:
type: string
description: Normalized status
example: "Downloading"
progress:
type: number
description: Progress percentage (0-100)
example: 45.5
size:
type: integer
description: Total size in bytes
example: 1073741824
downloaded:
type: integer
description: Downloaded bytes
example: 536870912
speed:
type: integer
description: Current speed in bytes/sec
example: 1048576
eta:
type: integer
nullable: true
description: ETA in seconds, null if unknown
example: 300
category:
type: string
description: Download category
example: "tv"
tags:
type: array
items:
type: string
description: Download tags
example: ["user-john"]
savePath:
type: string
description: Save path
example: "/downloads/tv"
addedOn:
type: string
description: Added timestamp (ISO 8601)
example: "2026-05-21T10:00:00.000Z"
arrQueueId:
type: integer
nullable: true
description: Sonarr/Radarr queue ID
example: 123
arrType:
type: string
enum: [series, movie]
nullable: true
description: Sonarr/Radarr type
example: "series"
ombiLink:
type: string
nullable: true
description: Link to Ombi request or search
example: "https://ombi.example.com/#/request/movie/123"
ombiRequestId:
type: string
nullable: true
description: Ombi request ID (if request exists)
example: "123"
ombiTooltip:
type: string
nullable: true
description: Tooltip text for Ombi icon ("Request" or "Search")
example: "Request"
DashboardPayload:
type: object
properties:
user:
type: string
description: Username
example: "john"
isAdmin:
type: boolean
description: Admin flag
example: false
downloads:
type: array
items:
$ref: '#/components/schemas/NormalizedDownload'
description: Matched download objects
downloadClients:
type: array
items:
type: object
properties:
id:
type: string
example: "qbittorrent-main"
name:
type: string
example: "Main qBittorrent"
type:
type: string
example: "qbittorrent"
description: Configured download clients
ErrorResponse:
type: object
properties:
error:
type: string
description: Error message
example: "Invalid username or password"
details:
type: string
nullable: true
description: Additional error details (dev-only)
example: "Emby API returned 401"
OmbiRequest:
type: object
description: Normalised Ombi movie or TV request
properties:
id:
type: integer
example: 123
title:
type: string
example: "The Batman"
requestedDate:
type: string
format: date-time
nullable: true
example: "2026-05-21T10:00:00.000Z"
available:
type: boolean
example: false
approved:
type: boolean
example: true
denied:
type: boolean
example: false
requested:
type: boolean
example: true
deniedReason:
type: string
nullable: true
example: "Already on Plex"
theMovieDbId:
type: integer
nullable: true
example: 414906
year:
type: integer
nullable: true
example: 2022
quality:
type: string
nullable: true
example: "1080p"
requestedUser:
type: object
nullable: true
mediaType:
type: string
enum: [movie, tv]
description: Injected by Sofarr to distinguish movies from TV
example: "movie"
BlocklistSearchRequest:
type: object
required:
- arrQueueId
- arrType
- arrInstanceUrl
- arrContentType
properties:
arrQueueId:
type: integer
description: Sonarr/Radarr queue record ID
example: 123
arrType:
type: string
enum: [sonarr, radarr]
description: Which *arr service
example: "sonarr"
arrInstanceUrl:
type: string
format: uri
description: Base URL of the *arr instance
example: "http://sonarr:8989"
arrInstanceKey:
type: string
description: API key for the *arr instance. Only required for admin users; non-admin requests resolve the key from server-side configurations using arrInstanceUrl.
example: "abc123def456"
arrContentId:
type: integer
description: episodeId (Sonarr) or movieId (Radarr)
example: 456
arrContentIds:
type: array
items:
type: integer
description: Array of episodeIds for multi-episode packs (Sonarr)
example: [456, 457]
arrSeriesId:
type: integer
description: seriesId for fallback automatic series search (Sonarr)
example: 789
arrContentType:
type: string
enum: [episode, movie]
description: Content type for search command
example: "episode"
WebhookPayload:
type: object
description: Webhook payload from Sonarr/Radarr
properties:
eventType:
type: string
description: Event type (Grab, Download, DownloadFolderImported, etc.)
example: "Grab"
instanceName:
type: string
description: Instance name from configuration
example: "Main Sonarr"
date:
type: string
format: date-time
description: Event timestamp
example: "2026-05-21T10:00:00.000Z"
HistoryItem:
type: object
properties:
type:
type: string
enum: [series, movie]
example: "series"
outcome:
type: string
enum: [imported, failed]
example: "imported"
title:
type: string
description: Source title from *arr record
example: "Show.Name.S01E01.1080p.WEB-DL"
seriesName:
type: string
nullable: true
example: "Show Name"
movieName:
type: string
nullable: true
example: "Movie Name"
coverArt:
type: string
nullable: true
format: uri
example: "http://sonarr:8989/media/poster.jpg"
completedAt:
type: string
format: date-time
example: "2026-05-21T10:00:00.000Z"
quality:
type: string
nullable: true
example: "HDTV-1080p"
instanceName:
type: string
nullable: true
example: "Main Sonarr"
arrLink:
type: string
nullable: true
format: uri
example: "http://sonarr:8989/series/show-slug"
allTags:
type: array
items:
type: string
example: ["user-john", "user-jane"]
matchedUserTag:
type: string
nullable: true
example: "user-john"
availableForUpgrade:
type: boolean
description: True if failed but content is on disk
example: true
StatusResponse:
type: object
properties:
server:
type: object
properties:
uptimeSeconds:
type: integer
example: 3600
nodeVersion:
type: string
example: "v22.0.0"
memoryUsageMB:
type: number
example: 128.5
heapUsedMB:
type: number
example: 64.2
heapTotalMB:
type: number
example: 128.0
polling:
type: object
properties:
enabled:
type: boolean
example: true
intervalMs:
type: integer
example: 5000
lastPoll:
type: object
additionalProperties: true
cache:
type: object
additionalProperties: true
webhooks:
type: object
properties:
sonarr:
type: object
properties:
configured:
type: boolean
example: true
eventsReceived:
type: integer
example: 42
lastWebhookTimestamp:
type: string
format: date-time
pollsSkipped:
type: integer
example: 15
radarr:
type: object
properties:
configured:
type: boolean
example: true
eventsReceived:
type: integer
example: 38
lastWebhookTimestamp:
type: string
format: date-time
pollsSkipped:
type: integer
example: 12
paths:
# Public health endpoints
/health:
get:
tags: [Health]
summary: Health check
description: Returns server uptime and status. No authentication required.
responses:
'200':
description: Server is healthy
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ok"
uptime:
type: number
example: 3600.5
/ready:
get:
tags: [Health]
summary: Readiness check
description: Checks if critical configuration (EMBY_URL) is present. Used by Docker HEALTHCHECK.
responses:
'200':
description: Server is ready
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ready"
'503':
description: Server not ready
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "not ready"
reason:
type: string
example: "EMBY_URL not configured"
# Auth endpoints (detailed in JSDoc)
/api/auth/login:
post:
tags: [Auth]
summary: Login
description: Authenticate with Emby/Jellyfin and set session cookies
security: []
responses:
'200':
description: Login successful
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
user:
type: object
properties:
id:
type: string
name:
type: string
isAdmin:
type: boolean
csrfToken:
type: string
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/auth/me:
get:
tags: [Auth]
summary: Get current user
description: Returns the currently authenticated user from the session cookie
security:
- CookieAuth: []
responses:
'200':
description: User data
content:
application/json:
schema:
type: object
properties:
authenticated:
type: boolean
user:
type: object
properties:
id:
type: string
name:
type: string
isAdmin:
type: boolean
/api/auth/csrf:
get:
tags: [Auth]
summary: Refresh CSRF token
description: Get a fresh CSRF token without re-authenticating
security: []
responses:
'200':
description: CSRF token
content:
application/json:
schema:
type: object
properties:
csrfToken:
type: string
/api/auth/logout:
post:
tags: [Auth]
summary: Logout
description: Clear session cookies and revoke Emby token
security:
- CookieAuth: []
- CsrfToken: []
responses:
'200':
description: Logout successful
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
# Dashboard endpoints (detailed in JSDoc)
/api/dashboard/user-downloads:
get:
tags: [Dashboard]
summary: Get user downloads (deprecated)
description: DEPRECATED: Use /api/dashboard/stream for real-time updates. Returns current downloads for the authenticated user.
security:
- CookieAuth: []
responses:
'200':
description: User downloads
content:
application/json:
schema:
type: object
properties:
user:
type: string
isAdmin:
type: boolean
downloads:
type: array
items:
$ref: '#/components/schemas/NormalizedDownload'
/api/dashboard/cover-art:
get:
tags: [Dashboard]
summary: Cover art proxy
description: Proxies external poster images server-side for CSP compliance
security:
- CookieAuth: []
parameters:
- name: url
in: query
required: true
schema:
type: string
format: uri
responses:
'200':
description: Image data
content:
image/*:
schema:
type: string
format: binary
'400':
description: Invalid URL or non-image
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/dashboard/stream:
get:
tags: [Dashboard]
summary: SSE stream
description: Server-Sent Events stream for real-time download updates. No CSRF token required (GET request).
security:
- CookieAuth: []
responses:
'200':
description: SSE stream
content:
text/event-stream:
schema:
type: string
/api/dashboard/blocklist-search:
post:
tags: [Dashboard]
summary: Blocklist and re-search
description: Removes queue item with blocklist=true, then triggers new automatic search. Accessible by admins, or by non-admins who own the item under specific eligibility conditions (has import issues, or torrent older than 1h and availability < 100%).
security:
- CookieAuth: []
- CsrfToken: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BlocklistSearchRequest'
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
example: true
'403':
description: Permission denied (admin or qualifying conditions required)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# Status endpoint (detailed in JSDoc)
/api/status/status:
get:
tags: [Status]
summary: Get server status
description: Admin-only endpoint returning server metrics, cache stats, polling info, and webhook metrics
security:
- CookieAuth: []
responses:
'200':
description: Status data
content:
application/json:
schema:
$ref: '#/components/schemas/StatusResponse'
'403':
description: Admin access required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# History endpoint (detailed in JSDoc)
/api/history/recent:
get:
tags: [History]
summary: Get recent history
description: Returns Sonarr/Radarr history records for the authenticated user, filtered by tag and date
security:
- CookieAuth: []
parameters:
- name: days
in: query
schema:
type: integer
minimum: 1
maximum: 90
default: 7
description: Number of days to look back
- name: showAll
in: query
schema:
type: boolean
default: false
description: Admin-only: show all users' history
responses:
'200':
description: History items
content:
application/json:
schema:
type: object
properties:
user:
type: string
isAdmin:
type: boolean
days:
type: integer
history:
type: array
items:
$ref: '#/components/schemas/HistoryItem'
# Webhook endpoints (detailed in JSDoc)
/api/webhook/sonarr:
post:
tags: [Webhook]
summary: Sonarr webhook
description: Receives webhook events from Sonarr. Requires X-Sofarr-Webhook-Secret header or secret query parameter.
security: []
parameters:
- name: secret
in: query
required: false
schema:
type: string
description: Webhook secret token (alternative to X-Sofarr-Webhook-Secret header)
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookPayload'
responses:
'200':
description: Event received
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
duplicate:
type: boolean
'401':
description: Invalid or missing secret
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/webhook/radarr:
post:
tags: [Webhook]
summary: Radarr webhook
description: Receives webhook events from Radarr. Requires X-Sofarr-Webhook-Secret header or secret query parameter.
security: []
parameters:
- name: secret
in: query
required: false
schema:
type: string
description: Webhook secret token (alternative to X-Sofarr-Webhook-Secret header)
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookPayload'
responses:
'200':
description: Event received
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
duplicate:
type: boolean
'401':
description: Invalid or missing secret
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/webhook/ombi:
post:
tags: [Webhook]
summary: Ombi webhook
description: Receives webhook events from Ombi. Requires X-Sofarr-Webhook-Secret header or secret query parameter.
security: []
parameters:
- name: secret
in: query
required: false
schema:
type: string
description: Webhook secret token (alternative to X-Sofarr-Webhook-Secret header)
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Event received
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
example: true
'401':
description: Invalid or missing secret
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/webhook/config:
get:
tags: [Webhook]
summary: Get webhook configuration status
description: Returns whether the required webhook configuration is properly configured.
security:
- CookieAuth: []
responses:
'200':
description: Webhook configuration status
content:
application/json:
schema:
type: object
properties:
valid:
type: boolean
example: true
missing:
type: array
items:
type: string
example: []
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# Sonarr proxy endpoints (detailed in JSDoc)
/api/sonarr/queue:
get:
tags: [Sonarr]
summary: Get Sonarr queue
description: Proxy to Sonarr's queue endpoint
security:
- CookieAuth: []
responses:
'200':
description: Queue data
content:
application/json:
schema:
type: object
'500':
description: Proxy error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/sonarr/history:
get:
tags: [Sonarr]
summary: Get Sonarr history
description: Proxy to Sonarr's history endpoint
security:
- CookieAuth: []
parameters:
- name: pageSize
in: query
schema:
type: integer
default: 50
responses:
'200':
description: History data
content:
application/json:
schema:
type: object
/api/sonarr/series/{id}:
get:
tags: [Sonarr]
summary: Get series details
description: Proxy to Sonarr's series details endpoint
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Series data
content:
application/json:
schema:
type: object
/api/sonarr/series:
get:
tags: [Sonarr]
summary: Get all series
description: Proxy to Sonarr's series list endpoint
security:
- CookieAuth: []
responses:
'200':
description: Series list
content:
application/json:
schema:
type: array
/api/sonarr/notifications:
get:
tags: [Sonarr]
summary: List notifications
description: Proxy to Sonarr's notification list endpoint
security:
- CookieAuth: []
responses:
'200':
description: Notifications list
content:
application/json:
schema:
type: array
'503':
description: Sonarr not configured
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/sonarr/notifications/{id}:
get:
tags: [Sonarr]
summary: Get notification
description: Proxy to Sonarr's notification details endpoint
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Notification data
content:
application/json:
schema:
type: object
/api/sonarr/notifications:
post:
tags: [Sonarr]
summary: Create notification
description: Proxy to Sonarr's notification create endpoint
security:
- CookieAuth: []
- CsrfToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Created notification
content:
application/json:
schema:
type: object
/api/sonarr/notifications/{id}:
put:
tags: [Sonarr]
summary: Update notification
description: Proxy to Sonarr's notification update endpoint
security:
- CookieAuth: []
- CsrfToken: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Updated notification
content:
application/json:
schema:
type: object
/api/sonarr/notifications/{id}:
delete:
tags: [Sonarr]
summary: Delete notification
description: Proxy to Sonarr's notification delete endpoint
security:
- CookieAuth: []
- CsrfToken: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Deleted notification
content:
application/json:
schema:
type: object
/api/sonarr/notifications/test:
post:
tags: [Sonarr]
summary: Test notification
description: Proxy to Sonarr's notification test endpoint
security:
- CookieAuth: []
- CsrfToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Test result
content:
application/json:
schema:
type: object
/api/sonarr/notifications/schema:
get:
tags: [Sonarr]
summary: Get notification schema
description: Proxy to Sonarr's notification schema endpoint
security:
- CookieAuth: []
responses:
'200':
description: Schema data
content:
application/json:
schema:
type: object
/api/sonarr/notifications/sofarr-webhook:
post:
tags: [Sonarr]
summary: Configure Sofarr webhook
description: One-click setup for Sofarr webhook notification in Sonarr
security:
- CookieAuth: []
- CsrfToken: []
responses:
'200':
description: Configured notification
content:
application/json:
schema:
type: object
'400':
description: Missing configuration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Sonarr not configured
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# Radarr proxy endpoints (detailed in JSDoc)
/api/radarr/queue:
get:
tags: [Radarr]
summary: Get Radarr queue
description: Proxy to Radarr's queue endpoint
security:
- CookieAuth: []
responses:
'200':
description: Queue data
content:
application/json:
schema:
type: object
/api/radarr/history:
get:
tags: [Radarr]
summary: Get Radarr history
description: Proxy to Radarr's history endpoint
security:
- CookieAuth: []
parameters:
- name: pageSize
in: query
schema:
type: integer
default: 50
responses:
'200':
description: History data
content:
application/json:
schema:
type: object
/api/radarr/movies/{id}:
get:
tags: [Radarr]
summary: Get movie details
description: Proxy to Radarr's movie details endpoint
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Movie data
content:
application/json:
schema:
type: object
/api/radarr/movies:
get:
tags: [Radarr]
summary: Get all movies
description: Proxy to Radarr's movie list endpoint
security:
- CookieAuth: []
responses:
'200':
description: Movies list
content:
application/json:
schema:
type: array
/api/radarr/notifications:
get:
tags: [Radarr]
summary: List notifications
description: Proxy to Radarr's notification list endpoint
security:
- CookieAuth: []
responses:
'200':
description: Notifications list
content:
application/json:
schema:
type: array
'503':
description: Radarr not configured
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/radarr/notifications/{id}:
get:
tags: [Radarr]
summary: Get notification
description: Proxy to Radarr's notification details endpoint
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Notification data
content:
application/json:
schema:
type: object
/api/radarr/notifications:
post:
tags: [Radarr]
summary: Create notification
description: Proxy to Radarr's notification create endpoint
security:
- CookieAuth: []
- CsrfToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Created notification
content:
application/json:
schema:
type: object
/api/radarr/notifications/{id}:
put:
tags: [Radarr]
summary: Update notification
description: Proxy to Radarr's notification update endpoint
security:
- CookieAuth: []
- CsrfToken: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Updated notification
content:
application/json:
schema:
type: object
/api/radarr/notifications/{id}:
delete:
tags: [Radarr]
summary: Delete notification
description: Proxy to Radarr's notification delete endpoint
security:
- CookieAuth: []
- CsrfToken: []
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Deleted notification
content:
application/json:
schema:
type: object
/api/radarr/notifications/test:
post:
tags: [Radarr]
summary: Test notification
description: Proxy to Radarr's notification test endpoint
security:
- CookieAuth: []
- CsrfToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Test result
content:
application/json:
schema:
type: object
/api/radarr/notifications/schema:
get:
tags: [Radarr]
summary: Get notification schema
description: Proxy to Radarr's notification schema endpoint
security:
- CookieAuth: []
responses:
'200':
description: Schema data
content:
application/json:
schema:
type: object
/api/radarr/notifications/sofarr-webhook:
post:
tags: [Radarr]
summary: Configure Sofarr webhook
description: One-click setup for Sofarr webhook notification in Radarr
security:
- CookieAuth: []
- CsrfToken: []
responses:
'200':
description: Configured notification
content:
application/json:
schema:
type: object
'400':
description: Missing configuration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Radarr not configured
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# SABnzbd proxy endpoints (detailed in JSDoc)
/api/sabnzbd/queue:
get:
tags: [SABnzbd]
summary: Get SABnzbd queue
description: Proxy to SABnzbd's queue endpoint
security:
- CookieAuth: []
responses:
'200':
description: Queue data
content:
application/json:
schema:
type: object
/api/sabnzbd/history:
get:
tags: [SABnzbd]
summary: Get SABnzbd history
description: Proxy to SABnzbd's history endpoint
security:
- CookieAuth: []
parameters:
- name: limit
in: query
schema:
type: integer
default: 50
responses:
'200':
description: History data
content:
application/json:
schema:
type: object
# Emby proxy endpoints (detailed in JSDoc)
/api/emby/sessions:
get:
tags: [Emby]
summary: Get active sessions
description: Proxy to Emby's sessions endpoint
security:
- CookieAuth: []
responses:
'200':
description: Sessions data
content:
application/json:
schema:
type: array
/api/emby/users/{id}:
get:
tags: [Emby]
summary: Get user by ID
description: Proxy to Emby's user details endpoint
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: User data
content:
application/json:
schema:
type: object
/api/emby/users:
get:
tags: [Emby]
summary: Get all users
description: Proxy to Emby's users list endpoint
security:
- CookieAuth: []
responses:
'200':
description: Users list
content:
application/json:
schema:
type: array
/api/emby/session/{sessionId}/user:
get:
tags: [Emby]
summary: Get user from session
description: Get user details for a specific session ID
security:
- CookieAuth: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
responses:
'200':
description: User data
content:
application/json:
schema:
type: object
'404':
description: Session not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# Ombi endpoints
/api/ombi/requests:
get:
tags: [Ombi]
summary: Get Ombi requests
description: Returns Ombi movie and TV requests. Non-admin users only see their own requests, while admins see all requests. Supports server-side filtering by media type, request status, title search, and sorting.
security:
- CookieAuth: []
parameters:
- name: type
in: query
schema:
type: array
items:
type: string
enum: [movie, tv, all]
default: [all]
description: Filter by media type. Omit or use `all` for both.
style: form
explode: true
- name: status
in: query
schema:
type: array
items:
type: string
enum: [pending, approved, available, denied]
description: Filter by request status. Omit for all statuses.
style: form
explode: true
- name: sort
in: query
schema:
type: string
enum: [requestedDate_desc, requestedDate_asc, title_asc, title_desc]
default: requestedDate_desc
description: Sort mode.
- name: search
in: query
schema:
type: string
description: Case-insensitive substring match on title.
- name: showAll
in: query
schema:
type: string
enum: ['true', 'false']
description: Admin only. Show all users' requests.
responses:
'200':
description: Ombi requests retrieved successfully
content:
application/json:
schema:
type: object
properties:
user:
type: string
isAdmin:
type: boolean
showAll:
type: boolean
requests:
type: object
properties:
movie:
type: array
items:
$ref: '#/components/schemas/OmbiRequest'
tv:
type: array
items:
$ref: '#/components/schemas/OmbiRequest'
total:
type: integer
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/ombi/webhook/enable:
post:
tags: [Ombi]
summary: Enable Ombi webhook
description: Registers or updates the Sofarr webhook in Ombi. Requires authentication and CSRF protection.
security:
- CookieAuth: []
responses:
'200':
description: Webhook enabled successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
webhookUrl:
type: string
applicationToken:
type: string
'400':
description: Invalid request or missing configuration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/ombi/webhook/status:
get:
tags: [Ombi]
summary: Get Ombi webhook status
description: Returns the current Ombi webhook configuration status and metrics.
security:
- CookieAuth: []
responses:
'200':
description: Webhook status retrieved successfully
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
webhookUrl:
type: string
nullable: true
applicationToken:
type: string
nullable: true
triggers:
type: object
properties:
requestAvailable:
type: boolean
requestApproved:
type: boolean
requestDeclined:
type: boolean
requestPending:
type: boolean
requestProcessing:
type: boolean
stats:
type: object
nullable: true
properties:
eventsReceived:
type: integer
pollsSkipped:
type: integer
lastWebhookTimestamp:
type: integer
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/ombi/webhook/test:
post:
tags: [Ombi]
summary: Test Ombi webhook
description: Sends a test webhook event to the Sofarr Ombi webhook endpoint.
security:
- CookieAuth: []
- CsrfToken: []
responses:
'200':
description: Test webhook sent successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
'400':
description: Invalid request or missing configuration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/debug/status:
get:
tags: [Debug]
summary: Check if log streaming is enabled
description: Returns whether the log streaming feature is enabled at runtime. No authentication required.
security: []
responses:
'200':
description: Feature status returned successfully
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
example: true
/api/debug/server-logs:
get:
tags: [Debug]
summary: Stream server logs in real-time
description: |
Streams server-side standard output (stdout/stderr) logs via Server-Sent Events (SSE).
**Security Policies:**
- **Subnet IP Filtering**: IP must match subnet ranges configured in `LOG_ALLOW_SUBNETS` (if set).
- **Bypass Header**: Direct bypass if `X-Webhook-Secret` header matches the configured `SOFARR_WEBHOOK_SECRET`.
- **Session Auth**: Emby session cookie `emby_user` where user is an administrator.
- **Basic Auth Fallback**: `Authorization` header containing credentials of a valid Emby administrator.
security:
- CookieAuth: []
parameters:
- name: X-Webhook-Secret
in: header
required: false
schema:
type: string
description: Fast-track webhook secret bypass token
responses:
'200':
description: Event stream established
content:
text/event-stream:
schema:
type: string
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden (feature disabled or IP not in subnet allowlist)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/debug/client-logs:
get:
tags: [Debug]
summary: Stream client console logs in real-time
description: |
Streams client-side console logs via Server-Sent Events (SSE).
**Security Policies:**
- **Subnet IP Filtering**: IP must match subnet ranges configured in `LOG_ALLOW_SUBNETS` (if set).
- **Bypass Header**: Direct bypass if `X-Webhook-Secret` header matches the configured `SOFARR_WEBHOOK_SECRET`.
- **Session Auth**: Emby session cookie `emby_user` where user is an administrator.
- **Basic Auth Fallback**: `Authorization` header containing credentials of a valid Emby administrator.
security:
- CookieAuth: []
parameters:
- name: X-Webhook-Secret
in: header
required: false
schema:
type: string
description: Fast-track webhook secret bypass token
responses:
'200':
description: Event stream established
content:
text/event-stream:
schema:
type: string
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden (feature disabled or IP not in subnet allowlist)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
tags: [Debug]
summary: Ingest client console logs
description: |
Ingests a batch of client-side console logs into the server-side rolling clientLogBuffer.
**Security Policies:**
- **Subnet IP Filtering**: IP must match subnet ranges configured in `LOG_ALLOW_SUBNETS` (if set).
- **Bypass Header**: Direct bypass if `X-Webhook-Secret` header matches the configured `SOFARR_WEBHOOK_SECRET`.
- **Session Auth**: Emby session cookie `emby_user` where user is an administrator.
- **Basic Auth Fallback**: `Authorization` header containing credentials of a valid Emby administrator.
security:
- CookieAuth: []
parameters:
- name: X-Webhook-Secret
in: header
required: false
schema:
type: string
description: Fast-track webhook secret bypass token
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
type: object
required: [level, message]
properties:
timestamp:
type: string
format: date-time
level:
type: string
enum: [info, warn, error]
message:
type: string
responses:
'200':
description: Logs ingested successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
count:
type: integer
'400':
description: Invalid JSON body
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden (feature disabled or IP not in subnet allowlist)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'