diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs
new file mode 100644
index 0000000000..7e7978a7ff
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Workstation.cs
@@ -0,0 +1,167 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Interfaces;
+ using InventorySystem.Items.Firearms.Attachments;
+ using Mirror;
+ using UnityEngine;
+
+ ///
+ /// A wrapper class for .
+ ///
+ public class Workstation : IWrapper, IWorldSpace
+ {
+ ///
+ /// A dictionary mapping to .
+ ///
+ internal static readonly Dictionary WorkstationControllerToWorkstation = new(new ComponentsEqualityComparer());
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to wrap.
+ internal Workstation(WorkstationController workstationController)
+ {
+ WorkstationControllerToWorkstation.Add(workstationController, this);
+ Base = workstationController;
+ }
+
+ ///
+ /// Gets a read-only collection of all instances.
+ ///
+ public static IReadOnlyCollection List => WorkstationControllerToWorkstation.Values;
+
+ ///
+ /// Gets the underlying instance.
+ ///
+ public WorkstationController Base { get; }
+
+ ///
+ /// Gets the of the workstation.
+ ///
+ public GameObject GameObject => Base.gameObject;
+
+ ///
+ /// Gets the of the workstation.
+ ///
+ public Transform Transform => Base.transform;
+
+ ///
+ /// Gets the the workstation is located in.
+ ///
+ public Room Room => Room.Get(Position);
+
+ ///
+ /// Gets the of the workstation's room.
+ ///
+ public ZoneType Zone => Room.Zone;
+
+ ///
+ /// Gets or sets the position of the workstation.
+ ///
+ public Vector3 Position
+ {
+ get => Transform.position;
+ set
+ {
+ NetworkServer.UnSpawn(GameObject);
+ Transform.position = value;
+ NetworkServer.Spawn(GameObject);
+ }
+ }
+
+ ///
+ /// Gets or sets the rotation of the workstation.
+ ///
+ public Quaternion Rotation
+ {
+ get => Transform.rotation;
+ set
+ {
+ NetworkServer.UnSpawn(GameObject);
+ Transform.rotation = value;
+ NetworkServer.Spawn(GameObject);
+ }
+ }
+
+ ///
+ /// Gets or sets the status of the workstation.
+ ///
+ public WorkstationController.WorkstationStatus Status
+ {
+ get => (WorkstationController.WorkstationStatus)Base.Status;
+ set => Base.NetworkStatus = (byte)value;
+ }
+
+ ///
+ /// Gets the used by the workstation.
+ ///
+ public Stopwatch Stopwatch => Base.ServerStopwatch;
+
+ ///
+ /// Gets or sets the player known to be using the workstation.
+ ///
+ public Player KnownUser
+ {
+ get => Player.Get(Base.KnownUser);
+ set => Base.KnownUser = value.ReferenceHub;
+ }
+
+ ///
+ /// Gets a given a instance.
+ ///
+ /// The instance.
+ /// The instance.
+ public static Workstation Get(WorkstationController workstationController) => WorkstationControllerToWorkstation.TryGetValue(workstationController, out Workstation workstation) ? workstation : new(workstationController);
+
+ ///
+ /// Gets all instances that match the specified predicate.
+ ///
+ /// The predicate to filter workstations.
+ /// An of matching workstations.
+ public static IEnumerable Get(Func predicate) => List.Where(predicate);
+
+ ///
+ /// Tries to get all instances that match the specified predicate.
+ ///
+ /// The predicate to filter workstations.
+ /// The matching workstations, if any.
+ /// true if any workstations were found; otherwise, false.
+ public static bool TryGet(Func predicate, out IEnumerable workstations)
+ {
+ workstations = Get(predicate);
+ return workstations.Any();
+ }
+
+ ///
+ /// Determines whether the specified player is in range of the workstation.
+ ///
+ /// The player to check.
+ /// true if the player is in range; otherwise, false.
+ public bool IsInRange(Player player) => Base.IsInRange(player.ReferenceHub);
+
+ ///
+ /// Interacts with the workstation as the specified player.
+ ///
+ /// The player to interact as.
+ public void Interact(Player player) => Base.ServerInteract(player.ReferenceHub, Base.ActivateCollider.ColliderId);
+
+ ///
+ /// Returns the Room in a human-readable format.
+ ///
+ /// A string containing Workstation-related data.
+ public override string ToString() => $"{GameObject.name} ({Zone}) [{Room}]";
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs
new file mode 100644
index 0000000000..544ef5086e
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs
@@ -0,0 +1,39 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Generic
+{
+#pragma warning disable SA1313
+#pragma warning disable SA1402
+
+ using HarmonyLib;
+ using InventorySystem.Items.Firearms.Attachments;
+
+ ///
+ /// Patch for adding to list.
+ ///
+ [HarmonyPatch(typeof(WorkstationController), nameof(WorkstationController.Start))]
+ internal class WorkstationListAdd
+ {
+ private static void Postfix(WorkstationController __instance)
+ {
+ API.Features.Workstation.Get(__instance);
+ }
+ }
+
+ ///
+ /// Patch for removing to list.
+ ///
+ [HarmonyPatch(typeof(WorkstationController), nameof(WorkstationController.OnDestroy))]
+ internal class WorkstationListRemove
+ {
+ private static void Postfix(WorkstationController __instance)
+ {
+ API.Features.Workstation.WorkstationControllerToWorkstation.Remove(__instance);
+ }
+ }
+}
\ No newline at end of file