Files
zpan/docs/openapi/downloader.json
T
Jasper VanandClaude Opus 4.8 5a5583b4ed feat(licensing): regroup comparison table by capability and add social-login/downloader gates (#423)
* feat(licensing): regroup comparison table by capability and add social-login/downloader gates

Decouple the feature comparison table's grouping axis from the pricing tier:
features are now grouped by capability (core/advanced) while edition
availability is expressed purely by the per-edition cells. Coming-soon
features show a badge next to the name with a muted check in the target
edition column, so it's clear which edition they will land in.

Tier reclassification (per product decision):
- Social login & OIDC: free = 1 provider, Pro/Business = unlimited
- Downloaders: free = 1, Pro/Business = unlimited
- Site announcements, Multi-IdP SSO, LDAP/SCIM, Analytics: Business-only

New runtime gates (enforced, mirroring the storages count-gate):
- social_login_unlimited in POST /api/admin/auth-providers (402 on 2nd)
- downloaders_unlimited in POST /api/admin/downloaders (402 on 2nd)
- site_announcements added to BUSINESS_ONLY_FEATURES

Copy cleanup:
- Rename rows that embedded a limit word: "Unlimited Team Workspaces"
  -> "Team Workspaces", "Storage Backends" -> "Storages"
- Clarify "Storage Plans" -> "Sell Storage & Traffic" (the quota_store feature)
- Make the Licensing page intro edition-neutral (Pro + Business) instead of
  the leftover Pro-only copy

Tests: add gate tests for both new limits; seed licenses in the existing
multi-provider/multi-downloader tests; switch announcement tests to a
Business license.

Note: site_announcements moving to Business takes full effect for real
licenses only once zpan-cloud stops listing it in Pro certificates; the
local edition-derived path is already updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(licensing): drop unused per-cert feature override, derive from edition

The optional `features[]` override on the license certificate was added with
the Pro/Business split but was never exercised: real certs carry only
`edition`, and entitlements are derived from it via the feature registry
(PRO_GATE_KEYS minus BUSINESS_ONLY_FEATURES). The override was dead in the
normal flow and duplicated the edition→feature mapping in two places.

Remove it so edition is the single source of truth:
- Drop `LicenseAssertion.features` and `normalizeFeatures` (verify.ts)
- `effectiveFeatures(edition)` no longer takes/honors an override list
- Simplify the test seed helpers (no `features` arg, no test-side
  business-only set) and update licensing tests to assert edition-derived
  entitlements

`BindingState.features` (the resolved list exposed to the client) is kept.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(downloader): regenerate OpenAPI spec and Go client for new 402 response

The downloaders create route gained a 402 (feature_not_available) response
for the free-plan limit; regenerate the committed OpenAPI document and Go
client so openapi:downloader:check passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 13:32:59 -04:00

5303 lines
189 KiB
JSON

{
"openapi": "3.0.0",
"info": {
"title": "ZPan Downloader API",
"version": "0.1.0"
},
"components": {
"schemas": {
"DeviceCode": {
"type": "object",
"properties": {
"device_code": {
"type": "string"
},
"user_code": {
"type": "string"
},
"verification_uri": {
"type": "string"
},
"verification_uri_complete": {
"type": "string"
},
"expires_in": {
"type": "integer"
},
"interval": {
"type": "integer"
}
},
"required": [
"device_code",
"user_code",
"verification_uri",
"verification_uri_complete",
"expires_in",
"interval"
]
},
"DeviceCodeRequest": {
"type": "object",
"properties": {
"client_id": {
"type": "string"
},
"scope": {
"type": "string"
}
},
"required": [
"client_id",
"scope"
]
},
"DeviceToken": {
"type": "object",
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"expires_in": {
"type": "integer"
},
"scope": {
"type": "string"
}
},
"required": [
"access_token",
"token_type",
"expires_in",
"scope"
]
},
"ErrorResponse": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
},
"DeviceTokenRequest": {
"type": "object",
"properties": {
"grant_type": {
"type": "string"
},
"device_code": {
"type": "string"
},
"client_id": {
"type": "string"
}
},
"required": [
"grant_type",
"device_code",
"client_id"
]
}
},
"parameters": {}
},
"paths": {
"/api/auth/device/code": {
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceCodeRequest"
}
}
}
},
"responses": {
"200": {
"description": "Device authorization code",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceCode"
}
}
}
}
}
}
},
"/api/auth/device/token": {
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceTokenRequest"
}
}
}
},
"responses": {
"200": {
"description": "Device access token",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceToken"
}
}
}
},
"400": {
"description": "Device login error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/api/download-tasks": {
"get": {
"parameters": [
{
"schema": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"required": false,
"name": "status",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"me"
]
},
"required": false,
"name": "assignedTo",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"required": false,
"name": "category",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"required": false,
"name": "tag",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"createdAt",
"source",
"category",
"tags",
"status",
"progress",
"eta"
],
"default": "createdAt"
},
"required": false,
"name": "sortBy",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"asc",
"desc"
],
"default": "desc"
},
"required": false,
"name": "sortDir",
"in": "query"
},
{
"schema": {
"type": "integer",
"minimum": 1,
"default": 1
},
"required": false,
"name": "page",
"in": "query"
},
{
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"required": false,
"name": "pageSize",
"in": "query"
}
],
"responses": {
"200": {
"description": "Download tasks",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"orgId": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string"
}
},
"required": [
"type",
"uri"
]
},
"destination": {
"type": "object",
"properties": {
"folder": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
}
},
"required": [
"folder",
"name"
]
},
"labels": {
"type": "object",
"properties": {
"category": {
"type": "string",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"category",
"tags"
]
}
},
"required": [
"source",
"destination",
"labels"
]
},
"status": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"attempt": {
"type": "integer",
"minimum": 1
},
"assignment": {
"type": "object",
"nullable": true,
"properties": {
"downloaderId": {
"type": "string"
},
"assignedAt": {
"type": "string",
"nullable": true
},
"uploadToken": {
"type": "string"
}
},
"required": [
"downloaderId"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"billing": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"none",
"ok",
"insufficient_credits"
]
},
"authorizedBytes": {
"type": "integer",
"format": "int64"
},
"chargedBytes": {
"type": "integer",
"format": "int64"
},
"chargedCredits": {
"type": "integer",
"format": "int64"
}
},
"required": [
"state",
"authorizedBytes",
"chargedBytes",
"chargedCredits"
]
},
"output": {
"type": "object",
"nullable": true,
"properties": {
"objectId": {
"type": "string"
}
},
"required": [
"objectId"
]
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
},
"error": {
"type": "object",
"nullable": true,
"properties": {
"code": {
"type": "string",
"nullable": true,
"maxLength": 80
},
"message": {
"type": "string",
"nullable": true,
"maxLength": 1000
}
},
"required": [
"message"
]
},
"startedAt": {
"type": "string",
"nullable": true
},
"finishedAt": {
"type": "string",
"nullable": true
},
"updatedAt": {
"type": "string"
}
},
"required": [
"state",
"attempt",
"assignment",
"progress",
"billing",
"output",
"runtime",
"error",
"startedAt",
"finishedAt",
"updatedAt"
]
},
"createdAt": {
"type": "string"
}
},
"required": [
"id",
"spec",
"status",
"createdAt"
]
}
},
"total": {
"type": "integer"
},
"page": {
"type": "integer"
},
"pageSize": {
"type": "integer"
}
},
"required": [
"items",
"total",
"page",
"pageSize"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
},
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string",
"minLength": 1,
"maxLength": 4096
}
},
"required": [
"type",
"uri"
]
},
"targetFolder": {
"type": "string",
"maxLength": 1024
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"category": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"tags": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"maxItems": 20
}
},
"required": [
"source",
"targetFolder"
]
}
}
}
},
"responses": {
"201": {
"description": "Created download task",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"orgId": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string"
}
},
"required": [
"type",
"uri"
]
},
"destination": {
"type": "object",
"properties": {
"folder": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
}
},
"required": [
"folder",
"name"
]
},
"labels": {
"type": "object",
"properties": {
"category": {
"type": "string",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"category",
"tags"
]
}
},
"required": [
"source",
"destination",
"labels"
]
},
"status": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"attempt": {
"type": "integer",
"minimum": 1
},
"assignment": {
"type": "object",
"nullable": true,
"properties": {
"downloaderId": {
"type": "string"
},
"assignedAt": {
"type": "string",
"nullable": true
},
"uploadToken": {
"type": "string"
}
},
"required": [
"downloaderId"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"billing": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"none",
"ok",
"insufficient_credits"
]
},
"authorizedBytes": {
"type": "integer",
"format": "int64"
},
"chargedBytes": {
"type": "integer",
"format": "int64"
},
"chargedCredits": {
"type": "integer",
"format": "int64"
}
},
"required": [
"state",
"authorizedBytes",
"chargedBytes",
"chargedCredits"
]
},
"output": {
"type": "object",
"nullable": true,
"properties": {
"objectId": {
"type": "string"
}
},
"required": [
"objectId"
]
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
},
"error": {
"type": "object",
"nullable": true,
"properties": {
"code": {
"type": "string",
"nullable": true,
"maxLength": 80
},
"message": {
"type": "string",
"nullable": true,
"maxLength": 1000
}
},
"required": [
"message"
]
},
"startedAt": {
"type": "string",
"nullable": true
},
"finishedAt": {
"type": "string",
"nullable": true
},
"updatedAt": {
"type": "string"
}
},
"required": [
"state",
"attempt",
"assignment",
"progress",
"billing",
"output",
"runtime",
"error",
"startedAt",
"finishedAt",
"updatedAt"
]
},
"createdAt": {
"type": "string"
}
},
"required": [
"id",
"spec",
"status",
"createdAt"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"402": {
"description": "Insufficient credits",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"409": {
"description": "Download task conflict",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/download-tasks/events": {
"get": {
"parameters": [
{
"schema": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"required": false,
"name": "status",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"me"
]
},
"required": false,
"name": "assignedTo",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"required": false,
"name": "category",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"required": false,
"name": "tag",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"createdAt",
"source",
"category",
"tags",
"status",
"progress",
"eta"
],
"default": "createdAt"
},
"required": false,
"name": "sortBy",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"asc",
"desc"
],
"default": "desc"
},
"required": false,
"name": "sortDir",
"in": "query"
},
{
"schema": {
"type": "integer",
"minimum": 1,
"default": 1
},
"required": false,
"name": "page",
"in": "query"
},
{
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"required": false,
"name": "pageSize",
"in": "query"
}
],
"responses": {
"200": {
"description": "Download task events",
"content": {
"text/event-stream": {
"schema": {
"type": "string"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/download-tasks/{id}": {
"get": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"responses": {
"200": {
"description": "Download task",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"orgId": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string"
}
},
"required": [
"type",
"uri"
]
},
"destination": {
"type": "object",
"properties": {
"folder": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
}
},
"required": [
"folder",
"name"
]
},
"labels": {
"type": "object",
"properties": {
"category": {
"type": "string",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"category",
"tags"
]
}
},
"required": [
"source",
"destination",
"labels"
]
},
"status": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"attempt": {
"type": "integer",
"minimum": 1
},
"assignment": {
"type": "object",
"nullable": true,
"properties": {
"downloaderId": {
"type": "string"
},
"assignedAt": {
"type": "string",
"nullable": true
},
"uploadToken": {
"type": "string"
}
},
"required": [
"downloaderId"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"billing": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"none",
"ok",
"insufficient_credits"
]
},
"authorizedBytes": {
"type": "integer",
"format": "int64"
},
"chargedBytes": {
"type": "integer",
"format": "int64"
},
"chargedCredits": {
"type": "integer",
"format": "int64"
}
},
"required": [
"state",
"authorizedBytes",
"chargedBytes",
"chargedCredits"
]
},
"output": {
"type": "object",
"nullable": true,
"properties": {
"objectId": {
"type": "string"
}
},
"required": [
"objectId"
]
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
},
"error": {
"type": "object",
"nullable": true,
"properties": {
"code": {
"type": "string",
"nullable": true,
"maxLength": 80
},
"message": {
"type": "string",
"nullable": true,
"maxLength": 1000
}
},
"required": [
"message"
]
},
"startedAt": {
"type": "string",
"nullable": true
},
"finishedAt": {
"type": "string",
"nullable": true
},
"updatedAt": {
"type": "string"
}
},
"required": [
"state",
"attempt",
"assignment",
"progress",
"billing",
"output",
"runtime",
"error",
"startedAt",
"finishedAt",
"updatedAt"
]
},
"createdAt": {
"type": "string"
}
},
"required": [
"id",
"spec",
"status",
"createdAt"
]
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
},
"patch": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
}
},
"errorMessage": {
"type": "string",
"nullable": true,
"maxLength": 1000
},
"resultObjectId": {
"type": "string",
"nullable": true,
"minLength": 1
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
}
}
}
}
}
},
"responses": {
"200": {
"description": "Updated download task",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"orgId": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string"
}
},
"required": [
"type",
"uri"
]
},
"destination": {
"type": "object",
"properties": {
"folder": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
}
},
"required": [
"folder",
"name"
]
},
"labels": {
"type": "object",
"properties": {
"category": {
"type": "string",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"category",
"tags"
]
}
},
"required": [
"source",
"destination",
"labels"
]
},
"status": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"attempt": {
"type": "integer",
"minimum": 1
},
"assignment": {
"type": "object",
"nullable": true,
"properties": {
"downloaderId": {
"type": "string"
},
"assignedAt": {
"type": "string",
"nullable": true
},
"uploadToken": {
"type": "string"
}
},
"required": [
"downloaderId"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"billing": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"none",
"ok",
"insufficient_credits"
]
},
"authorizedBytes": {
"type": "integer",
"format": "int64"
},
"chargedBytes": {
"type": "integer",
"format": "int64"
},
"chargedCredits": {
"type": "integer",
"format": "int64"
}
},
"required": [
"state",
"authorizedBytes",
"chargedBytes",
"chargedCredits"
]
},
"output": {
"type": "object",
"nullable": true,
"properties": {
"objectId": {
"type": "string"
}
},
"required": [
"objectId"
]
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
},
"error": {
"type": "object",
"nullable": true,
"properties": {
"code": {
"type": "string",
"nullable": true,
"maxLength": 80
},
"message": {
"type": "string",
"nullable": true,
"maxLength": 1000
}
},
"required": [
"message"
]
},
"startedAt": {
"type": "string",
"nullable": true
},
"finishedAt": {
"type": "string",
"nullable": true
},
"updatedAt": {
"type": "string"
}
},
"required": [
"state",
"attempt",
"assignment",
"progress",
"billing",
"output",
"runtime",
"error",
"startedAt",
"finishedAt",
"updatedAt"
]
},
"createdAt": {
"type": "string"
}
},
"required": [
"id",
"spec",
"status",
"createdAt"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"402": {
"description": "Insufficient credits",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"409": {
"description": "Download task conflict",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/download-tasks/{id}/actions": {
"post": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"pause",
"resume",
"cancel",
"retry",
"restart",
"delete"
]
}
},
"required": [
"action"
]
}
}
}
},
"responses": {
"200": {
"description": "Task action result",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"orgId": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"http",
"magnet",
"torrent_url"
]
},
"uri": {
"type": "string"
}
},
"required": [
"type",
"uri"
]
},
"destination": {
"type": "object",
"properties": {
"folder": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
}
},
"required": [
"folder",
"name"
]
},
"labels": {
"type": "object",
"properties": {
"category": {
"type": "string",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"category",
"tags"
]
}
},
"required": [
"source",
"destination",
"labels"
]
},
"status": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"queued",
"assigned",
"downloading",
"suspended",
"pausing",
"paused",
"interrupted",
"uploading",
"canceling",
"completed",
"failed",
"canceled"
]
},
"attempt": {
"type": "integer",
"minimum": 1
},
"assignment": {
"type": "object",
"nullable": true,
"properties": {
"downloaderId": {
"type": "string"
},
"assignedAt": {
"type": "string",
"nullable": true
},
"uploadToken": {
"type": "string"
}
},
"required": [
"downloaderId"
]
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"billing": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"none",
"ok",
"insufficient_credits"
]
},
"authorizedBytes": {
"type": "integer",
"format": "int64"
},
"chargedBytes": {
"type": "integer",
"format": "int64"
},
"chargedCredits": {
"type": "integer",
"format": "int64"
}
},
"required": [
"state",
"authorizedBytes",
"chargedBytes",
"chargedCredits"
]
},
"output": {
"type": "object",
"nullable": true,
"properties": {
"objectId": {
"type": "string"
}
},
"required": [
"objectId"
]
},
"runtime": {
"type": "object",
"nullable": true,
"properties": {
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"state": {
"type": "string",
"maxLength": 80
},
"phase": {
"type": "string",
"enum": [
"metadata",
"downloading",
"uploading",
"seeding",
"completed",
"error"
]
},
"message": {
"type": "string",
"maxLength": 500
},
"updatedAt": {
"type": "string"
},
"progress": {
"type": "object",
"properties": {
"download": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
},
"upload": {
"type": "object",
"properties": {
"bytes": {
"type": "integer",
"format": "int64"
},
"totalBytes": {
"type": "integer",
"format": "int64",
"nullable": true
},
"bytesPerSecond": {
"type": "integer",
"format": "int64"
}
},
"required": [
"bytes",
"bytesPerSecond"
]
}
},
"required": [
"download",
"upload"
]
},
"torrent": {
"type": "object",
"properties": {
"infoHash": {
"type": "string",
"maxLength": 120
},
"name": {
"type": "string",
"maxLength": 255
},
"seeders": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"peers": {
"type": "integer",
"minimum": 0
}
}
},
"seeding": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"active": {
"type": "boolean"
},
"uploadedBytes": {
"type": "integer",
"format": "int64"
},
"uploadBytesPerSecond": {
"type": "integer",
"format": "int64"
},
"ratio": {
"type": "number",
"minimum": 0
},
"startedAt": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "string",
"nullable": true
}
}
},
"connections": {
"type": "integer",
"minimum": 0
},
"etaSeconds": {
"type": "integer",
"nullable": true,
"minimum": 0
},
"trackers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "string",
"maxLength": 80
},
"peers": {
"type": "integer",
"minimum": 0
},
"seeds": {
"type": "integer",
"minimum": 0
},
"leechers": {
"type": "integer",
"minimum": 0
},
"message": {
"type": "string",
"maxLength": 500
}
},
"required": [
"url"
]
},
"maxItems": 20
},
"peers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address": {
"type": "string",
"maxLength": 160
},
"client": {
"type": "string",
"maxLength": 160
},
"progress": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"countryCode": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"regionCode": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"address"
]
},
"maxItems": 20
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"maxLength": 1024
},
"size": {
"type": "integer",
"format": "int64"
},
"completedBytes": {
"type": "integer",
"format": "int64"
},
"selected": {
"type": "boolean"
}
},
"required": [
"path",
"size"
]
},
"maxItems": 50
}
}
},
"error": {
"type": "object",
"nullable": true,
"properties": {
"code": {
"type": "string",
"nullable": true,
"maxLength": 80
},
"message": {
"type": "string",
"nullable": true,
"maxLength": 1000
}
},
"required": [
"message"
]
},
"startedAt": {
"type": "string",
"nullable": true
},
"finishedAt": {
"type": "string",
"nullable": true
},
"updatedAt": {
"type": "string"
}
},
"required": [
"state",
"attempt",
"assignment",
"progress",
"billing",
"output",
"runtime",
"error",
"startedAt",
"finishedAt",
"updatedAt"
]
},
"createdAt": {
"type": "string"
}
},
"required": [
"id",
"spec",
"status",
"createdAt"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"deleted": {
"type": "boolean",
"enum": [
true
]
}
},
"required": [
"id",
"deleted"
]
}
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"409": {
"description": "Invalid task state",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/downloader/heartbeat": {
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"version": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"hostname": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"platform": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"arch": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"maxItems": 32
},
"maxConcurrentTasks": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"currentTasks": {
"type": "integer",
"minimum": 0,
"maximum": 100
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks"
]
}
}
}
},
"responses": {
"200": {
"description": "Updated downloader",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"online",
"offline",
"disabled"
]
},
"enabled": {
"type": "boolean"
},
"heartbeat": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"hostname": {
"type": "string"
},
"platform": {
"type": "string"
},
"arch": {
"type": "string"
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string"
}
},
"maxConcurrentTasks": {
"type": "integer"
},
"currentTasks": {
"type": "integer"
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks",
"downloadBps",
"uploadBps",
"freeDiskBytes"
]
}
},
"required": [
"id"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/admin/downloaders": {
"get": {
"responses": {
"200": {
"description": "Downloaders",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"online",
"offline",
"disabled"
]
},
"enabled": {
"type": "boolean"
},
"heartbeat": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"hostname": {
"type": "string"
},
"platform": {
"type": "string"
},
"arch": {
"type": "string"
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string"
}
},
"maxConcurrentTasks": {
"type": "integer"
},
"currentTasks": {
"type": "integer"
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks",
"downloadBps",
"uploadBps",
"freeDiskBytes"
]
}
},
"required": [
"id"
]
}
},
"total": {
"type": "integer"
}
},
"required": [
"items",
"total"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
},
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"heartbeat": {
"type": "object",
"properties": {
"version": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"hostname": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"platform": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"arch": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"maxItems": 32
},
"maxConcurrentTasks": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"currentTasks": {
"type": "integer",
"minimum": 0,
"maximum": 100
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks"
]
}
},
"required": [
"name",
"heartbeat"
]
}
}
}
},
"responses": {
"201": {
"description": "Downloader registration",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"downloader": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"online",
"offline",
"disabled"
]
},
"enabled": {
"type": "boolean"
},
"heartbeat": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"hostname": {
"type": "string"
},
"platform": {
"type": "string"
},
"arch": {
"type": "string"
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string"
}
},
"maxConcurrentTasks": {
"type": "integer"
},
"currentTasks": {
"type": "integer"
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks",
"downloadBps",
"uploadBps",
"freeDiskBytes"
]
}
},
"required": [
"id"
]
},
"token": {
"type": "string"
}
},
"required": [
"downloader",
"token"
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
},
"402": {
"description": "Feature not available",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/admin/downloaders/{id}": {
"patch": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"enabled": {
"type": "boolean"
},
"remoteDownloadCreditBillingEnabled": {
"type": "boolean"
},
"remoteDownloadCreditUnitBytes": {
"type": "integer",
"minimum": 0,
"exclusiveMinimum": true
},
"remoteDownloadCreditPerUnit": {
"type": "integer",
"minimum": 0,
"exclusiveMinimum": true
}
}
}
}
}
},
"responses": {
"200": {
"description": "Updated downloader",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"online",
"offline",
"disabled"
]
},
"enabled": {
"type": "boolean"
},
"heartbeat": {
"type": "object",
"properties": {
"version": {
"type": "string"
},
"hostname": {
"type": "string"
},
"platform": {
"type": "string"
},
"arch": {
"type": "string"
},
"engine": {
"type": "string",
"enum": [
"builtin",
"aria2",
"qbittorrent"
]
},
"capabilities": {
"type": "array",
"items": {
"type": "string"
}
},
"maxConcurrentTasks": {
"type": "integer"
},
"currentTasks": {
"type": "integer"
},
"downloadBps": {
"type": "integer",
"format": "int64"
},
"uploadBps": {
"type": "integer",
"format": "int64"
},
"freeDiskBytes": {
"type": "integer",
"format": "int64"
}
},
"required": [
"version",
"hostname",
"platform",
"arch",
"engine",
"capabilities",
"maxConcurrentTasks",
"currentTasks",
"downloadBps",
"uploadBps",
"freeDiskBytes"
]
}
},
"required": [
"id"
]
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
},
"delete": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"responses": {
"200": {
"description": "Deleted downloader",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"deleted": {
"type": "boolean"
}
},
"required": [
"id",
"deleted"
]
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
},
"required": [
"error"
]
}
}
}
}
}
}
},
"/api/objects": {
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string",
"minLength": 1
},
"size": {
"type": "integer",
"minimum": 0
},
"parent": {
"type": "string",
"default": ""
},
"dirtype": {
"type": "integer",
"default": 0
},
"onConflict": {
"type": "string",
"enum": [
"fail",
"rename",
"replace"
]
}
},
"required": [
"name",
"type"
]
}
}
}
},
"responses": {
"200": {
"description": "Object draft with upload URL",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"uploadUrl": {
"type": "string"
},
"contentDisposition": {
"type": "string"
}
},
"required": [
"id",
"name"
]
}
}
}
},
"201": {
"description": "Object draft with upload URL",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"uploadUrl": {
"type": "string"
},
"contentDisposition": {
"type": "string"
}
},
"required": [
"id",
"name"
]
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"409": {
"description": "Name conflict",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/api/objects/{id}": {
"patch": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"confirm"
]
},
"onConflict": {
"type": "string",
"enum": [
"fail",
"rename",
"replace"
]
}
},
"required": [
"action"
]
}
}
}
},
"responses": {
"200": {
"description": "Confirmed object",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"uploadUrl": {
"type": "string"
},
"contentDisposition": {
"type": "string"
}
},
"required": [
"id",
"name"
]
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/api/objects/{id}/uploads": {
"post": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"partSize": {
"type": "integer",
"minimum": 5242880,
"maximum": 536870912
}
}
}
}
}
},
"responses": {
"201": {
"description": "Object multipart upload session",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"objectId": {
"type": "string"
},
"uploadId": {
"type": "string"
},
"partSize": {
"type": "integer"
},
"status": {
"type": "string",
"enum": [
"active",
"completed",
"aborted"
]
},
"expiresAt": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
},
"required": [
"id",
"objectId",
"uploadId",
"partSize",
"status",
"expiresAt",
"createdAt",
"updatedAt"
]
}
}
}
},
"400": {
"description": "Invalid upload session",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/api/objects/{id}/uploads/{uploadSessionId}/parts": {
"post": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
},
{
"schema": {
"type": "string"
},
"required": true,
"name": "uploadSessionId",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"partNumbers": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"minItems": 1,
"maxItems": 100
}
},
"required": [
"partNumbers"
]
}
}
}
},
"responses": {
"200": {
"description": "Presigned multipart upload parts",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"uploadId": {
"type": "string"
},
"partSize": {
"type": "integer"
},
"parts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"partNumber": {
"type": "integer"
},
"url": {
"type": "string"
}
},
"required": [
"partNumber",
"url"
]
}
}
},
"required": [
"uploadId",
"partSize",
"parts"
]
}
}
}
},
"400": {
"description": "Invalid upload session",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
"/api/objects/{id}/uploads/{uploadSessionId}": {
"patch": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "id",
"in": "path"
},
{
"schema": {
"type": "string"
},
"required": true,
"name": "uploadSessionId",
"in": "path"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"complete"
]
},
"parts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"partNumber": {
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"etag": {
"type": "string",
"minLength": 1
}
},
"required": [
"partNumber",
"etag"
]
},
"minItems": 1
}
},
"required": [
"action",
"parts"
]
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"abort"
]
}
},
"required": [
"action"
]
}
]
}
}
}
},
"responses": {
"200": {
"description": "Updated object multipart upload session",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"objectId": {
"type": "string"
},
"uploadId": {
"type": "string"
},
"partSize": {
"type": "integer"
},
"status": {
"type": "string",
"enum": [
"active",
"completed",
"aborted"
]
},
"expiresAt": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
},
"required": [
"id",
"objectId",
"uploadId",
"partSize",
"status",
"expiresAt",
"createdAt",
"updatedAt"
]
}
}
}
},
"400": {
"description": "Invalid upload session",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
}
}
}