These docs are for MetaTana 2.0, coming soon
API
MetaTana has a local app API at /api/v1/**. The web UI uses it, and so do scripts and the MCP bridge. This page covers how authentication works, where to find the full endpoint list, how to make your first call, and the curl recipes you'll reach for.
Discover the full API
Three places in the app describe the API:
/api/v1/docs: an interactive browser for every endpoint, with request and response shapes and "try it now".
/api/v1/openapi: the JSON spec, for generators and clients.
This page covers contracts, conventions, and worked examples. It doesn't list every endpoint; use the OpenAPI docs above for that.
Authentication
External callers send two headers:
x-api-key: <local API key from Settings › Maintenance › Advanced › API key>
x-metatana-hosted-session: <hosted Pro session token>
The hosted-session header is the Pro check. Calls without it fail with a Pro-required error even when the API key is valid.
METATANA_AUTH_BYPASS and METATANA_TEST_AUTH_BYPASS). The Pro check can't be turned off in a release build.
The web UI authenticates via a same-origin session cookie set by POST /api/auth/session. Browser calls from the MetaTana UI don't carry the two external headers; the cookie is enough. That exchange works only for the account linked to the install; any other account gets 403 with {"error": "This MetaTana is linked to a different account.", "code": "install_owner_mismatch"} and no cookie. See Install owner.
Host names and cross-origin writes
Every page and API request passes two checks first. Both answer with a plain-text body, not JSON.
421 Misdirected Requestwhen theHostheader is not a name MetaTana trusts. IP addresses,localhost, one-word names, and names ending in.local,.lan,.home,.home.arpa,.internal, or.localdomainalways pass. For any other name, add it toMETATANA_ALLOWED_HOSTS. Scripts that callhttp://localhost:3000or an IP address are not affected.403for aPOST,PUT,PATCH, orDELETEto/api/**sent by a browser page from another origin. Requests without a browserOriginheader, such as curl, scripts, the CLI, and the MCP bridge, are not affected.
Quick start
Health check (no auth)
GET
/api/health
Liveness probe
curl http://localhost:3000/api/health
Returns 200 with a small JSON body when the app is up. No auth required. Useful for container healthchecks.
List library items
GET
/api/v1/library
Paginated library list
curl "http://localhost:3000/api/v1/library?limit=10" \
-H "x-api-key: $METATANA_API_KEY" \
-H "x-metatana-hosted-session: $METATANA_HOSTED_SESSION"
Returns one page of library items as items plus a total. Use limit and offset to page, type for one media type, q for search text, and filter and sort for the Library's filter and sort expressions (see /api/v1/docs for the full filter language).
Search for a match
POST
/api/v1/scrape
Search the providers, as Rescrape does
curl -X POST "http://localhost:3000/api/v1/scrape" \
-H "x-api-key: $METATANA_API_KEY" \
-H "x-metatana-hosted-session: $METATANA_HOSTED_SESSION" \
-H "Content-Type: application/json" \
-d '{"query": "Midnight Harbor", "year": 2024, "mediaType": "movie"}'
Searches your configured providers and returns candidates. Nothing in the library changes. The same endpoint takes { enrichId } to fetch one candidate's full metadata and { matchId, providerId, mediaType } to apply it; applying keeps your edits and locked fields. See /api/v1/docs for the full request body.
Endpoint categories
The API is grouped into these areas. Use /api/v1/docs for the per-endpoint detail.
| Category | Examples | What it covers |
|---|---|---|
| Library | /api/v1/library, /api/v1/library/{id}, /api/v1/library/editions |
Browse, filter, fetch detail, delete |
| Scrape | /api/v1/scrape, /api/v1/scrape/auto, /api/v1/scrape/sessions |
Search, fetch, and apply matches; bulk scrape; scrape sessions |
| Shows | /api/v1/shows/{id}/extras, /api/v1/shows/{id}/provenance |
Show reads, including where each field's value came from |
| Metadata editor | /api/v1/metadata-editor/tasks, PATCH /api/v1/metadata-editor/show/{id} |
The Needs attention task lists and title edits |
| Folders | /api/v1/sources, /api/v1/sources/stats, /api/v1/sources/scan/status |
The Folders page: folder list, scans, scan status |
| Activity & operations | /api/v1/activity/summary, /api/v1/operations, /api/v1/operations/{id}/retry |
Activity history, retry, undo |
| Sync | /api/v1/sync/status, /api/v1/playback-destinations |
Media server sync state |
| Diagnostics | /api/v1/observability/pipeline |
Scan and match counts, recent failures |
| System | /api/v1/status, /api/health, /api/v1/openapi |
App status and the API spec |
| Admin | /api/v1/admin/library-reset, /api/v1/admin/factory-reset |
Destructive maintenance (see below) |
Admin endpoints: destructive
The two admin reset endpoints are the API form of Settings › Maintenance › Danger zone. They are local maintenance actions, not file deletion: media files and sidecars on disk stay untouched. Both need an exact confirmation string in the body, and both save a "Before reset" database backup first. If that backup fails, nothing changes and the call returns 409.
POST
/api/v1/admin/library-reset
Clear derived library state
curl -X POST "http://localhost:3000/api/v1/admin/library-reset" \
-H "x-api-key: $METATANA_API_KEY" \
-H "x-metatana-hosted-session: $METATANA_HOSTED_SESSION" \
-H "Content-Type: application/json" \
-d '{"confirm": "RESET LIBRARY"}'
Clears the library MetaTana built (matches, metadata, file records). Keeps: your folders and path mappings, settings and provider keys, destinations and media servers, tags, saved filters, routing rules, and per-show metadata and episode order choices. Use this when you want a clean re-scan without losing your setup.
Answers 202: the reset runs the next time MetaTana starts, after a "Before reset" backup. DELETE on the same path cancels it before then.
POST
/api/v1/admin/factory-reset
Drop user tables, rerun migrations
curl -X POST "http://localhost:3000/api/v1/admin/factory-reset" \
-H "x-api-key: $METATANA_API_KEY" \
-H "x-metatana-hosted-session: $METATANA_HOSTED_SESSION" \
-H "Content-Type: application/json" \
-d '{"confirm": "RESET METATANA"}'
Drops all user-owned database tables and reruns migrations to first-run state, like a fresh install with the same database path. Folders, provider keys, destinations: everything goes. Sidecar files on disk are untouched.
Answers 202: the reset runs the next time MetaTana starts, after a "Before reset" backup. DELETE on the same path cancels it before then.
Install owner
Each install is linked to the first MetaTana account that signs in. On Docker and NAS installs, signing in from another device also needs the one-time claim code from the server log (see Enter the claim code); the desktop app needs no code. This endpoint unlinks the owner, so the next account to sign in is linked instead, and a new claim code is printed. It is the API form of metatana owner reset.
DELETE
/api/auth/owner
Unlink the account this install belongs to
curl -X DELETE "http://localhost:3000/api/auth/owner" \
-H "x-api-key: $METATANA_API_KEY"
Returns {"unlinked": true}, or {"unlinked": false} when no account was linked. Accepted only with the local API key, a local MetaTana browser session, or, on the desktop app, a request from the same computer. It does not need the hosted Pro header. A hosted session on its own gets 401, so another MetaTana account can never unlink the owner over the network. The MCP bridge blocks this endpoint. A factory reset also unlinks the owner.
MCP bridge
The MCP bridge lets MCP-capable agents (Claude Desktop, Claude Code, Cursor, and others) use the local API over stdio. It runs from the installed desktop app. Copy the exact client configuration from Settings › Maintenance › Advanced › MCP › Set up; on macOS it looks like this:
{
"mcpServers": {
"metatana": {
"command": "/Applications/MetaTana.app/Contents/MacOS/MetaTana",
"args": ["--mcp-stdio"],
"env": {
"METATANA_DATA_DIR": "/Users/you/Library/Application Support/MetaTana/data"
}
}
}
}
The copied configuration uses your install's real executable path and data folder, so Windows and Linux installs work the same way. No npm or separate Node install is needed.
MCP is Pro. The bridge checks for a signed-in Pro account before it offers any tools. It attaches the local API key and verified hosted session automatically. Agents don't see credential values.
The bridge is stricter than a direct API-key caller. An agent reads provider text and NFO plots, which can carry instructions, so the bridge checks every call before it reaches the app:
- Reads (
GET) are open, except the routes refused below. - Changes (
POST,PATCH,PUT,DELETE) are refused unless the route belongs to library work: scans, scrapes, Arrivals and the Inbox, metadata editing, NFO and artwork, subtitles, trailers, renames, organize, operations and undo, duplicates, people, tags, collections, folders, destinations, routing rules, media server sync, Trakt sync, database backups, and running a manual tool you already saved. A new route stays closed until it is added to that list. - Always refused: sign-in and local auth routes,
tools/testandtools/preview(which run a command you didn't save), hooks and webhooks, every Settings write including provider keys, media server and Trakt sign-ins,/api/v1/admin/**(factory and library reset), backup export and restore, and routes that open files in other programs.
A refused call fails in the bridge with a plain message and never reaches the app. Make those changes in the MetaTana app.
Conventions
- Versioning: endpoints live under
/api/v1/. - Errors: non-2xx responses carry a JSON body with an
errormessage. Some also include acode. - Pagination: list endpoints such as
/api/v1/librarytakelimitandoffsetand returnitemsandtotal. - Timestamps: ISO 8601 UTC.
- IDs: numeric SQLite row IDs unless explicitly external (TMDb ID, IMDb ID, etc.).
Going deeper
- Local API key: enable the key, make your first call
- Reference: API keys: key rotation, env-var configuration
- AI and agents: MCP bridge architecture and tool catalog
- Accounts and Pro: what Pro adds