Plex Host Docs
API

Examples

Every snippet on this page uses plx_srv_… as a placeholder — swap it for a real token from Tokens, and never commit a real token to source control.

Restart a server

curl -X POST https://api.host.plex.gg/api/v1/servers/srv_01hz.../power \
  -H "Authorization: Bearer plx_srv_…" \
  -H "Content-Type: application/json" \
  -d '{"action": "restart"}'
const token = process.env.PLEX_HOST_TOKEN // plx_srv_…
const serverId = 'srv_01hz...'

const res = await fetch(`https://api.host.plex.gg/api/v1/servers/${serverId}/power`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ action: 'restart' }),
})

/** @type {{ data?: { queued: boolean }, meta?: { requestId: string }, error?: { code: string, message: string } }} */
const body = await res.json()

if (!res.ok) {
  throw new Error(`${body.error?.code}: ${body.error?.message} (requestId ${body.error?.requestId})`)
}

console.log('restart queued, requestId', body.meta?.requestId)
import os
import requests

token = os.environ["PLEX_HOST_TOKEN"]  # plx_srv_…
server_id = "srv_01hz..."

res = requests.post(
    f"https://api.host.plex.gg/api/v1/servers/{server_id}/power",
    headers={"Authorization": f"Bearer {token}"},
    json={"action": "restart"},
    timeout=10,
)
body = res.json()

if not res.ok:
    error = body["error"]
    raise RuntimeError(f"{error['code']}: {error['message']} (requestId {error['requestId']})")

print("restart queued, requestId", body["meta"]["requestId"])

Discord bot

A discord.js slash command that restarts a server and reports back the request id, for correlating a Discord report with server-side logs.

import { SlashCommandBuilder } from 'discord.js'

export const data = new SlashCommandBuilder()
  .setName('restart-server')
  .setDescription('Restart a Plex Host server')
  .addStringOption((option) =>
    option.setName('server-id').setDescription('Server id, e.g. srv_01hz...').setRequired(true)
  )

export async function execute(interaction) {
  const serverId = interaction.options.getString('server-id', true)
  const token = process.env.PLEX_HOST_TOKEN // plx_srv_…, scoped to canControlServer only

  await interaction.deferReply()

  const res = await fetch(`https://api.host.plex.gg/api/v1/servers/${serverId}/power`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ action: 'restart' }),
  })
  const body = await res.json()

  if (!res.ok) {
    await interaction.editReply(
      `Restart failed: **${body.error.code}** — ${body.error.message} (requestId \`${body.error.requestId}\`)`
    )
    return
  }

  await interaction.editReply(`Restart queued for \`${serverId}\` (requestId \`${body.meta.requestId}\`).`)
}

Mint a dedicated server token for the bot with only canControlServer (and canViewServer if it also reports status), and set an IP allowlist to the host running the bot if it has a static address.

On this page