API
This document describes the REST API and WebSocket protocol used by aMuTorrent.
Table of Contents
Section titled “Table of Contents”- Authentication
- REST API v1 — General-purpose API for downloads, categories, search, logs
- Metrics API
- History API
- Torznab API — Exposes aMule ED2K search as a Torznab indexer for Sonarr/Radarr
- qBittorrent-Compatible API — Exposes aMule as a qBittorrent-compatible download client for Sonarr/Radarr
- WebSocket Protocol
Authentication
Section titled “Authentication”When web UI authentication is enabled, the following authentication methods apply:
Web UI & Internal APIs
Section titled “Web UI & Internal APIs”The web interface and internal APIs use session-based authentication. Users must log in through the web interface to obtain a session cookie, or provide an API key via the X-API-Key header.
Session login:
curl -c cookies.txt -X POST http://host:4000/api/auth/login \ -H 'Content-Type: application/json' \ -d '{"username":"admin","password":"yourpass"}'
# Use the cookie in subsequent requestscurl -b cookies.txt http://host:4000/api/v1/categoriesAPI key:
curl -H 'X-API-Key: your-api-key' http://host:4000/api/v1/categoriesAPI keys are per-user and can be found/regenerated in Settings → User Management.
Protected endpoints:
/api/v1/*- REST API v1 (capability-gated per endpoint)/api/metrics/*- Metrics API/api/history/*- History API/api/config/*- Configuration API
WebSocket
Section titled “WebSocket”WebSocket connections are also protected when authentication is enabled. The WebSocket upgrade request must include a valid session cookie (amule.sid) from an authenticated web session.
Torznab API (for Sonarr/Radarr)
Section titled “Torznab API (for Sonarr/Radarr)”The Torznab indexer API uses API key authentication (admin-only).
- API Key: Use your admin user’s API key (found in Settings → User Management)
- Pass the key via the
apikeyquery parameter
Example:
GET /indexer/amule/api?t=search&q=test&apikey=YOUR_API_KEYWhen configuring in Sonarr/Radarr, enter your admin API key in the “API Key” field.
qBittorrent-Compatible API (for Sonarr/Radarr)
Section titled “qBittorrent-Compatible API (for Sonarr/Radarr)”The qBittorrent-compatible API uses HTTP Basic Authentication (admin-only). Two credential methods are supported:
- Username + password — use your aMuTorrent admin username and password
- API key as password — use any username with your admin API key as the password
When configuring the download client in Sonarr/Radarr:
- Username: Your admin username (or any value when using API key)
- Password: Your admin password or API key
REST API v1
Section titled “REST API v1”General-purpose REST API for managing downloads, categories, search, and more. All endpoints are under /api/v1/.
Authentication
Section titled “Authentication”All /api/v1/ endpoints require authentication when auth is enabled. Two methods are supported:
- Session cookie — Log in via
POST /api/auth/loginand include the session cookie in subsequent requests - API key — Pass the
X-API-Keyheader with a user’s API key (found in Settings → User Management)
Each endpoint requires specific capabilities (permissions). Admin users have all capabilities. Non-admin users need the listed capability assigned to their account.
Response Format
Section titled “Response Format”All responses are JSON objects with a type field indicating the response type. On error, the response has type: "error" with a message field.
Data Endpoints
Section titled “Data Endpoints”GET /api/v1/data/snapshot
Section titled “GET /api/v1/data/snapshot”Returns the current state of all downloads, shared files, and statistics. This is the same data the WebSocket sends on connection.
Capabilities: None (any authenticated user)
Response:
{ "type": "batch-update", "data": { "stats": { "instanceSpeeds": { "amule-host-4712": { "uploadSpeed": 1024, "downloadSpeed": 0 } }, "instances": { "amule-host-4712": { "type": "amule", "connected": true, "name": "aMule" } } }, "items": [ { "hash": "abc123...", "name": "file.mkv", "client": "amule", "instanceId": "amule-host-4712", "status": "active", "progress": 45.2, "size": 1073741824, "downloadSpeed": 512000, "uploadSpeed": 0 } ] }}Download Management
Section titled “Download Management”POST /api/v1/downloads/magnets
Section titled “POST /api/v1/downloads/magnets”Add magnet links to a BitTorrent client.
Capabilities: add_downloads
Request Body:
{ "links": ["magnet:?xt=urn:btih:..."], "instanceId": "rtorrent-host-8000", "categoryName": "Default"}Response:
{ "type": "magnet-added", "results": [{ "link": "magnet:?...", "success": true }], "clientId": "rtorrent"}POST /api/v1/downloads/ed2k
Section titled “POST /api/v1/downloads/ed2k”Add ED2K links to an aMule instance.
Capabilities: add_downloads
Request Body:
{ "links": ["ed2k://|file|name|size|hash|/"], "instanceId": "amule-host-4712", "categoryName": "Default"}Response:
{ "type": "ed2k-added", "results": [{ "link": "ed2k://...", "success": true }]}POST /api/v1/downloads/torrent
Section titled “POST /api/v1/downloads/torrent”Add a torrent file (base64-encoded in JSON body).
Capabilities: add_downloads
Request Body:
{ "data": "base64-encoded-torrent-data", "fileName": "file.torrent", "instanceId": "rtorrent-host-8000", "categoryName": "Default"}POST /api/v1/downloads/search-results
Section titled “POST /api/v1/downloads/search-results”Download files from an ED2K search result (aMule).
Capabilities: add_downloads
Request Body:
{ "fileHashes": ["abc123...", "def456..."], "instanceId": "amule-host-4712", "categoryName": "Default"}Response:
{ "type": "batch-download-complete", "results": [{ "fileHash": "abc123...", "success": true }], "message": "Downloaded 2/2 files"}Download Control
Section titled “Download Control”All control endpoints accept an items array with fileHash and instanceId per item.
POST /api/v1/downloads/pause
Section titled “POST /api/v1/downloads/pause”Capabilities: pause_resume
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }]}Response:
{ "type": "batch-pause-complete", "results": [{ "fileHash": "abc123...", "success": true, "instanceId": "rtorrent-host-8000" }], "message": "1/1 successful"}POST /api/v1/downloads/resume
Section titled “POST /api/v1/downloads/resume”Capabilities: pause_resume
Same request/response format as pause.
POST /api/v1/downloads/stop
Section titled “POST /api/v1/downloads/stop”Capabilities: pause_resume
Same request/response format as pause. Fully closes the torrent (releases file handles).
POST /api/v1/downloads/delete
Section titled “POST /api/v1/downloads/delete”Capabilities: remove_downloads
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000", "fileName": "file.mkv" }], "deleteFiles": false}Response:
{ "type": "batch-delete-complete", "results": [{ "fileHash": "abc123...", "success": true, "instanceId": "rtorrent-host-8000" }], "message": "Deleted 1/1 files"}POST /api/v1/downloads/move
Section titled “POST /api/v1/downloads/move”Move files to a destination path without changing category.
Capabilities: edit_downloads
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }], "destPath": "/downloads/movies"}POST /api/v1/downloads/category
Section titled “POST /api/v1/downloads/category”Change the category/label of downloads.
Capabilities: assign_categories
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }], "categoryName": "Movies", "moveFiles": true}POST /api/v1/downloads/rename
Section titled “POST /api/v1/downloads/rename”Rename a file.
Capabilities: rename_files
Request Body:
{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000", "newName": "new-name.mkv"}POST /api/v1/downloads/rating-comment
Section titled “POST /api/v1/downloads/rating-comment”Set the rating and comment on a shared file. Currently supported only by aMule
shared (completed) files — use the client capability fileRatingComment in
/api/v1/clients/instances to detect support.
aMule’s EC handler writes both fields together; omitting one clears it. To
preserve an existing value, pass it through unchanged. rating uses the
scale: 0 = Not rated, 1 = Fake, 2 = Poor, 3 = Fair, 4 = Good,
5 = Excellent.
Capabilities: set_comment
Request Body:
{ "fileHash": "abc123...", "instanceId": "amule-host-4712", "comment": "High-quality rip", "rating": 4}Permission Checks
Section titled “Permission Checks”Pre-flight checks to verify paths are accessible before performing operations.
POST /api/v1/permissions/delete
Section titled “POST /api/v1/permissions/delete”Capabilities: remove_downloads
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }]}Response:
{ "type": "delete-permissions", "results": [{ "fileHash": "abc123...", "canDelete": true, "path": "/downloads/file.mkv" }], "isDocker": true}POST /api/v1/permissions/move
Section titled “POST /api/v1/permissions/move”Check permissions for category-based move.
Capabilities: move_files
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }], "categoryName": "Movies"}POST /api/v1/permissions/move-to
Section titled “POST /api/v1/permissions/move-to”Check permissions for direct path move.
Capabilities: edit_downloads
Request Body:
{ "items": [{ "fileHash": "abc123...", "instanceId": "rtorrent-host-8000" }], "destPath": "/downloads/movies"}Response:
{ "type": "move-to-permissions", "results": [{ "fileHash": "abc123...", "canMove": true, "reason": "ok" }], "canMove": true, "destPath": "/downloads/movies"}Categories
Section titled “Categories”GET /api/v1/categories
Section titled “GET /api/v1/categories”List all categories.
Capabilities: None (any authenticated user)
Response:
{ "type": "categories-update", "data": [ { "name": "Default", "title": "Default", "path": "", "color": 13421772, "comment": "", "priority": 0 } ]}POST /api/v1/categories
Section titled “POST /api/v1/categories”Create a new category.
Capabilities: manage_categories
Request Body:
{ "title": "Movies", "path": "/downloads/movies", "comment": "Movie downloads", "color": 255, "priority": 0}PUT /api/v1/categories
Section titled “PUT /api/v1/categories”Update an existing category.
Capabilities: manage_categories
Request Body:
{ "name": "Movies", "path": "/downloads/movies-updated", "comment": "Updated path"}DELETE /api/v1/categories
Section titled “DELETE /api/v1/categories”Delete a category.
Capabilities: manage_categories
Request Body:
{ "name": "Movies"}Search (ED2K)
Section titled “Search (ED2K)”POST /api/v1/search
Section titled “POST /api/v1/search”Start an ED2K search. By default this is a blocking call that waits for aMule to return results (up to 120 seconds). Set wait: false for non-blocking mode.
Capabilities: search
Request Body:
{ "query": "ubuntu", "type": "global", "instanceId": "amule-host-4712", "wait": true}| Field | Default | Description |
|---|---|---|
query | (required) | Search query string |
type | global | Search type: global, local, kad |
instanceId | (first aMule) | Target aMule instance ID |
wait | true | If true, blocks until results are ready (up to 120s). If false, returns immediately. |
Response (blocking, wait: true):
{ "type": "search-results", "data": [ { "fileName": "ubuntu-24.04.iso", "fileSize": 5120000000, "fileHash": "abc123...", "sourceCount": 42 } ]}Response (non-blocking, wait: false):
{ "type": "search-started", "message": "Search started. Poll GET /api/v1/search/results for results."}When using non-blocking mode, poll GET /api/v1/search/results to retrieve results once the search completes.
GET /api/v1/search/results
Section titled “GET /api/v1/search/results”Get cached results from the last search.
Capabilities: search
Query Parameters:
| Parameter | Description |
|---|---|
instanceId | aMule instance ID (optional — defaults to first connected) |
Response:
{ "type": "previous-search-results", "data": [...]}aMule Specific
Section titled “aMule Specific”GET /api/v1/amule/servers
Section titled “GET /api/v1/amule/servers”List ED2K servers.
Capabilities: view_servers
POST /api/v1/amule/servers/action
Section titled “POST /api/v1/amule/servers/action”Connect, disconnect, or remove an ED2K server.
Capabilities: view_servers
Request Body:
{ "action": "connect", "ip": "45.82.80.155", "port": 5687, "instanceId": "amule-host-4712"}Actions: connect, disconnect, remove
GET /api/v1/amule/server-info
Section titled “GET /api/v1/amule/server-info”Get ED2K server info (message of the day).
Capabilities: view_servers
GET /api/v1/amule/stats-tree
Section titled “GET /api/v1/amule/stats-tree”Get aMule statistics tree.
Capabilities: view_statistics
POST /api/v1/amule/refresh-shared
Section titled “POST /api/v1/amule/refresh-shared”Trigger a shared files rescan.
Capabilities: view_shared
Request Body:
{ "instanceId": "amule-host-4712"}Shared Directory Management (Experimental)
Section titled “Shared Directory Management (Experimental)”Admin-only endpoints for managing aMule’s shareddir.dat file.
GET /api/amule/shared-dirs?instanceId=...
Section titled “GET /api/amule/shared-dirs?instanceId=...”Read current shared directories. Returns config roots as authoritative, merges any dat-only roots.
Response (configured):
{ "configured": true, "path": "/home/amule/.aMule/shareddir.dat", "exists": true, "canWrite": true, "roots": ["/downloads/movies", "/downloads/tv"], "inaccessibleRoots": [], "isDocker": false}Response (unconfigured):
{ "configured": false, "path": null, "isDocker": false}PUT /api/amule/shared-dirs?instanceId=...
Section titled “PUT /api/amule/shared-dirs?instanceId=...”Save shared directories. Persists roots to config.json, auto-expands each root to include all subdirectories via find -type d, writes to shareddir.dat, and reloads aMule shared files.
Request Body:
{ "directories": ["/downloads/movies", "/downloads/tv"]}POST /api/amule/shared-dirs/reload?instanceId=...
Section titled “POST /api/amule/shared-dirs/reload?instanceId=...”Rescan subdirectories using roots from config and reload. Picks up new subdirectories without changing root dirs.
PUT /api/amule/shared-dirs/config?instanceId=...
Section titled “PUT /api/amule/shared-dirs/config?instanceId=...”Save the sharedDirDatPath for an aMule instance. Send an empty string to clear the configuration (removes both sharedDirDatPath and sharedDirRoots).
Request Body:
{ "sharedDirDatPath": "/home/amule/.aMule/shareddir.dat"}GET /api/v1/logs/app
Section titled “GET /api/v1/logs/app”Get aMuTorrent application log.
Capabilities: view_logs
GET /api/v1/logs/amule
Section titled “GET /api/v1/logs/amule”Get aMule log.
Capabilities: view_logs
GET /api/v1/logs/qbittorrent
Section titled “GET /api/v1/logs/qbittorrent”Get qBittorrent log.
Capabilities: view_logs
Instance Selection
Section titled “Instance Selection”Most endpoints accept an instanceId field to target a specific client instance. Instance IDs can be found in the snapshot response (data.stats.instances). If omitted, the server selects the first connected instance of the expected type.
Metrics API
Section titled “Metrics API”Historical metrics for speed and transfer data.
GET /api/metrics/speed-history
Section titled “GET /api/metrics/speed-history”Returns speed data with different granularities based on time range.
Query Parameters:
| Parameter | Values | Description |
|---|---|---|
range | 24h, 7d, 30d | Time range |
Granularity:
- 24h: 15-second buckets (~5,760 points)
- 7d: 15-minute buckets (672 points)
- 30d: 1-hour buckets (720 points)
Response:
{ "range": "24h", "data": [ { "timestamp": 1234567890000, "uploadSpeed": 102400, "downloadSpeed": 512000 } ]}GET /api/metrics/history
Section titled “GET /api/metrics/history”Returns data transferred with time buckets.
Query Parameters:
| Parameter | Values | Description |
|---|---|---|
range | 24h, 7d, 30d | Time range |
Granularity:
- 24h: 15-minute buckets (96 bars)
- 7d: 2-hour buckets (84 bars)
- 30d: 6-hour buckets (120 bars)
Response:
{ "range": "24h", "data": [ { "timestamp": 1234567890000, "uploadSpeed": 102400, "downloadSpeed": 512000, "uploadedDelta": 1024000, "downloadedDelta": 5120000 } ]}GET /api/metrics/stats
Section titled “GET /api/metrics/stats”Returns summary statistics for a time range.
Query Parameters:
| Parameter | Values | Description |
|---|---|---|
range | 24h, 7d, 30d | Time range |
Response:
{ "range": "24h", "totalUploaded": 10737418240, "totalDownloaded": 53687091200, "avgUploadSpeed": 124108, "avgDownloadSpeed": 620540, "peakUploadSpeed": 1048576, "peakDownloadSpeed": 5242880}History API
Section titled “History API”Download history tracking.
GET /api/history
Section titled “GET /api/history”Returns paginated download history.
Query Parameters:
| Parameter | Default | Description |
|---|---|---|
limit | 50 | Items per page |
offset | 0 | Pagination offset |
sortBy | started_at | Sort field |
sortDir | desc | Sort direction (asc/desc) |
search | - | Filter by filename |
status | - | Filter by status |
Response:
{ "entries": [ { "hash": "abc123...", "filename": "file.mkv", "size": 1073741824, "status": "completed", "started_at": "2024-01-15T10:00:00Z", "completed_at": "2024-01-15T12:00:00Z", "username": "user1" } ], "total": 150, "trackUsername": true}DELETE /api/history/:hash
Section titled “DELETE /api/history/:hash”Deletes a history entry by file hash.
Torznab API
Section titled “Torznab API”Exposes aMule’s ED2K search as a Torznab-compatible indexer, allowing Sonarr, Radarr, and other *arr apps to search the ED2K network directly. See authentication above.
GET /indexer/amule/api?t=caps
Section titled “GET /indexer/amule/api?t=caps”Returns indexer capabilities.
Response: XML with supported categories and search capabilities.
GET /indexer/amule/api?t=search
Section titled “GET /indexer/amule/api?t=search”Performs an ED2K search.
Query Parameters:
| Parameter | Description |
|---|---|
q | Search query |
cat | Category filter (optional) |
limit | Max results |
offset | Pagination offset |
Response: XML in Torznab format with search results.
qBittorrent-Compatible API
Section titled “qBittorrent-Compatible API”Exposes aMule as a qBittorrent-compatible download client, allowing Sonarr, Radarr, and other *arr apps to add ED2K downloads, monitor progress, and manage categories through aMule. See authentication above.
GET /api/v2/app/version
Section titled “GET /api/v2/app/version”Returns application version.
Response: v4.5.0
GET /api/v2/app/webapiVersion
Section titled “GET /api/v2/app/webapiVersion”Returns Web API version.
Response: 2.8.3
GET /api/v2/torrents/info
Section titled “GET /api/v2/torrents/info”Lists current downloads.
Query Parameters:
| Parameter | Description |
|---|---|
filter | Filter by status (all, downloading, completed, etc.) |
category | Filter by category |
hashes | Filter by specific hashes |
Response:
[ { "hash": "abc123...", "name": "file.mkv", "size": 1073741824, "progress": 0.75, "dlspeed": 512000, "upspeed": 102400, "state": "downloading", "category": "sonarr", "content_path": "/downloads/sonarr/file.mkv", "save_path": "/downloads/sonarr" }]POST /api/v2/torrents/add
Section titled “POST /api/v2/torrents/add”Adds a download from ED2K link.
Form Data:
| Field | Description |
|---|---|
urls | ED2K link(s), one per line |
category | Category name |
POST /api/v2/torrents/pause
Section titled “POST /api/v2/torrents/pause”Pauses download(s).
Form Data:
| Field | Description |
|---|---|
hashes | Hash(es) to pause, all for all |
POST /api/v2/torrents/resume
Section titled “POST /api/v2/torrents/resume”Resumes download(s).
Form Data:
| Field | Description |
|---|---|
hashes | Hash(es) to resume, all for all |
POST /api/v2/torrents/delete
Section titled “POST /api/v2/torrents/delete”Deletes download(s).
Form Data:
| Field | Description |
|---|---|
hashes | Hash(es) to delete |
deleteFiles | true to also delete files |
GET /api/v2/torrents/categories
Section titled “GET /api/v2/torrents/categories”Returns configured categories.
Response:
{ "sonarr": { "name": "sonarr", "savePath": "/downloads/sonarr" }, "radarr": { "name": "radarr", "savePath": "/downloads/radarr" }}WebSocket Protocol
Section titled “WebSocket Protocol”The server exposes a WebSocket endpoint at ws://HOST:PORT for real-time communication.
Client → Server Actions
Section titled “Client → Server Actions”All messages are JSON objects with an action field.
Search
Section titled “Search”{ "action": "search", "query": "file name", "type": "global" }Downloads
Section titled “Downloads”{ "action": "getDownloads" }{ "action": "pauseDownload", "fileHash": "..." }{ "action": "resumeDownload", "fileHash": "..." }{ "action": "delete", "fileHash": "..." }{ "action": "download", "fileHash": "..." }Uploads
Section titled “Uploads”{ "action": "getUploadingQueue" }Shared Files
Section titled “Shared Files”{ "action": "getShared" }{ "action": "reloadSharedFiles" }Statistics
Section titled “Statistics”{ "action": "getStats" }{ "action": "getStatsTree" }Servers
Section titled “Servers”{ "action": "getServers" }{ "action": "connectServer", "serverAddress": "ip:port" }{ "action": "disconnectServer" }{ "action": "removeServer", "serverAddress": "ip:port" }{ "action": "getLog" }{ "action": "getServerInfo" }Categories
Section titled “Categories”{ "action": "getCategories" }{ "action": "createCategory", "category": { "title": "...", "path": "...", "color": 0xCCCCCC, "priority": 0 } }{ "action": "updateCategory", "id": 1, "category": { ... } }{ "action": "deleteCategory", "id": 1 }{ "action": "setFileCategory", "fileHash": "...", "categoryId": 1 }ED2K Links
Section titled “ED2K Links”{ "action": "addEd2kLink", "link": "ed2k://...", "categoryId": 0 }Server → Client Messages
Section titled “Server → Client Messages”All messages are JSON objects with a type field.
Search Results
Section titled “Search Results”{ "type": "search-results", "data": [...] }Downloads Update
Section titled “Downloads Update”{ "type": "downloads-update", "data": [...] }Uploads Update
Section titled “Uploads Update”{ "type": "uploads-update", "data": [...] }Stats Update
Section titled “Stats Update”{ "type": "stats-update", "data": { ... } }Shared Files Update
Section titled “Shared Files Update”{ "type": "shared-update", "data": [...] }Servers Update
Section titled “Servers Update”{ "type": "servers-update", "data": [...] }Categories Update
Section titled “Categories Update”{ "type": "categories-update", "data": [...] }Log Updates
Section titled “Log Updates”{ "type": "log-update", "data": [...] }{ "type": "serverinfo-update", "data": [...] }Error Messages
Section titled “Error Messages”{ "type": "error", "message": "Error description" }Connection Status
Section titled “Connection Status”{ "type": "connection-status", "connected": true }