diff --git a/changelog.d/15611.feature b/changelog.d/15611.feature
new file mode 100644
index 0000000000..7cfb46fd0a
--- /dev/null
+++ b/changelog.d/15611.feature
@@ -0,0 +1 @@
+Add a new admin API to create a new device for a user.
diff --git a/docs/admin_api/user_admin_api.md b/docs/admin_api/user_admin_api.md
index 6b952ba396..229942b311 100644
--- a/docs/admin_api/user_admin_api.md
+++ b/docs/admin_api/user_admin_api.md
@@ -813,6 +813,33 @@ The following fields are returned in the JSON response body:
- `total` - Total number of user's devices.
+### Create a device
+
+Creates a new device for a specific `user_id` and `device_id`. Does nothing if the `device_id`
+exists already.
+
+The API is:
+
+```
+POST /_synapse/admin/v2/users/<user_id>/devices
+
+{
+ "device_id": "QBUAZIFURK"
+}
+```
+
+An empty JSON dict is returned.
+
+**Parameters**
+
+The following parameters should be set in the URL:
+
+- `user_id` - fully qualified: for example, `@user:server.com`.
+
+The following fields are required in the JSON request body:
+
+- `device_id` - The device ID to create.
+
### Delete multiple devices
Deletes the given devices for a specific `user_id`, and invalidates
any access token associated with them.
diff --git a/synapse/rest/admin/devices.py b/synapse/rest/admin/devices.py
index 3b2f2d9abb..11ebed9bfd 100644
--- a/synapse/rest/admin/devices.py
+++ b/synapse/rest/admin/devices.py
@@ -137,6 +137,35 @@ class DevicesRestServlet(RestServlet):
devices = await self.device_handler.get_devices_by_user(target_user.to_string())
return HTTPStatus.OK, {"devices": devices, "total": len(devices)}
+ async def on_POST(
+ self, request: SynapseRequest, user_id: str
+ ) -> Tuple[int, JsonDict]:
+ """Creates a new device for the user."""
+ await assert_requester_is_admin(self.auth, request)
+
+ target_user = UserID.from_string(user_id)
+ if not self.is_mine(target_user):
+ raise SynapseError(
+ HTTPStatus.BAD_REQUEST, "Can only create devices for local users"
+ )
+
+ u = await self.store.get_user_by_id(target_user.to_string())
+ if u is None:
+ raise NotFoundError("Unknown user")
+
+ body = parse_json_object_from_request(request)
+ device_id = body.get("device_id")
+ if not device_id:
+ raise SynapseError(HTTPStatus.BAD_REQUEST, "Missing device_id")
+ if not isinstance(device_id, str):
+ raise SynapseError(HTTPStatus.BAD_REQUEST, "device_id must be a string")
+
+ await self.device_handler.check_device_registered(
+ user_id=user_id, device_id=device_id
+ )
+
+ return HTTPStatus.CREATED, {}
+
class DeleteDevicesRestServlet(RestServlet):
"""
|