-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAPI.openapi.json
More file actions
186 lines (186 loc) · 37.4 KB
/
Copy pathAPI.openapi.json
File metadata and controls
186 lines (186 loc) · 37.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
{
"openapi": "3.1.0",
"info": {
"title": "TorrentNG API",
"version": "0.1.0",
"description": "Machine-readable contract for the implemented TorrentNG /api/v1 JSON REST surface. Compatibility facades are documented by their client-specific matrices. Mutating requests accept an optional Idempotency-Key; successful responses may be replayed with Idempotency-Replayed: true. API tokens are bearer tokens or tng_session cookies."
},
"servers": [{"url": "/"}],
"security": [{"bearerAuth": []}, {"sessionCookie": []}],
"paths": {
"/health": {
"get": {"operationId": "health", "security": [], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "503": {"$ref": "#/components/responses/JsonError"}}}
},
"/metrics": {
"get": {"operationId": "metrics", "responses": {"200": {"description": "Prometheus text exposition", "content": {"text/plain": {"schema": {"type": "string"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}
},
"/api/v1/auth/login": {
"post": {"operationId": "authLogin", "security": [], "requestBody": {"$ref": "#/components/requestBodies/AuthLoginForm"}, "responses": {"200": {"description": "Login accepted; sets the tng_session cookie", "content": {"text/plain": {"schema": {"type": "string", "enum": ["Ok."]}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "429": {"description": "Login rate limit reached; response includes Retry-After"}}}
},
"/api/v1/auth/logout": {
"post": {"operationId": "authLogout", "security": [], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}
},
"/api/v1/auth/settings": {
"get": {"operationId": "getAuthSettings", "responses": {"200": {"description": "Current safe authentication settings; does not return the password", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AuthSettings"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}},
"put": {"operationId": "updateAuthSettings", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/UpdateAuthSettings"}, "responses": {"200": {"description": "Updated safe authentication settings", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AuthSettings"}}}}, "400": {"$ref": "#/components/responses/JsonError"}, "401": {"$ref": "#/components/responses/Unauthorized"}}},
"delete": {"operationId": "resetAuthSettings", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"description": "Config-file authentication settings restored", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AuthSettings"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}
},
"/api/v1/torrents": {
"get": {"operationId": "listTorrents", "parameters": [{"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/Offset"}, {"$ref": "#/components/parameters/Snapshot"}, {"$ref": "#/components/parameters/Filter"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "401": {"$ref": "#/components/responses/Unauthorized"}}},
"post": {"operationId": "addTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/AddTorrent"}, "responses": {"201": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}}
},
"/api/v1/torrents/live": {
"get": {"operationId": "liveTorrentStats", "parameters": [{"name": "hashes", "in": "query", "required": true, "description": "Comma-separated list of at most 128 non-empty 40/64-character hexadecimal info hashes; repeated entries count toward the limit and the value is capped at 8,320 bytes", "schema": {"type": "string", "maxLength": 8320}}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "503": {"$ref": "#/components/responses/JsonError"}}}
},
"/api/v1/torrents/{hash}": {
"parameters": [{"$ref": "#/components/parameters/Hash"}],
"get": {"operationId": "getTorrent", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "404": {"$ref": "#/components/responses/NotFound"}}},
"put": {"operationId": "updateTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "202": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "404": {"$ref": "#/components/responses/NotFound"}}},
"delete": {"operationId": "deleteTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "202": {"$ref": "#/components/responses/JsonOk"}, "404": {"$ref": "#/components/responses/NotFound"}}}
},
"/api/v1/torrents/{hash}/start": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "startTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/resume": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "resumeTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/stop": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "stopTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/pause": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "pauseTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/recheck": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "recheckTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"202": {"$ref": "#/components/responses/JsonOk"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/reannounce": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "reannounceTorrent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/category": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "put": {"operationId": "setTorrentCategory", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/SetTorrentCategory"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
"/api/v1/torrents/{hash}/limits": {
"parameters": [{"$ref": "#/components/parameters/Hash"}],
"get": {"operationId": "getTorrentLimits", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "404": {"$ref": "#/components/responses/NotFound"}}},
"put": {"operationId": "updateTorrentLimits", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "501": {"$ref": "#/components/responses/JsonError"}}}
},
"/api/v1/torrents/{hash}/peers": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "post": {"operationId": "addTorrentPeers", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/torrents/queue": {"post": {"operationId": "updateTorrentQueue", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}}}},
"/api/v1/torrents/{hash}/tags": {
"parameters": [{"$ref": "#/components/parameters/Hash"}],
"post": {"operationId": "addTorrentTags", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/TorrentTags"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}},
"patch": {"operationId": "patchTorrentTags", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/PatchTorrentTags"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "404": {"$ref": "#/components/responses/NotFound"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}},
"delete": {"operationId": "removeTorrentTags", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/TorrentTags"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "404": {"$ref": "#/components/responses/NotFound"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}}
},
"/api/v1/torrents/{hash}/files": {
"parameters": [{"$ref": "#/components/parameters/Hash"}],
"get": {"operationId": "listTorrentFiles", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"patch": {"operationId": "patchTorrentFiles", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}}}
},
"/api/v1/torrents/{hash}/trackers": {
"parameters": [{"$ref": "#/components/parameters/Hash"}],
"get": {"operationId": "listTorrentTrackers", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"patch": {"operationId": "patchTorrentTrackers", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}}}
},
"/api/v1/torrents/{hash}/diagnostics": {"parameters": [{"$ref": "#/components/parameters/Hash"}], "get": {"operationId": "diagnoseTorrent", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/transfer/info": {"get": {"operationId": "transferInfo", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/transfer/limits": {
"get": {"operationId": "transferLimits", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"put": {"operationId": "updateTransferLimits", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}}}
},
"/api/v1/session/features": {
"get": {"operationId": "sessionFeatures", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"put": {"operationId": "updateSessionFeatures", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}}}
},
"/api/v1/session/settings": {
"get": {"operationId": "sessionSettings", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "503": {"$ref": "#/components/responses/JsonError"}}},
"patch": {"operationId": "updateSessionSettings", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}
},
"/api/v1/categories": {
"get": {"operationId": "listCategories", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"post": {"operationId": "upsertCategory", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/CategoryUpsert"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}}
},
"/api/v1/categories/{name}": {"parameters": [{"$ref": "#/components/parameters/Name"}], "delete": {"operationId": "deleteCategory", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/tags": {
"get": {"operationId": "listTags", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}},
"post": {"operationId": "createTag", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/TagCreate"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}}
},
"/api/v1/tags/{name}": {"parameters": [{"$ref": "#/components/parameters/Name"}], "delete": {"operationId": "deleteTag", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/bulk/{action}": {"parameters": [{"$ref": "#/components/parameters/Action"}], "post": {"operationId": "bulkAction", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/BulkAction"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "422": {"$ref": "#/components/responses/InvalidRequest"}}}},
"/api/v1/cross-seed": {"post": {"operationId": "crossSeed", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/tracker-health": {"get": {"operationId": "trackerHealth", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/sidebar-facets": {"get": {"operationId": "sidebarFacets", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/logs": {"get": {"operationId": "logs", "parameters": [{"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/LastKnownId"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/saved-views": {"get": {"operationId": "listSavedViews", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "post": {"operationId": "upsertSavedView", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/saved-views/{id}": {"parameters": [{"$ref": "#/components/parameters/Id"}], "delete": {"operationId": "deleteSavedView", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/ratio-groups": {"get": {"operationId": "listRatioGroups", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "post": {"operationId": "upsertRatioGroup", "description": "The TorrentNG daemon stores at most 4,096 entries and 1 MiB of serialized JSON. Native IDs, names, and category filters are limited to 256 UTF-8 bytes; tracker filters to 8,192 bytes. Invalid shapes or oversized fields return 400, count capacity returns 429, and aggregate overflow returns 413 without replacing stored state.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"description": "Invalid ratio group fields."}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "429": {"description": "Ratio group capacity reached."}}}},
"/api/v1/ratio-groups/{id}": {"parameters": [{"$ref": "#/components/parameters/Id"}], "post": {"operationId": "runRatioGroup", "description": "Applies to at most 10,000 matching torrents; larger matches return 413 before mutation. Over-limit stored native rules fail closed with 400. The native daemon response contains at most 32 samples per result array with full totals and errors truncated to 512 UTF-8 bytes. Returns 501 when the selected backend does not support share limits.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/NativeWorkflowResult"}, "400": {"description": "Invalid or oversized stored ratio group."}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "501": {"description": "Selected backend does not support share limits."}, "503": {"$ref": "#/components/responses/JsonError"}}}, "delete": {"operationId": "deleteRatioGroup", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/workflows": {"get": {"operationId": "listWorkflows", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "post": {"operationId": "upsertWorkflow", "description": "The category field filters matching torrents; target_category is the destination for set_category actions. Category-only legacy rules migrate their category to target_category, and set_category requires a non-empty destination. Native IDs, names, and category fields are limited to 256 UTF-8 bytes; event/action to 64; tracker/filter/command/URL text to 8,192; and paths to 4,096. The daemon stores at most 4,096 entries and 1 MiB serialized. Invalid shapes or oversized fields return 400, count capacity returns 429, and aggregate overflow returns 413 without replacing stored state.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"description": "Invalid workflow fields or an unsupported legacy rule."}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "429": {"description": "Workflow rule capacity reached."}}}},
"/api/v1/workflows/{id}": {"parameters": [{"$ref": "#/components/parameters/Id"}], "post": {"operationId": "runWorkflow", "description": "Runs a rule over at most 10,000 matching torrents; larger matches return 413 before actions. The native response contains at most 32 samples per result array with full totals and errors truncated to 512 UTF-8 bytes. Invalid oversized or incomplete legacy rules fail closed with 400.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/NativeWorkflowResult"}, "400": {"description": "Invalid or oversized stored workflow rule."}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "503": {"$ref": "#/components/responses/JsonError"}}}, "delete": {"operationId": "deleteWorkflow", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/workflow-runs": {"get": {"operationId": "listWorkflowRuns", "description": "Native history retains at most 200 records and 1 MiB serialized, evicting oldest records as needed. Each result array has at most 32 samples, full totals, and errors capped at 512 UTF-8 bytes.", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/rss-rules": {"get": {"operationId": "listRssRules", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "post": {"operationId": "upsertRssRule", "description": "Native RSS rules limit IDs, names, and categories to 256 UTF-8 bytes; rule text/feed URLs to 8,192; save paths to 4,096; and tags to at most 1,024 values of 256 bytes each. The daemon stores at most 4,096 entries and 1 MiB serialized. Invalid shapes or oversized fields return 400, count capacity returns 429, and aggregate overflow returns 413 without replacing stored state.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"description": "Invalid RSS rule fields."}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "429": {"description": "RSS rule capacity reached."}}}},
"/api/v1/rss-rules/test": {"post": {"operationId": "testRssRules", "description": "Title and optional link are each limited to 8,192 UTF-8 bytes during JSON deserialization. Empty titles return 400; invalid oversized legacy rules fail closed with 503.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"description": "Title must not be empty."}, "422": {"$ref": "#/components/responses/InvalidRequest"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/rss-rules/apply": {"post": {"operationId": "applyRssRules", "description": "Title and optional link are each limited to 8,192 UTF-8 bytes during JSON deserialization. Empty titles return 400. No matching rules complete as a no-op without requiring a link or live client. The native response has at most 32 matched rule-name, applied, and error samples with full totals and 512-byte error samples; non-dry runs are recorded in workflow history. Invalid oversized legacy rules fail closed with 503.", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/NativeWorkflowResult"}, "400": {"description": "Title must not be empty."}, "422": {"$ref": "#/components/responses/InvalidRequest"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/rss-rules/{id}": {"parameters": [{"$ref": "#/components/parameters/Id"}], "delete": {"operationId": "deleteRssRule", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/engine": {"get": {"operationId": "engineDiagnostics", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/engine/commands": {"get": {"operationId": "engineCommands", "responses": {"501": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/engine/rtorrent-settings": {"get": {"operationId": "getRtorrentSettings", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "put": {"operationId": "saveRtorrentSettings", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "501": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/engine/restart": {"post": {"operationId": "restartEngine", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"501": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/engine/user-agent": {"get": {"operationId": "getEngineUserAgent", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "put": {"operationId": "setEngineUserAgent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/settings/user-agent": {"get": {"operationId": "getUserAgent", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}, "put": {"operationId": "setUserAgent", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"204": {"$ref": "#/components/responses/Empty"}, "400": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/settings/crash-safety/path": {"get": {"operationId": "describeCrashSafetyPath", "parameters": [{"name": "path", "in": "query", "required": true, "description": "Absolute directory to inspect (at most 4096 bytes); it need not exist", "schema": {"type": "string", "minLength": 1, "maxLength": 4096}}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/settings/crash-safety": {"get": {"operationId": "getCrashSafety", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "503": {"$ref": "#/components/responses/JsonError"}}}, "put": {"operationId": "putCrashSafety", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "503": {"$ref": "#/components/responses/JsonError"}}}, "delete": {"operationId": "resetCrashSafety", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "503": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/events": {"get": {"operationId": "streamEvents", "parameters": [{"$ref": "#/components/parameters/LastKnownRevision"}], "responses": {"200": {"description": "Bounded server-sent event stream", "content": {"text/event-stream": {"schema": {"type": "string"}}}}}}},
"/api/v1/session-events": {"get": {"operationId": "listSessionEvents", "parameters": [{"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/LastKnownId"}], "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/jobs": {"get": {"operationId": "listJobs", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/jobs/{id}/pause": {"parameters": [{"$ref": "#/components/parameters/Id"}], "post": {"operationId": "pauseJob", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}}}},
"/api/v1/jobs/{id}/resume": {"parameters": [{"$ref": "#/components/parameters/Id"}], "post": {"operationId": "resumeJob", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}}}},
"/api/v1/jobs/{id}/cancel": {"parameters": [{"$ref": "#/components/parameters/Id"}], "post": {"operationId": "cancelJob", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "responses": {"204": {"$ref": "#/components/responses/Empty"}}}},
"/api/v1/storage": {"get": {"operationId": "storage", "responses": {"200": {"$ref": "#/components/responses/JsonOk"}}}},
"/api/v1/storage/plan": {"post": {"operationId": "previewStoragePlan", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"200": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}}}},
"/api/v1/storage/execute": {"post": {"operationId": "executeStoragePlan", "parameters": [{"$ref": "#/components/parameters/IdempotencyKey"}], "requestBody": {"$ref": "#/components/requestBodies/JsonObject"}, "responses": {"202": {"$ref": "#/components/responses/JsonOk"}, "400": {"$ref": "#/components/responses/JsonError"}, "409": {"$ref": "#/components/responses/JsonError"}}}}
},
"components": {
"securitySchemes": {
"bearerAuth": {"type": "http", "scheme": "bearer"},
"sessionCookie": {"type": "apiKey", "in": "cookie", "name": "tng_session"}
},
"parameters": {
"Hash": {"name": "hash", "in": "path", "required": true, "schema": {"type": "string", "minLength": 40, "maxLength": 64}},
"Name": {"name": "name", "in": "path", "required": true, "description": "Maximum 256 UTF-8 bytes.", "schema": {"type": "string", "minLength": 1, "x-maxUtf8Bytes": 256}},
"Id": {"name": "id", "in": "path", "required": true, "schema": {"type": "string", "minLength": 1}},
"Action": {"name": "action", "in": "path", "required": true, "schema": {"type": "string", "minLength": 1}},
"Limit": {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "maximum": 5000}},
"Offset": {"name": "offset", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 0}},
"Snapshot": {"name": "snapshot", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 0}},
"Filter": {"name": "filter", "in": "query", "required": false, "schema": {"type": "string"}},
"LastKnownId": {"name": "last_known_id", "in": "query", "required": false, "schema": {"type": "integer"}},
"LastKnownRevision": {"name": "last_known_revision", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 0}},
"IdempotencyKey": {"name": "Idempotency-Key", "in": "header", "required": false, "description": "Printable ASCII key, max 128 bytes. Successful responses are replayable for the retention window; reuse with a different request is rejected.", "schema": {"type": "string", "minLength": 1, "maxLength": 128}}
},
"requestBodies": {
"AuthLoginForm": {"required": true, "description": "Supply configured username/password or an API token in either field.", "content": {"application/x-www-form-urlencoded": {"schema": {"type": "object", "properties": {"username": {"type": "string"}, "password": {"type": "string", "format": "password"}}}}}},
"UpdateAuthSettings": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateAuthSettings"}}}},
"JsonObject": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JsonObject"}}}},
"CategoryUpsert": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CategoryUpsert"}}}},
"TagCreate": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TagCreate"}}}},
"SetTorrentCategory": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SetTorrentCategory"}}}},
"TorrentTags": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TorrentTags"}}}},
"PatchTorrentTags": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PatchTorrentTags"}}}},
"BulkAction": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkActionRequest"}}}},
"AddTorrent": {"required": true, "description": "The native daemon accepts either JSON or multipart form data. Exactly one torrent source must be supplied.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AddTorrentRequest"}}, "multipart/form-data": {"schema": {"$ref": "#/components/schemas/AddTorrentMultipartRequest"}}}}
},
"responses": {
"JsonOk": {"description": "JSON response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JsonValue"}}}},
"NativeWorkflowResult": {"description": "Native execution response with bounded samples and full totals", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NativeWorkflowResult"}}}},
"JsonError": {"description": "Structured API error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
"InvalidRequest": {"description": "Malformed JSON or field/list values exceed bounded request limits"},
"Unauthorized": {"description": "Missing or invalid API token"},
"NotFound": {"description": "Torrent, job, or named resource was not found"},
"PayloadTooLarge": {"description": "Request or resulting persisted state exceeds a configured size limit"},
"Empty": {"description": "Mutation accepted with no response body"}
},
"schemas": {
"JsonValue": {},
"JsonObject": {"type": "object", "additionalProperties": true},
"AuthSettings": {"type": "object", "required": ["username", "api_token_login_enabled"], "properties": {"username": {"type": "string"}, "api_token_login_enabled": {"type": "boolean"}}, "additionalProperties": false},
"UpdateAuthSettings": {"type": "object", "required": ["username", "password"], "properties": {"username": {"type": "string", "minLength": 1, "maxLength": 256}, "password": {"type": "string", "minLength": 8, "maxLength": 1024}}, "additionalProperties": false},
"CategoryUpsert": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string", "minLength": 1, "x-maxUtf8Bytes": 256}, "save_path": {"type": ["string", "null"], "x-maxUtf8Bytes": 4096}}, "additionalProperties": true},
"TagCreate": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string", "minLength": 1, "x-maxUtf8Bytes": 256}}, "additionalProperties": true},
"SetTorrentCategory": {"type": "object", "properties": {"category": {"type": ["string", "null"], "x-maxUtf8Bytes": 256}}, "additionalProperties": true},
"TorrentTags": {"type": "object", "required": ["tags"], "properties": {"tags": {"type": "array", "maxItems": 1024, "items": {"type": "string", "x-maxUtf8Bytes": 256}}}, "additionalProperties": true},
"PatchTorrentTags": {"type": "object", "properties": {"add": {"type": "array", "maxItems": 1024, "items": {"type": "string", "x-maxUtf8Bytes": 256}}, "remove": {"type": "array", "maxItems": 1024, "items": {"type": "string", "x-maxUtf8Bytes": 256}}}, "x-maxCombinedItems": 1024, "additionalProperties": true},
"BulkActionRequest": {"type": "object", "required": ["hashes"], "properties": {"hashes": {"type": "array", "maxItems": 16384, "items": {"type": "string", "maxLength": 256}}, "dry_run": {"type": "boolean", "default": false}, "category": {"type": "string", "x-maxUtf8Bytes": 256, "description": "An empty string clears the category."}, "save_path": {"type": "string", "minLength": 1, "maxLength": 4096}, "tags": {"type": ["array", "null"], "maxItems": 1024, "items": {"type": "string", "x-maxUtf8Bytes": 256}}}, "additionalProperties": true},
"AddTorrentRequest": {"type": "object", "required": ["save_path"], "properties": {"torrent_b64": {"type": ["string", "null"], "minLength": 1, "description": "Base64-encoded payload, limited to 64 MiB after decoding."}, "magnet": {"type": ["string", "null"], "minLength": 1, "x-maxUtf8Bytes": 8192}, "save_path": {"type": "string", "x-maxUtf8Bytes": 4096}, "category": {"type": ["string", "null"], "x-maxUtf8Bytes": 256}, "tags": {"type": ["array", "null"], "maxItems": 1024, "items": {"type": "string", "x-maxUtf8Bytes": 256}}, "start": {"type": ["boolean", "null"]}}, "anyOf": [{"required": ["magnet"], "properties": {"magnet": {"type": "string", "minLength": 1}}}, {"required": ["torrent_b64"], "properties": {"torrent_b64": {"type": "string", "minLength": 1}}}], "not": {"required": ["magnet", "torrent_b64"], "properties": {"magnet": {"type": "string"}, "torrent_b64": {"type": "string"}}}, "additionalProperties": true},
"AddTorrentMultipartRequest": {"type": "object", "properties": {"magnet": {"type": "string", "minLength": 1, "x-maxUtf8Bytes": 8192}, "torrent": {"type": "string", "format": "binary", "description": "Maximum payload is 64 MiB."}, "save_path": {"type": "string", "x-maxUtf8Bytes": 4096}, "category": {"type": "string", "x-maxUtf8Bytes": 256}, "start": {"type": "string", "enum": ["true", "false"], "default": "true"}}, "oneOf": [{"required": ["magnet"], "not": {"required": ["torrent"]}}, {"required": ["torrent"], "not": {"required": ["magnet"]}}], "additionalProperties": false},
"NativeWorkflowResult": {"type": "object", "required": ["matched", "matched_total", "applied", "applied_total", "errors", "errors_total", "dry_run"], "properties": {"matched": {"type": "array", "maxItems": 32, "items": {"type": "string", "x-maxUtf8Bytes": 256}}, "matched_total": {"type": "integer", "minimum": 0}, "applied": {"type": "array", "maxItems": 32, "items": {"type": "string", "x-maxUtf8Bytes": 256}}, "applied_total": {"type": "integer", "minimum": 0}, "errors": {"type": "array", "maxItems": 32, "items": {"type": "string", "x-maxUtf8Bytes": 512}}, "errors_total": {"type": "integer", "minimum": 0}, "dry_run": {"type": "boolean"}}, "additionalProperties": false},
"Error": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}}, "required": ["code", "message"], "additionalProperties": true}
}
}
}