Post

Using the HTTP API of tinyMediaManager

Using the HTTP API of tinyMediaManager

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:

  1. Open SettingsGeneralSystemHTTP API.
  2. Check ✅ Enable HTTP API.
  3. An API key (a random GUID) is pre-generated - you may use this or create your own.
  4. 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 as update, 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 the update command in the same request.
  • If you run scrape alone 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:

  1. Scan your sources for new files.
  2. Scrape metadata only for new entries found in that scan.
  3. 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 OK once 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:

  1. update
  2. scrape
  3. rename

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 POST with Content-Type: application/json
  • 🔐 Authenticate via api-key
  • 🔄 Commands are queued and run asynchronously
  • 📑 Internal order of commands is fixed
  • ⚠️ scope = new only works with update in the same request

With these tools, tmm becomes a solid part of any modern media automation setup.

This post is licensed under CC BY 4.0 by the author.