Using the HTTP API of tinyMediaManager
Automate tinyMediaManager via its HTTP API: enable the API, auth with api-key, send JSON commands, understand scope=new, and run curl/bash examples.
tinyMediaManager (commonly referred to as tmm) is a GUI application for organizing and managing local libraries of movies and TV shows. While itβs primarily desktop-oriented, it also includes a powerful but minimal HTTP API, making it suitable for automated and headless environments.
This blog post walks you through enabling the API, how it works internally, and how to integrate it with automation tools like Radarr, Sonarr, SABnzbd, or even shell scripts.
βοΈ What Is the tmm HTTP API?
The tmm HTTP API allows you to trigger core media actions:
- π Update data sources (scan folders)
- π§² Scrape metadata
- π§ Download trailers/subtitles
- π Rename media files
- β¦
Itβs designed for lightweight remote control, not full database querying. Think of it as a command queue for background jobs.
π Official API Documentation
π οΈ How to Enable the API
To use the API, you must enable it in the tmm GUI.
Steps:
- Open Settings β
GeneralβSystemβHTTP API. - Check β Enable HTTP API.
- An API key (a random GUID) is pre-generated - you may use this or create your own.
- Choose the listening port (default is
7878).
π Keep your API key secure - anyone with access can control your media library.
π Authentication and Request Format
All API requests must be authenticated using a custom header:
1
api-key: your-api-key
Do not pass the API key as a query parameter - it will be ignored.
JSON Payload Format
All commands are issued as POST requests with JSON.
Hereβs the basic structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[
{
"action": <action name>,
"scope": {
"name": <scope name>,
"args": [
<value>
]
},
"args": {
<key>: <value>
}
},
...
]
You will find more details about possible actions and arguments in the Official API Documentation.
π§ Understanding the scope = new Behavior
This is one of the most misunderstood parts of the tmm API.
1
2
3
"scope": {
"name": "new"
}
This does not mean βprocess anything newly added since last time.β
Instead, hereβs how it works:
If you include
"scope": "new"in the same API call asupdate, only media items detected during that update will be processed by subsequent commands (e.g.,scrape,rename).
π§ Important notes:
- The
"new"scope has no memory. It only applies to the results of theupdatecommand in the same request. - If you run
scrapealone with"scope": "new"- it will do nothing, because thereβs no list of new items.
Correct Usage:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[
{
"action": "update",
"scope": {
"name": "all"
}
},
{
"action": "scrape",
"scope": {
"name": "new"
}
},
{
"action": "rename",
"scope": {
"name": "new"
}
}
]
This will:
- Scan your sources for new files.
- Scrape metadata only for new entries found in that scan.
- Rename those new entries.
π API Execution Flow
Hereβs how a request is processed inside tmm:
sequenceDiagram
participant ExternalTool as π§° External Tool (e.g. Radarr)
participant HttpServer as π tmm HTTP Server
participant CommandParser as βοΈ Command Parser
participant JobQueue as π¬ Async Job Queue
participant Core as π¦ Core Executor
ExternalTool->>HttpServer: POST /api/v1/command\n+ JSON Payload\n+ api-key
HttpServer->>CommandParser: β
Validate & Parse
CommandParser->>JobQueue: π¨ Enqueue Commands
JobQueue-->>CommandParser: π Job(s) Queued
CommandParser-->>HttpServer: π Job(s) Queued
HttpServer-->>ExternalTool: π¬ HTTP 200 OK
JobQueue->>Core: π Execute Jobs (Async)
Core-->>JobQueue: β
Done
π Summary:
- The client receives
200 OKonce the commands are queued - not when they finish. - Jobs are processed asynchronously, in the internal order defined by the source code.
- The
"scope"affects command behavior only within the context of this request.
π§© Execution Order of Commands
Even though you send multiple commands like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[
{
"action": "rename",
"scope": {
"name": "new"
}
},
{
"action": "scrape",
"scope": {
"name": "new"
}
},
{
"action": "update",
"scope": {
"name": "all"
}
}
]
They are always processed in the predefined internal order, for example:
updatescraperename
This behavior is hardcoded in the tmm source files:
π§ The order in your JSON request does not matter.
π§ͺ Real-World Automation Examples
Example: Scrape and Rename Newly Added Movies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
curl -X POST http://localhost:7878/api/movie \
-H "Content-Type: application/json" \
-H "api-key: your-api-key" \
-d '[
{
"action": "update",
"scope": {
"name": "all"
}
},
{
"action": "scrape",
"scope": {
"name": "new"
}
},
{
"action": "rename",
"scope": {
"name": "new"
}
}
]'
Example: TV Show Automation After Import of New Episodes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl -X POST http://localhost:7878/api/tvshow \
-H "Content-Type: application/json" \
-H "api-key: your-api-key" \
-d '[
{
"action": "update",
"scope": {
"name": "path",
"args": "/media/tv_shows/Show 1"
}
},
{
"action": "scrape",
"scope": {
"name" : "new"
}
}
]'
Clean Bash Script Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
API_KEY="your-api-key"
API_URL="http://localhost:7878/api/movie"
curl -X POST "$API_URL" \
-H "Content-Type: application/json" \
-H "api-key: $API_KEY" \
-d '{
"action": "update",
"scope": {
"name": "all"
}
}'
π Resources
π§ Final Thoughts
tinyMediaManager isnβt just for GUI users. With its JSON-based HTTP API, you can fully automate your media processing workflow:
- Trigger updates and metadata scraping after downloads
- Automatically rename files
- Integrate with Radarr, Sonarr, or custom scripts
Just remember:
- π¬ Use
POSTwithContent-Type: application/json - π Authenticate via
api-key - π Commands are queued and run asynchronously
- π Internal order of commands is fixed
- β οΈ
scope = newonly works withupdatein the same request
With these tools, tmm becomes a solid part of any modern media automation setup.
