Files
sofarr/server/openapi.yaml
T
gronod b2aa4f23fa
Build and Push Docker Image / build (push) Successful in 1m16s
Docs Check / Markdown lint (push) Successful in 1m36s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m14s
CI / Security audit (push) Successful in 2m42s
Docs Check / Mermaid diagram parse check (push) Successful in 3m3s
CI / Swagger Validation & Coverage (push) Successful in 3m20s
CI / Tests & coverage (push) Successful in 6m38s
chore: bump version to 1.7.37 and update CHANGELOG and docs
2026-05-29 14:37:36 +01:00

1970 lines
56 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.37
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: Selective Sonarr API proxy (specific endpoints only)
- name: Radarr
description: Selective Radarr API proxy (specific endpoints only)
- 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"
arrLink:
type: string
nullable: true
format: uri
description: Sonarr/Radarr show/movie web UI link (admin-only)
example: "http://sonarr:8989/series/show-slug"
downloadPath:
type: string
nullable: true
description: Save path in download client (admin-only)
example: "/downloads/series/show-slug"
targetPath:
type: string
nullable: true
description: Target path in library (admin-only)
example: "/tv/show-slug"
arrInstanceKey:
type: string
nullable: true
description: Sonarr/Radarr instance API key (admin-only)
example: "api-key-here"
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'