RPC Protocol
The JSON-RPC interface used by the CLI and external clients.
Risuko exposes a JSON-RPC 2.0 server over HTTP. The CLI uses this interface, and you can also build custom clients.
Connection
The RPC server listens on http://127.0.0.1:16800/jsonrpc by default. Host, port, and secret come from the rpc-host, rpc-listen-port, and rpc-secret config keys.
Besides POST, the same endpoint accepts GET /jsonrpc?method=<name>&id=<id>¶ms=<base64(JSON array)>. An optional jsoncallback query parameter wraps the response in JSONP. A GET with an Upgrade: websocket header opens a WebSocket instead (see below).
Request Format
{
"jsonrpc": "2.0",
"id": "1",
"method": "risuko.addUri",
"params": [
["https://example.com/file.zip"],
{ "split": "16", "dir": "/downloads" }
]
}params must be a positional array; named (object) params are rejected with -32602. The body may also be a batch array of request objects.
Response Format
{
"jsonrpc": "2.0",
"id": "1",
"result": "a1b2c3d4e5f6"
}Available Methods
Task Management
| Method | Parameters | Returns |
|---|---|---|
risuko.addUri | [uris[], options?] | GID string |
risuko.addTorrent | [base64Data, uris[], options?] | GID string |
risuko.addMetalink | [base64MetalinkData, options?] | GID string |
risuko.addNzb | [base64NzbData, options?] | GID string |
risuko.addEd2k | [uri, options?] | GID string |
risuko.addMedia | [url, options?] | GID string |
risuko.pause | [gid] | GID string |
risuko.unpause | [gid] | GID string |
risuko.remove | [gid] | GID string |
risuko.forcePause | [gid] | GID string |
risuko.forceRemove | [gid] | GID string |
risuko.pauseAll | — | "OK" |
risuko.unpauseAll | — | "OK" |
risuko.forcePauseAll | — | "OK" |
risuko.changePosition | [gid, pos?, how?] | New position |
risuko.updateTask | [gid, patch] | { restarted, trackersAdded, progressPreserved } |
risuko.addMedia accepts URLs from supported media sites (downloaded via yt-dlp). Other URLs are rejected with "Not a supported media URL" unless the force-ytdlp option is set. Methods that take a gid also accept a unique GID prefix of at least 4 characters.
risuko.addMetalink accepts a standard-base64 Metalink document (.meta4 / .metalink). risuko.updateTask applies a { uris, dir, out, trackers, options } patch; see updateTask.
risuko.addNzb accepts a standard-base64 NZB document, not a URL. It creates
one Usenet task from the parsed manifest. The options object may select a
non-secret provider reference or cleanup policy, but it must not contain
provider credentials or archive passwords. Configure those in the desktop
app's Provider Profiles editor instead.
{
"jsonrpc": "2.0",
"id": "nzb-1",
"method": "risuko.addNzb",
"params": [
"PD94bWwgdmVyc2lvbj0iMS4wIj8+Li4u",
{
"dir": "/downloads",
"usenet-profile-id": "primary",
"usenet-cleanup-mode": "keep-all"
}
]
}Queries
| Method | Parameters | Returns |
|---|---|---|
risuko.tellStatus | [gid, keys?] | Status object |
risuko.tellActive | [keys?] | Status object array |
risuko.tellWaiting | [offset?, num?, keys?] | Status object array |
risuko.tellStopped | [offset?, num?, keys?] | Status object array |
risuko.getGlobalStat | — | Stat object |
risuko.getFiles | [gid] | File array |
risuko.getPeers | [gid] | Peer array |
risuko.setBtPeerBlocklist | [entries[]] | { revision, ruleCount, disconnectedPeers, removedPeers } |
risuko.getUris | [gid] | URI array |
risuko.getServers | [gid] | Server array |
risuko.getVersion | — | Version object |
risuko.getSessionInfo | — | Session info object |
risuko.tellWaiting returns waiting and paused tasks. Scheduled tasks are a
desktop/Tauri list (tell_scheduled), not a JSON-RPC method. risuko.getGlobalStat
does count scheduled tasks in numWaiting, matching aria2's broad
"not active yet" bucket.
risuko.setBtPeerBlocklist full-replaces the process-wide BitTorrent IP/CIDR
blocklist. Each string is a plain IP (1.2.3.4, 2001:db8::1) or CIDR
(10.0.0.0/8, 2001:db8::/32); invalid entries are ignored. Connected peers
that match are disconnected and dropped from the swarm. PeerBanHelper drives
this method through the Aria2Next-compat listener (see below).
Options
| Method | Parameters | Returns |
|---|---|---|
risuko.getOption | [gid] | Options object |
risuko.getGlobalOption | — | Options object |
risuko.changeOption | [gid, options] | "OK" |
risuko.changeGlobalOption | [options] | "OK" |
Session
| Method | Parameters | Returns |
|---|---|---|
risuko.saveSession | — | "OK" |
risuko.purgeDownloadResult | — | "OK" |
risuko.removeDownloadResult | [gid] | "OK" |
risuko.shutdown | — | "OK" |
risuko.forceShutdown | — | "OK" |
shutdown saves the session before stopping the engine; forceShutdown skips the save.
Task Routing
Pattern-based rules that override the download directory and assign a tag based on the inferred output filename. See the Task Routing guide.
| Method | Parameters | Returns |
|---|---|---|
risuko.listRoutingRules | — | Rule array |
risuko.addRoutingRule | [rule] | The rule, with id filled in if omitted |
risuko.updateRoutingRule | [rule] | "OK" |
risuko.removeRoutingRule | [ruleId] | "OK" |
risuko.resolveRouting | [filename] | { tag, dir } decision preview against the current rules |
A rule has the shape:
{
"id": "rule-videos",
"label": "Videos",
"pattern": "*.mkv",
"dir": "/downloads/videos",
"enabled": true
}pattern is a case-insensitive glob (glob crate syntax) matched against
the inferred filename only — not the URL or directory.
Example: curl
# Add a download
curl -X POST http://localhost:16800/jsonrpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "risuko.addUri",
"params": [["https://example.com/file.zip"], {"split": "16"}]
}'
# Check status
curl -X POST http://localhost:16800/jsonrpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "2",
"method": "risuko.tellActive",
"params": []
}'Error Responses
{
"jsonrpc": "2.0",
"id": "1",
"error": {
"code": 1,
"message": "Task a1b2c3d4 not found"
}
}Protocol errors use the standard JSON-RPC codes: -32700 (parse error), -32600 (invalid request), -32601 (method not found), -32602 (invalid params). Application errors — including failed authentication — use code 1.
aria2 Compatibility
The RPC server accepts both risuko.* and aria2.* method prefixes. For example, aria2.addUri is treated as risuko.addUri. This makes it compatible with existing aria2 RPC clients. system.listMethods returns every method under both prefixes.
PeerBanHelper / Aria2Next listener
When pbh-enable is true, the engine starts a second JSON-RPC server on
pbh-listen-port (default 16801), bound to the same rpc-host as the
primary RPC. That listener uses Aria2Next compatibility mode:
GET/POST/is accepted in addition to/jsonrpc(PeerBanHelper posts to the root)aria2.getVersionreports{ version: "1.37.0", product: "aria2-next", rpcVersion: "1", enabledFeatures: [...] }instead of the Risuko engine versionaria2.getPeersincludes the extra Aria2Next fields listed in getPeersaria2.setBtPeerBlocklistapplies the IP/CIDR blocklist described above
In PeerBanHelper, add an Aria2Next downloader pointed at
http://127.0.0.1:16801/jsonrpc (or the configured port) and set the RPC token
to pbh-rpc-secret. These keys are startup-only.
Authentication
When rpc-secret is set, every call must prefix its params array with "token:<secret>":
{
"jsonrpc": "2.0",
"id": "1",
"method": "risuko.addUri",
"params": ["token:my-secret", ["https://example.com/file.zip"]]
}The token is stripped from params before dispatch. When rpc-secret is empty, the token: prefix is still accepted (and stripped) for compatibility with aria2 clients that always send one.
system.multicall
Batch any number of calls into a single round-trip. Per aria2 convention, the outer params array is not authenticated; each nested call is authenticated independently and must carry its own "token:<secret>" prefix when rpc-secret is set.
{
"jsonrpc": "2.0",
"id": "1",
"method": "system.multicall",
"params": [[
{ "methodName": "risuko.tellActive", "params": ["token:my-secret"] },
{ "methodName": "risuko.getGlobalStat", "params": ["token:my-secret"] }
]]
}Returns an array where each element is either [result] (success) or { "code", "message" } (per-call error). The legacy ["token:...", [calls]] shape is also accepted, but the outer token is never trusted as authentication.
WebSocket Subscribe
The server upgrades GET /jsonrpc requests with a Connection: Upgrade / Upgrade: websocket header to a WebSocket. Once connected, the engine streams JSON-RPC notifications for every task transition: risuko.onDownloadStart, risuko.onDownloadPause, risuko.onDownloadStop, risuko.onDownloadComplete, risuko.onDownloadError, risuko.onBtDownloadComplete. Pushed notifications always use the risuko. prefix, even though system.listNotifications lists each name under both prefixes. Each notification carries params: [{"gid": "<gid>"}] and no id. Regular request/response calls also work over the same socket.