diff --git a/src/pages/api/services/proxy.js b/src/pages/api/services/proxy.js
index be4a96a6..9347c4eb 100644
--- a/src/pages/api/services/proxy.js
+++ b/src/pages/api/services/proxy.js
@@ -18,6 +18,11 @@ export default async function handler(req, res) {
     const serviceProxyHandler = widget.proxyHandler || genericProxyHandler;
 
     if (serviceProxyHandler instanceof Function) {
+      // quick return for no endpoint services
+      if (!req.query.endpoint) {
+        return serviceProxyHandler(req, res);
+      }
+
       // map opaque endpoints to their actual endpoint
       if (widget?.mappings) {
         const mapping = widget?.mappings?.[req.query.endpoint];
@@ -38,6 +43,15 @@ export default async function handler(req, res) {
 
         if (req.query.segments) {
           const segments = JSON.parse(req.query.segments);
+          for (const key in segments) {
+            if (!mapping.segments.includes(key)) {
+              logger.debug("Unsupported segment: %s", key);
+              return res.status(403).json({ error: "Unsupported segment" });
+            } else if (segments[key].includes("/")) {
+              logger.debug("Unsupported segment value: %s", segments[key]);
+              return res.status(403).json({ error: "Unsupported segment value" });
+            }
+          }
           req.query.endpoint = formatApiCall(endpoint, segments);
         }
 
@@ -66,7 +80,14 @@ export default async function handler(req, res) {
         return serviceProxyHandler(req, res, map);
       }
 
-      return serviceProxyHandler(req, res);
+      if (widget.allowedEndpoints instanceof RegExp) {
+        if (widget.allowedEndpoints.test(req.query.endpoint)) {
+          return serviceProxyHandler(req, res);
+        }
+      }
+
+      logger.debug("Unmapped proxy request.");
+      return res.status(403).json({ error: "Unmapped proxy request." });
     }
 
     logger.debug("Unknown proxy service type: %s", type);
diff --git a/src/utils/proxy/api-helpers.js b/src/utils/proxy/api-helpers.js
index ffd2f63b..dceea3c4 100644
--- a/src/utils/proxy/api-helpers.js
+++ b/src/utils/proxy/api-helpers.js
@@ -8,22 +8,16 @@ export function formatApiCall(url, args) {
   return url.replace(/\/+$/, "").replace(find, replace).replace(find, replace);
 }
 
-function getURLSearchParams(widget, endpoint) {
+export function getURLSearchParams(widget, endpoint) {
   const params = new URLSearchParams({
     type: widget.type,
     group: widget.service_group,
     service: widget.service_name,
-    endpoint,
   });
-  return params;
-}
-
-export function formatProxyUrlWithSegments(widget, endpoint, segments) {
-  const params = getURLSearchParams(widget, endpoint);
-  if (segments) {
-    params.append("segments", JSON.stringify(segments));
+  if (endpoint) {
+    params.append("endpoint", endpoint);
   }
-  return `/api/services/proxy?${params.toString()}`;
+  return params;
 }
 
 export function formatProxyUrl(widget, endpoint, queryParams) {
@@ -59,6 +53,7 @@ export function sanitizeErrorURL(errorURL) {
   const url = new URL(errorURL);
   ["apikey", "api_key", "token", "t", "access_token", "auth"].forEach((key) => {
     if (url.searchParams.has(key)) url.searchParams.set(key, "***");
+    if (url.hash.includes(key)) url.hash = url.hash.replace(new RegExp(`${key}=[^&]+`), `${key}=***`);
   });
   return url.toString();
 }
diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx
index 9084cbac..090a9c3f 100644
--- a/src/widgets/emby/component.jsx
+++ b/src/widgets/emby/component.jsx
@@ -4,7 +4,7 @@ import { MdOutlineSmartDisplay } from "react-icons/md";
 
 import Block from "components/services/widget/block";
 import Container from "components/services/widget/container";
-import { formatProxyUrlWithSegments } from "utils/proxy/api-helpers";
+import { getURLSearchParams } from "utils/proxy/api-helpers";
 import useWidgetAPI from "utils/proxy/use-widget-api";
 
 function ticksToTime(ticks) {
@@ -217,10 +217,14 @@ export default function Component({ service }) {
   });
 
   async function handlePlayCommand(session, command) {
-    const url = formatProxyUrlWithSegments(widget, "PlayControl", {
-      sessionId: session.Id,
-      command,
-    });
+    const params = getURLSearchParams(widget, command);
+    params.append(
+      "segments",
+      JSON.stringify({
+        sessionId: session.Id,
+      }),
+    );
+    const url = `/api/services/proxy?${params.toString()}`;
     await fetch(url).then(() => {
       sessionMutate();
     });
diff --git a/src/widgets/emby/widget.js b/src/widgets/emby/widget.js
index 1dc009b2..3b04f59f 100644
--- a/src/widgets/emby/widget.js
+++ b/src/widgets/emby/widget.js
@@ -10,12 +10,16 @@ const widget = {
     },
     Count: {
       endpoint: "Items/Counts",
-      segments: ["MovieCount", "SeriesCount", "EpisodeCount", "SongCount"],
     },
-    PlayControl: {
+    Unpause: {
       method: "POST",
-      endpoint: "Sessions/{sessionId}/Playing/{command}",
-      segments: ["sessionId", "command"],
+      endpoint: "Sessions/{sessionId}/Playing/Unpause",
+      segments: ["sessionId"],
+    },
+    Pause: {
+      method: "POST",
+      endpoint: "Sessions/{sessionId}/Playing/Pause",
+      segments: ["sessionId"],
     },
   },
 };
diff --git a/src/widgets/flood/widget.js b/src/widgets/flood/widget.js
index 027ff344..13413cf4 100644
--- a/src/widgets/flood/widget.js
+++ b/src/widgets/flood/widget.js
@@ -2,6 +2,12 @@ import floodProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: floodProxyHandler,
+
+  mappings: {
+    torrents: {
+      endpoint: "torrents",
+    },
+  },
 };
 
 export default widget;
diff --git a/src/widgets/fritzbox/widget.js b/src/widgets/fritzbox/widget.js
index 13193821..32e8a5c2 100644
--- a/src/widgets/fritzbox/widget.js
+++ b/src/widgets/fritzbox/widget.js
@@ -2,6 +2,7 @@ import fritzboxProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: fritzboxProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/gamedig/widget.js b/src/widgets/gamedig/widget.js
index 6ccfa123..0f888b43 100644
--- a/src/widgets/gamedig/widget.js
+++ b/src/widgets/gamedig/widget.js
@@ -2,6 +2,7 @@ import gamedigProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: gamedigProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/glances/widget.js b/src/widgets/glances/widget.js
index 3357cf28..e018ae39 100644
--- a/src/widgets/glances/widget.js
+++ b/src/widgets/glances/widget.js
@@ -3,6 +3,7 @@ import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
 const widget = {
   api: "{url}/api/{endpoint}",
   proxyHandler: credentialedProxyHandler,
+  allowedEndpoints: /\d\/quicklook|diskio|fs|gpu|system|mem|network|processlist|sensors/,
 };
 
 export default widget;
diff --git a/src/widgets/minecraft/widget.js b/src/widgets/minecraft/widget.js
index f8a81bfb..fbe413b7 100644
--- a/src/widgets/minecraft/widget.js
+++ b/src/widgets/minecraft/widget.js
@@ -2,6 +2,7 @@ import minecraftProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: minecraftProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/npm/component.jsx b/src/widgets/npm/component.jsx
index 37712266..06ac91eb 100644
--- a/src/widgets/npm/component.jsx
+++ b/src/widgets/npm/component.jsx
@@ -5,7 +5,7 @@ import useWidgetAPI from "utils/proxy/use-widget-api";
 export default function Component({ service }) {
   const { widget } = service;
 
-  const { data: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts");
+  const { data: infoData, error: infoError } = useWidgetAPI(widget, "hosts");
 
   if (infoError) {
     return <Container service={service} error={infoError} />;
diff --git a/src/widgets/npm/widget.js b/src/widgets/npm/widget.js
index 652cb4a2..24b3ce02 100644
--- a/src/widgets/npm/widget.js
+++ b/src/widgets/npm/widget.js
@@ -3,6 +3,12 @@ import npmProxyHandler from "./proxy";
 const widget = {
   api: "{url}/api/{endpoint}",
   proxyHandler: npmProxyHandler,
+
+  mappings: {
+    hosts: {
+      endpoint: "nginx/proxy-hosts",
+    },
+  },
 };
 
 export default widget;
diff --git a/src/widgets/nzbget/widget.js b/src/widgets/nzbget/widget.js
index 841fb66c..79ca1807 100644
--- a/src/widgets/nzbget/widget.js
+++ b/src/widgets/nzbget/widget.js
@@ -3,6 +3,7 @@ import jsonrpcProxyHandler from "utils/proxy/handlers/jsonrpc";
 const widget = {
   api: "{url}/jsonrpc",
   proxyHandler: jsonrpcProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/qbittorrent/component.jsx b/src/widgets/qbittorrent/component.jsx
index 615709ea..e88b2622 100644
--- a/src/widgets/qbittorrent/component.jsx
+++ b/src/widgets/qbittorrent/component.jsx
@@ -9,7 +9,7 @@ export default function Component({ service }) {
 
   const { widget } = service;
 
-  const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents/info");
+  const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents");
 
   if (torrentError) {
     return <Container service={service} error={torrentError} />;
diff --git a/src/widgets/qbittorrent/widget.js b/src/widgets/qbittorrent/widget.js
index 1e8348b3..182ac9d1 100644
--- a/src/widgets/qbittorrent/widget.js
+++ b/src/widgets/qbittorrent/widget.js
@@ -2,6 +2,12 @@ import qbittorrentProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: qbittorrentProxyHandler,
+
+  mappings: {
+    torrents: {
+      endpoint: "torrents/info",
+    },
+  },
 };
 
 export default widget;
diff --git a/src/widgets/qnap/widget.js b/src/widgets/qnap/widget.js
index ebaf93c9..1069fa9a 100644
--- a/src/widgets/qnap/widget.js
+++ b/src/widgets/qnap/widget.js
@@ -3,6 +3,7 @@ import qnapProxyHandler from "./proxy";
 const widget = {
   api: "{url}",
   proxyHandler: qnapProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/swagdashboard/widget.js b/src/widgets/swagdashboard/widget.js
index 626586fe..7067e55d 100644
--- a/src/widgets/swagdashboard/widget.js
+++ b/src/widgets/swagdashboard/widget.js
@@ -3,6 +3,7 @@ import genericProxyHandler from "utils/proxy/handlers/generic";
 const widget = {
   api: "{url}/?stats=true",
   proxyHandler: genericProxyHandler,
+  allowedEndpoints: /overview/,
 };
 
 export default widget;
diff --git a/src/widgets/tdarr/proxy.js b/src/widgets/tdarr/proxy.js
index a1ebc149..898082f4 100644
--- a/src/widgets/tdarr/proxy.js
+++ b/src/widgets/tdarr/proxy.js
@@ -8,7 +8,7 @@ const proxyName = "tdarrProxyHandler";
 const logger = createLogger(proxyName);
 
 export default async function tdarrProxyHandler(req, res) {
-  const { group, service, endpoint } = req.query;
+  const { group, service } = req.query;
 
   if (!group || !service) {
     logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
@@ -22,7 +22,7 @@ export default async function tdarrProxyHandler(req, res) {
     return res.status(400).json({ error: "Invalid proxy service type" });
   }
 
-  const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
+  const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint: undefined, ...widget }));
 
   const [status, contentType, data] = await httpProxy(url, {
     method: "POST",
diff --git a/src/widgets/transmission/proxy.js b/src/widgets/transmission/proxy.js
index f12d2a0c..823def05 100644
--- a/src/widgets/transmission/proxy.js
+++ b/src/widgets/transmission/proxy.js
@@ -11,7 +11,7 @@ const headerCacheKey = `${proxyName}__headers`;
 const logger = createLogger(proxyName);
 
 export default async function transmissionProxyHandler(req, res) {
-  const { group, service, endpoint } = req.query;
+  const { group, service } = req.query;
 
   if (!group || !service) {
     logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
@@ -35,7 +35,7 @@ export default async function transmissionProxyHandler(req, res) {
 
   const api = `${widget.url}${widget.rpcUrl || widgets[widget.type].rpcUrl}rpc`;
 
-  const url = new URL(formatApiCall(api, { endpoint, ...widget }));
+  const url = new URL(formatApiCall(api, { endpoint: undefined, ...widget }));
   const csrfHeaderName = "x-transmission-session-id";
 
   const method = "POST";
diff --git a/src/widgets/urbackup/widget.js b/src/widgets/urbackup/widget.js
index 5eac66d0..96c52296 100644
--- a/src/widgets/urbackup/widget.js
+++ b/src/widgets/urbackup/widget.js
@@ -2,6 +2,7 @@ import urbackupProxyHandler from "./proxy";
 
 const widget = {
   proxyHandler: urbackupProxyHandler,
+  allowedEndpoints: /status/,
 };
 
 export default widget;
diff --git a/src/widgets/xteve/component.jsx b/src/widgets/xteve/component.jsx
index 75629909..84a617c2 100644
--- a/src/widgets/xteve/component.jsx
+++ b/src/widgets/xteve/component.jsx
@@ -9,7 +9,7 @@ export default function Component({ service }) {
 
   const { widget } = service;
 
-  const { data: xteveData, error: xteveError } = useWidgetAPI(widget, "api");
+  const { data: xteveData, error: xteveError } = useWidgetAPI(widget);
 
   if (xteveError) {
     return <Container service={service} error={xteveError} />;
diff --git a/src/widgets/xteve/proxy.js b/src/widgets/xteve/proxy.js
index a8b1c80f..421f2b49 100644
--- a/src/widgets/xteve/proxy.js
+++ b/src/widgets/xteve/proxy.js
@@ -7,7 +7,7 @@ import getServiceWidget from "utils/config/service-helpers";
 const logger = createLogger("xteveProxyHandler");
 
 export default async function xteveProxyHandler(req, res) {
-  const { group, service, endpoint } = req.query;
+  const { group, service } = req.query;
 
   if (!group || !service) {
     return res.status(400).json({ error: "Invalid proxy service type" });
@@ -19,7 +19,7 @@ export default async function xteveProxyHandler(req, res) {
     return res.status(403).json({ error: "Service does not support API calls" });
   }
 
-  const url = formatApiCall(api, { endpoint, ...widget });
+  const url = formatApiCall(api, { endpoint: "api/", ...widget });
   const method = "POST";
   const payload = { cmd: "status" };
 
diff --git a/src/widgets/xteve/widget.js b/src/widgets/xteve/widget.js
index e7998e2e..72c62b25 100644
--- a/src/widgets/xteve/widget.js
+++ b/src/widgets/xteve/widget.js
@@ -3,12 +3,6 @@ import xteveProxyHandler from "./proxy";
 const widget = {
   api: "{url}/{endpoint}",
   proxyHandler: xteveProxyHandler,
-
-  mappings: {
-    api: {
-      endpoint: "api/",
-    },
-  },
 };
 
 export default widget;