Skip to content

Latest commit

 

History

History
1083 lines (781 loc) · 22.5 KB

File metadata and controls

1083 lines (781 loc) · 22.5 KB

API Reference

This document describes the REST API and WebSocket protocol used by aMuTorrent.

Table of Contents


Authentication

When web UI authentication is enabled, the following authentication methods apply:

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 requests
curl -b cookies.txt http://host:4000/api/v1/categories

API key:

curl -H 'X-API-Key: your-api-key' http://host:4000/api/v1/categories

API 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

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)

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 apikey query parameter

Example:

GET /indexer/amule/api?t=search&q=test&apikey=YOUR_API_KEY

When configuring in Sonarr/Radarr, enter your admin API key in the "API Key" field.

qBittorrent-Compatible API (for Sonarr/Radarr)

The qBittorrent-compatible API uses HTTP Basic Authentication (admin-only). Two credential methods are supported:

  1. Username + password — use your aMuTorrent admin username and password
  2. 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

General-purpose REST API for managing downloads, categories, search, and more. All endpoints are under /api/v1/.

Authentication

All /api/v1/ endpoints require authentication when auth is enabled. Two methods are supported:

  1. Session cookie — Log in via POST /api/auth/login and include the session cookie in subsequent requests
  2. API key — Pass the X-API-Key header 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

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

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

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

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

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

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

All control endpoints accept an items array with fileHash and instanceId per item.

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

Capabilities: pause_resume

Same request/response format as pause.

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

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

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

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

Rename a file.

Capabilities: rename_files

Request Body:

{
  "fileHash": "abc123...",
  "instanceId": "rtorrent-host-8000",
  "newName": "new-name.mkv"
}

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

Pre-flight checks to verify paths are accessible before performing operations.

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

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

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

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

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

Update an existing category.

Capabilities: manage_categories

Request Body:

{
  "name": "Movies",
  "path": "/downloads/movies-updated",
  "comment": "Updated path"
}

DELETE /api/v1/categories

Delete a category.

Capabilities: manage_categories

Request Body:

{
  "name": "Movies"
}

Search (ED2K)

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

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

GET /api/v1/amule/servers

List ED2K servers.

Capabilities: view_servers

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

Get ED2K server info (message of the day).

Capabilities: view_servers

GET /api/v1/amule/stats-tree

Get aMule statistics tree.

Capabilities: view_statistics

POST /api/v1/amule/refresh-shared

Trigger a shared files rescan.

Capabilities: view_shared

Request Body:

{
  "instanceId": "amule-host-4712"
}

Shared Directory Management (Experimental)

Admin-only endpoints for managing aMule's shareddir.dat file.

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=...

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=...

Rescan subdirectories using roots from config and reload. Picks up new subdirectories without changing root dirs.

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"
}

Logs

GET /api/v1/logs/app

Get aMuTorrent application log.

Capabilities: view_logs

GET /api/v1/logs/amule

Get aMule log.

Capabilities: view_logs

GET /api/v1/logs/qbittorrent

Get qBittorrent log.

Capabilities: view_logs

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

Historical metrics for speed and transfer data.

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

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

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

Download history tracking.

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

Deletes a history entry by file hash.


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

Returns indexer capabilities.

Response: XML with supported categories and search capabilities.

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

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

Returns application version.

Response: v4.5.0

GET /api/v2/app/webapiVersion

Returns Web API version.

Response: 2.8.3

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

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

Pauses download(s).

Form Data:

Field Description
hashes Hash(es) to pause, all for all

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

Deletes download(s).

Form Data:

Field Description
hashes Hash(es) to delete
deleteFiles true to also delete files

GET /api/v2/torrents/categories

Returns configured categories.

Response:

{
  "sonarr": {
    "name": "sonarr",
    "savePath": "/downloads/sonarr"
  },
  "radarr": {
    "name": "radarr",
    "savePath": "/downloads/radarr"
  }
}

WebSocket Protocol

The server exposes a WebSocket endpoint at ws://HOST:PORT for real-time communication.

Client → Server Actions

All messages are JSON objects with an action field.

Search

{ "action": "search", "query": "file name", "type": "global" }

Downloads

{ "action": "getDownloads" }
{ "action": "pauseDownload", "fileHash": "..." }
{ "action": "resumeDownload", "fileHash": "..." }
{ "action": "delete", "fileHash": "..." }
{ "action": "download", "fileHash": "..." }

Uploads

{ "action": "getUploadingQueue" }

Shared Files

{ "action": "getShared" }
{ "action": "reloadSharedFiles" }

Statistics

{ "action": "getStats" }
{ "action": "getStatsTree" }

Servers

{ "action": "getServers" }
{ "action": "connectServer", "serverAddress": "ip:port" }
{ "action": "disconnectServer" }
{ "action": "removeServer", "serverAddress": "ip:port" }

Logs

{ "action": "getLog" }
{ "action": "getServerInfo" }

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

{ "action": "addEd2kLink", "link": "ed2k://...", "categoryId": 0 }

Server → Client Messages

All messages are JSON objects with a type field.

Search Results

{ "type": "search-results", "data": [...] }

Downloads Update

{ "type": "downloads-update", "data": [...] }

Uploads Update

{ "type": "uploads-update", "data": [...] }

Stats Update

{ "type": "stats-update", "data": { ... } }

Shared Files Update

{ "type": "shared-update", "data": [...] }

Servers Update

{ "type": "servers-update", "data": [...] }

Categories Update

{ "type": "categories-update", "data": [...] }

Log Updates

{ "type": "log-update", "data": [...] }
{ "type": "serverinfo-update", "data": [...] }

Error Messages

{ "type": "error", "message": "Error description" }

Connection Status

{ "type": "connection-status", "connected": true }