diff --git a/synadm/api.py b/synadm/api.py
index 75c0cb3d..6c08293d 100644
--- a/synadm/api.py
+++ b/synadm/api.py
@@ -1366,3 +1366,17 @@ def notice_send(self, receivers, content_plain, content_html, paginate,
         else:
             data["user_id"] = receivers
             return [self.query("post", "v1/send_server_notice", data=data)]
+
+    def raw_request(self, endpoint, method, data):
+        data_dict = {}
+        if method != "get":
+            self.log.debug("The data we are trying to parse and submit:")
+            self.log.debug(data)
+            try:  # user provided json might be crap
+                data_dict = json.loads(data)
+            except Exception as error:
+                self.log.error("loading data: %s: %s",
+                               type(error).__name__, error)
+                return None
+
+        return self.query(method, endpoint, data=data_dict)
diff --git a/synadm/cli/__init__.py b/synadm/cli/__init__.py
index 8346743b..a758c997 100644
--- a/synadm/cli/__init__.py
+++ b/synadm/cli/__init__.py
@@ -505,4 +505,4 @@ def version(helper):
 
 
 # Import additional commands
-from synadm.cli import room, user, media, group, history, matrix, regtok, notice  # noqa: F401, E402, E501
+from synadm.cli import room, user, media, group, history, matrix, regtok, notice, raw  # noqa: F401, E402, E501
diff --git a/synadm/cli/raw.py b/synadm/cli/raw.py
new file mode 100644
index 00000000..8dd7c85f
--- /dev/null
+++ b/synadm/cli/raw.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+# synadm
+# Copyright (C) 2020-2023 Johannes Tiefenbacher
+#
+# synadm is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# synadm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""This module holds the `raw` command only."""
+
+import click
+
+from synadm import cli
+from synadm.cli._common import common_opts_raw_command, data_opts_raw_command
+
+
+@cli.root.command(name="raw")
+@common_opts_raw_command
+@data_opts_raw_command
+@click.pass_obj
+def raw_request_cmd(helper, endpoint, method, data, data_file):
+    """ Issue a custom request to the Synapse Admin API.
+
+    The endpoint argument is the part of the URL _after_ the configured
+    "Synapse base URL" and "Synapse Admin API path" (see `synadm config`).
+    A get request to the "Query User Account API" would look like this:
+    `synadm raw v2/users/%40testuser%3Aexample.org`. URL encoding must be
+    handled at this point. Consider enabling debug outputs via synadm's global
+    flag `-vv`
+    """
+    if data_file:
+        data = data_file.read()
+
+    raw_request = helper.api.raw_request(endpoint, method, data)
+
+    if helper.no_confirm:
+        if raw_request is None:
+            raise SystemExit(1)
+        helper.output(raw_request)
+    else:
+        if raw_request is None:
+            click.echo("The Admin API's response was empty or JSON data "
+                       "could not be loaded.")
+            raise SystemExit(1)
+        else:
+            helper.output(raw_request)