diff --git a/gso/cli/netbox.py b/gso/cli/netbox.py
index d3016443c3870f01cebf521fad0d6a830326c20e..ddaa94ff7f70ab045f266629bc2e4370061cb3b7 100644
--- a/gso/cli/netbox.py
+++ b/gso/cli/netbox.py
@@ -8,7 +8,7 @@ app: typer.Typer = typer.Typer()
 
 @app.command()
 def netbox_initial_setup() -> None:
-    """Initial setup of NetBox.
+    """Set up NetBox for the first time.
 
     It includes:
     - Creating a default site (GEANT)
diff --git a/gso/services/netbox_client.py b/gso/services/netbox_client.py
index 67cfe77e767346d1dae215fc28d589960f7578db..4d6dbf03630c316151adfa126732a5ca7f55a711 100644
--- a/gso/services/netbox_client.py
+++ b/gso/services/netbox_client.py
@@ -1,35 +1,27 @@
-"""
-This module contains all methods
-to communicate with the
-NetBox API endpoint: Data Center Infrastructure Main (dcim)
-"""
+"""Contain all methods to communicate with the NetBox API endpoint.Data Center Infrastructure Main (DCIM)."""
 from uuid import UUID
 
 import pydantic
 import pynetbox
+from pynetbox.models.dcim import Devices, DeviceTypes, Interfaces
 
 from gso.products import Router
-from gso.settings import NetBoxParams, load_oss_params
-from gso.utils.device_info import TierInfo, FEASIBLE_LAG_RANGE
-from gso.utils.exceptions import NotFoundError, WorkflowStateException
+from gso.settings import load_oss_params
+from gso.utils.device_info import FEASIBLE_LAG_RANGE, TierInfo
+from gso.utils.exceptions import NotFoundError, WorkflowStateError
 
 
 # Define device models
 class Manufacturer(pydantic.BaseModel):
-    """
-    The device manufacturer.
-    Is mandatory to create a device in netbox.
-    Is needed to define the device type.
-    """
+    """Defines the manufacturer of a device."""
 
     name: str
     slug: str
 
 
 class DeviceType(pydantic.BaseModel):
-    """
-    The device type for a device.
-    Is mandatory to create a device.
+    """Defines the device type.
+
     The manufacturer should be created first to get the manufacturer id,
     which is defined here as int.
     """
@@ -40,38 +32,34 @@ class DeviceType(pydantic.BaseModel):
 
 
 class DeviceRole(pydantic.BaseModel):
-    """
-    The role of a device in netbox.
-    Is mandatory to create a device.
-    """
+    """Defines the role of a device."""
 
     name: str
     slug: str
 
 
 class Site(pydantic.BaseModel):
-    """
-    The site where to place the device.
-    Is mandatory to create a device.
-    """
+    """Defines the site of a device."""
 
     name: str
     slug: str
 
 
 class NetBoxClient:
-    def __init__(self):
+    """Implement all methods to communicate with the NetBox API."""
+
+    def __init__(self) -> None:
         netbox_params = load_oss_params().NETBOX
         self.netbox = pynetbox.api(netbox_params.api, netbox_params.token)
 
-    def get_all_devices(self):
+    def get_all_devices(self) -> list[Devices]:
         return list(self.netbox.dcim.devices.all())
 
-    def get_device_by_name(self, device_name: str):
-        """Returns the device object by name from netbox, or None if not found."""
+    def get_device_by_name(self, device_name: str) -> Devices:
+        """Return the device object by name from netbox, or None if not found."""
         return self.netbox.dcim.devices.get(name=device_name)
 
-    def get_interfaces_by_device(self, device_name: str, speed: str):
+    def get_interfaces_by_device(self, device_name: str, speed: str) -> list[Interfaces]:
         """Get all interfaces of a device by name and speed."""
 
         device = self.get_device_by_name(device_name)
@@ -79,56 +67,41 @@ class NetBoxClient:
             self.netbox.dcim.interfaces.filter(device_id=device.id, enabled=False, mark_connected=False, speed=speed)
         )
 
-    def create_interface(self, iface_name: str, type: str, speed: str, device_name: str) -> dict:
-        """
-        Creates a new interface on
-        a device, where device is defined by name.
+    def create_interface(self, iface_name: str, type: str, speed: str, device_name: str) -> Interfaces:
+        """Create new interface on a device, where device is defined by name.
+
         The type parameter can be 1000base-t, 10gbase-t, lag...
-        For more details on type definidtion have  a look in
-        choises.py in the netbox API implementation in module dcim.
+        For more details on type definition have  a look in
+        choices.py in the netbox API implementation in module DCIM.
         Returns the new interface object as dict.
         """
         device = self.get_device_by_name(device_name)
-
-        new_iface = self.netbox.dcim.interfaces.create(
+        return self.netbox.dcim.interfaces.create(
             name=iface_name, type=type, speed=speed, enabled=False, mark_connected=False, device=device.id
         )
 
-        return dict(new_iface)
-
-    def create_device_type(self, manufacturer: str, model: str, slug: str) -> dict:
-        """Creates a new device type in netbox."""
+    def create_device_type(self, manufacturer: str, model: str, slug: str) -> DeviceTypes:
+        """Create a new device type in netbox."""
 
         # First get manufacturer id
         manufacturer_id = int(self.netbox.dcim.manufacturers.get(name=manufacturer).id)
-        device_type = DeviceType(**{"manufacturer": manufacturer_id, "model": model, "slug": slug})
-
-        # Convert the format from DeviceType to dict
-        device_type = dict(device_type)
-
-        # Create device type
-        device_type = self.netbox.dcim.device_types.create(device_type)
-        return dict(device_type)
+        device_type = DeviceType(**{"manufacturer": manufacturer_id, "model": model, "slug": slug})  # type: ignore
+        return self.netbox.dcim.device_types.create(dict(device_type))
 
-    def create_device_role(self, name: str, slug: str) -> dict:
+    def create_device_role(self, name: str, slug: str) -> DeviceRole:
         device_role = DeviceRole(**{"name": name, "slug": slug})
-        device_role = dict(device_role)
-        device_role = self.netbox.dcim.device_roles.create(device_role)
-        return dict(device_role)
+        return self.netbox.dcim.device_roles.create(dict(device_role))
 
-    def create_device_site(self, name, slug) -> dict:
+    def create_device_site(self, name: str, slug: str) -> Site:
         device_site = Site(**{"name": name, "slug": slug})
-        device_site = self.netbox.dcim.sites.create(dict(device_site))
-        return dict(device_site)
+        return self.netbox.dcim.sites.create(dict(device_site))
 
-    def create_device_manufacturer(self, name: str, slug: str) -> dict:
+    def create_device_manufacturer(self, name: str, slug: str) -> Manufacturer:
         device_manufacturer = Manufacturer(**{"name": name, "slug": slug})
-        device_manufacturer = dict(device_manufacturer)
-        device_manufacturer = self.netbox.dcim.manufacturers.create(device_manufacturer)
-        return dict(device_manufacturer)
+        return self.netbox.dcim.manufacturers.create(dict(device_manufacturer))
 
-    def create_device(self, router_name: str, site_tier: str) -> dict:
-        """Creates a new device in netbox."""
+    def create_device(self, router_name: str, site_tier: str) -> Devices:
+        """Create a new device in netbox."""
 
         # Get device type id
         tier_info = TierInfo().get_module_by_name(f"Tier{site_tier}")
@@ -155,15 +128,15 @@ class NetBoxClient:
                 comments="Installed via pynetbox",
             )
 
-        return dict(device)
+        return device
 
-    def delete_device(self, router_name: str):
+    def delete_device(self, router_name: str) -> None:
         self.netbox.dcim.devices.get(name=router_name).delete()
         return
 
-    def attach_interface_to_lag(self, device_name: str, lag_name: str, iface_name: str) -> dict:
-        """
-        Assign a given interface to a lag.
+    def attach_interface_to_lag(self, device_name: str, lag_name: str, iface_name: str) -> Interfaces:
+        """Assign a given interface to a lag.
+
         Returns the lag object with the assignend interfaces
         """
         # Get device id
@@ -179,11 +152,9 @@ class NetBoxClient:
         iface.lag = lag.id
 
         # Update interface
-        updated_iface = self.netbox.dcim.interfaces.update(iface)
-
-        return dict(updated_iface)
+        return self.netbox.dcim.interfaces.update(iface)
 
-    def reserve_interface(self, device_name: str, iface_name: str) -> dict:
+    def reserve_interface(self, device_name: str, iface_name: str) -> Interfaces:
         """Reserve an interface by enabling it."""
 
         # First get interface from device
@@ -196,15 +167,15 @@ class NetBoxClient:
 
         # Check if interface is reserved
         if interface.enabled:
-            raise WorkflowStateException(f"The interface: {iface_name} on device: {device_name} is already reserved.")
+            raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is already reserved.")
 
         # Reserve interface by enabling it
         interface.enabled = True
         interface.save()
 
-        return dict(interface)
+        return interface
 
-    def allocate_interface(self, device_name: str, iface_name: str) -> dict:
+    def allocate_interface(self, device_name: str, iface_name: str) -> Interfaces:
         """Allocate an interface by marking it as connected."""
 
         device = self.get_device_by_name(device_name)
@@ -216,16 +187,16 @@ class NetBoxClient:
 
         # Check if interface is reserved
         if interface.mark_connected:
-            raise WorkflowStateException(f"The interface: {iface_name} on device: {device_name} is already allocated.")
+            raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is already allocated.")
 
         # allocate interface by mark as connected
         interface.mark_connected = True
         interface.save()
 
-        return dict(interface)
+        return interface
 
     def get_available_lags(self, router_id: UUID) -> list[str]:
-        """Returns all available lags not assigned to a device."""
+        """Return all available lags not assigned to a device."""
 
         router_name = Router.from_subscription(router_id).router.router_fqdn
         device = self.get_device_by_name(router_name)
@@ -238,10 +209,5 @@ class NetBoxClient:
         # Generate all feasible lags
         all_feasible_lags = [f"LAG-{i}" for i in FEASIBLE_LAG_RANGE]
 
-        # Find available lags not assigned to the device
-        available_lags = [lag for lag in all_feasible_lags if lag not in lag_interface_names]
-        return available_lags
-
-
-# if __name__ == "__main__":
-#     print(dict(create_device_manufacturer("Juniper", "juniper")))
+        # Return available lags not assigned to the device
+        return [lag for lag in all_feasible_lags if lag not in lag_interface_names]
diff --git a/gso/utils/device_info.py b/gso/utils/device_info.py
index 47b2a8bed2d08e93debff83e55c28f6399dc2e5f..c4d09ccb823a62de127093d1856f45ecb544594c 100644
--- a/gso/utils/device_info.py
+++ b/gso/utils/device_info.py
@@ -1,5 +1,3 @@
-from typing import Optional
-
 from pydantic import BaseModel
 
 
@@ -12,7 +10,7 @@ class ModuleInfo(BaseModel):
 
 
 class TierInfo:
-    def __init__(self):
+    def __init__(self) -> None:
         self.Tier1 = ModuleInfo(
             device_type="7750-SR7s",
             module_bays_slots=[1, 2],
@@ -28,13 +26,9 @@ class TierInfo:
             total_10g_interfaces=60,
         )
 
-    def get_module_by_name(self, name: str) -> Optional[ModuleInfo]:
-        if name == "Tier1":
-            return self.Tier1
-        elif name == "Tier2":
-            return self.Tier2
-        else:
-            return None
+    def get_module_by_name(self, name: str) -> ModuleInfo:
+        return getattr(self, name)
 
 
+# Ranges of LAGs that are feasible for a given device type.
 FEASIBLE_LAG_RANGE = range(1, 11)
diff --git a/gso/utils/exceptions.py b/gso/utils/exceptions.py
index a11a741fbd09c272a606d7927987ccf5baf7f058..21c127e88b3144d43eb6474e8a890881f36135b0 100644
--- a/gso/utils/exceptions.py
+++ b/gso/utils/exceptions.py
@@ -4,7 +4,7 @@ class NotFoundError(Exception):
     pass
 
 
-class WorkflowStateException(Exception):
+class WorkflowStateError(Exception):
     """Exception raised on problems during workflow."""
 
     pass
diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py
index 403148d26995c813b2fa35790ea7d374219ffb9f..2d28c06e64879a28f3a2d031a42e7a3771705675 100644
--- a/gso/workflows/router/create_router.py
+++ b/gso/workflows/router/create_router.py
@@ -146,22 +146,22 @@ def provision_router_dry(subscription: RouterProvisioning, process_id: UUIDstr,
 def provision_router_real(subscription: RouterProvisioning, process_id: UUIDstr, tt_number: str) -> State:
     provisioning_proxy.provision_router(subscription, process_id, tt_number, False)
 
-    return ({
+    return {
         "subscription": subscription,
         "label_text": (
             "Deployment of base config for a new router. Deployment is being taken care of by the"
             " provisioning proxy, please wait for the results to come back before continuing."
         ),
-    })
+    }
 
 
 @step("Create NetBox Device")
 def create_netbox_device(subscription: RouterProvisioning) -> State:
-    NetBoxClient().create_device(subscription.router.router_fqdn, subscription.router.router_site.site_tier)
+    NetBoxClient().create_device(
+        subscription.router.router_fqdn, subscription.router.router_site.site_tier  # type: ignore
+    )
 
-    return {
-        "subscription": subscription
-    }
+    return {"subscription": subscription}
 
 
 @step("Verify IPAM resources for loopback interface")
diff --git a/requirements.txt b/requirements.txt
index 0bc2c774ad1855686c36de8de63ff16bb55e6547..b103da38a717e01e8c339a38c8e5534d778183e6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,6 @@ orchestrator-core==1.3.0
 requests==2.31.0
 infoblox-client~=0.6.0
 pycountry==22.3.5
-
 pytest==7.4.2
 faker==19.6.2
 responses==0.23.3
@@ -13,4 +12,5 @@ mypy==1.5.1
 ruff==0.0.290
 sphinx==7.2.6
 sphinx-rtd-theme==1.3.0
-urllib3_mock==0.3.3
\ No newline at end of file
+urllib3_mock==0.3.3
+pynetbox==7.2.0
diff --git a/test/conftest.py b/test/conftest.py
index 39dff29c18ca71c53b50d29f8dee86624bace6b9..2bb17b7a4baf57e34ca19bfadcb70f0790cc5786 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -62,7 +62,7 @@ def configuration_data() -> dict:
         s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         yield {
             "GENERAL": {"public_hostname": "https://gap.geant.org"},
-            "RESOURCE_MANAGEMENT": {"todo": "todo"},
+            "NETBOX": {"api": "https://127.0.0.1:8000", "token": "TOKEN"},
             "IPAM": {
                 "INFOBLOX": {
                     "scheme": "https",
diff --git a/utils/netboxcli.py b/utils/netboxcli.py
index 2e5b680bd1b44fdf4ff8ec7b4a416aa8e0f40381..b934f5e7c94b1f43d3692865041bdd02d2af95bf 100644
--- a/utils/netboxcli.py
+++ b/utils/netboxcli.py
@@ -1,91 +1,88 @@
-"""
-Command line tool to communicate with
-the NetBox API
-"""
+"""Command line tool to communicate withthe NetBox API."""
+from typing import Any, Dict, List
+
 import click
 import pandas as pd
 
-from gso.services import netbox_client as nc
 from gso.services.netbox_client import NetBoxClient
 
 
-def convert_to_table(data, fields):
-    if len(data) == 0:
-        print("No data is available for your request")
-        exit()
+def convert_to_table(data: List[Dict[str, Any]], fields: List[str]) -> pd.DataFrame:
+    if not data:
+        raise ValueError("No data is available for your request")
 
     df = pd.DataFrame(data)
-    df = df[fields]  # Selecting specific fields to display
+    if fields:
+        df = df[fields]
+
     return df
 
 
 @click.group()
-def cli():
+def cli() -> None:
     pass
 
 
 @cli.group()
-def create():
+def create() -> None:
     pass
 
 
 @create.command()
-@click.option('--fqdn', prompt='Enter device name', help='Device name')
-@click.option('--model', default="vmx", help='Device model')
-@click.option('--role', default="router", help='Device role')
-@click.option('--site', default="Amsterdam", help='Device role')
-def device(fqdn: str, model: str, role: str, site: str):
-    click.echo(f"Creating device: fqdn={fqdn}, model={model}, role={role}")
+@click.option("--fqdn", prompt="Enter device name", help="Device name")
+@click.option("--model", default="vmx", help="Device model")
+def device(fqdn: str, model: str) -> None:
+    click.echo(f"Creating device: fqdn={fqdn}, model={model}")
     new_device = NetBoxClient().create_device(fqdn, model)
-    print(new_device)
+    click.echo(new_device)
 
 
 @create.command()
-@click.option('--name', help='Interfacename')
-@click.option('--type', default='10gbase-t', help='Interface type, default is 10GBASE-T')
-@click.option('--speed', default='1000', help='Interface speed , default is 1000')
-@click.option('--fqdn', help='Device where to create interface')
-def interface(name: str, type: str, speed: str, fqdn: str):
+@click.option("--name", help="Interfacename")
+@click.option("--type", default="10gbase-t", help="Interface type, default is 10GBASE-T")
+@click.option("--speed", default="1000", help="Interface speed , default is 1000")
+@click.option("--fqdn", help="Device where to create interface")
+def interface(name: str, type: str, speed: str, fqdn: str) -> None:
     click.echo(f"Creating interface: name={name}, speed={speed}, fqdn={fqdn}")
     new_interface = NetBoxClient().create_interface(name, type, speed, fqdn)
-    print(new_interface)
+    click.echo(new_interface)
 
 
 @create.command()
-@click.option('--name', help='Manufacturer name')
-@click.option('--slug', help='Short name for manufacturer')
-def manufacturer(name: str, slug: str):
+@click.option("--name", help="Manufacturer name")
+@click.option("--slug", help="Short name for manufacturer")
+def manufacturer(name: str, slug: str) -> None:
     click.echo(f"Creating manufacturer: name={name}")
     manufacturer = NetBoxClient().create_device_manufacturer(name, slug)
-    print(manufacturer)
+    click.echo(manufacturer)
 
 
 @create.command()
-@click.option('--manufacturer', help='Manufacturer for device')
-@click.option('--model', help='Model for device')
-@click.option('--slug', help='Short name for manufacturer')
-def device_type(manufacturer: str, model: str, slug: str):
+@click.option("--manufacturer", help="Manufacturer for device")
+@click.option("--model", help="Model for device")
+@click.option("--slug", help="Short name for manufacturer")
+def device_type(manufacturer: str, model: str, slug: str) -> None:
     click.echo(f"Creating device type: manufacturer={manufacturer} model = {model}")
     device_type = NetBoxClient().create_device_type(manufacturer, model, slug)
-    print(device_type)
+    click.echo(device_type)
 
 
 @create.command()
-@click.option('--name', help='Name for device role')
-@click.option('--slug', help='Short name for device role')
-def device_role(name: str, slug: str):
+@click.option("--name", help="Name for device role")
+@click.option("--slug", help="Short name for device role")
+def device_role(name: str, slug: str) -> None:
     click.echo(f"Creating device role: name={name}")
     device_role = NetBoxClient().create_device_role(name, slug)
-    print(device_role)
+    click.echo(device_role)
 
 
 @create.command()
-@click.option('--name', help='Name for device site')
-@click.option('--slug', help='Short name for device site')
-def device_site(name: str, slug: str):
+@click.option("--name", help="Name for device site")
+@click.option("--slug", help="Short name for device site")
+def device_site(name: str, slug: str) -> None:
     click.echo(f"Creating device site: name={name}")
     device_site = NetBoxClient().create_device_site(name, slug)
-    print(device_site)
+    click.echo(device_site)
 
 
 create.add_command(device)
@@ -98,14 +95,14 @@ create.add_command(device_site)
 
 # Define list commands here
 @cli.group()
-def list():
+def list() -> None:
     pass
 
 
 @list.command()
-@click.option('--fqdn', help='Device name to list interfaces')
-@click.option('--speed', default="1000", help='Interface speed to list interfaces (default 1000=1G)')
-def interfaces(fqdn: str, speed: str):
+@click.option("--fqdn", help="Device name to list interfaces")
+@click.option("--speed", default="1000", help="Interface speed to list interfaces (default 1000=1G)")
+def interfaces(fqdn: str, speed: str) -> None:
     click.echo(f"Listing all interfaces for: device with fqdn={fqdn}, speed={speed}")
     interface_list = NetBoxClient().get_interfaces_by_device(fqdn, speed)
     display_fields = ["name", "enabled", "mark_connected", "custom_fields", "lag", "speed"]
@@ -114,11 +111,11 @@ def interfaces(fqdn: str, speed: str):
         iface_list.append(dict(iface))
 
     table = convert_to_table(iface_list, display_fields)
-    print(table)
+    click.echo(table)
 
 
 @list.command()
-def devices():
+def devices() -> None:
     click.echo("Listing all devices:")
     device_list = NetBoxClient().get_all_devices()
     display_fields = ["name", "device_type"]
@@ -127,7 +124,7 @@ def devices():
         devices.append(dict(device))
 
     table = convert_to_table(devices, display_fields)
-    print(table)
+    click.echo(table)
 
 
 list.add_command(interfaces)
@@ -136,40 +133,40 @@ list.add_command(devices)
 
 # Define here attach command
 @cli.group()
-def attach():
+def attach() -> None:
     pass
 
 
 @attach.command()
-@click.option('--fqdn', help='Device name where to attach interface to lag')
-@click.option('--iface', help='Interface name to attach to lag')
-@click.option('--lag', help='LAG name to attach interface')
-def interface(fqdn: str, iface: str, lag: str):
+@click.option("--fqdn", help="Device name where to attach interface to lag")
+@click.option("--iface", help="Interface name to attach to lag")
+@click.option("--lag", help="LAG name to attach interface")
+def interface_to_lag(fqdn: str, iface: str, lag: str) -> None:
     click.echo(f"Attaching interface to lag: device ={fqdn}, interface name={iface} to lag={lag}")
     new_iface = NetBoxClient().attach_interface_to_lag(fqdn, lag, iface)
-    print(new_iface)
+    click.echo(new_iface)
 
 
-attach.add_command(interface)
+attach.add_command(interface_to_lag)
 
 
 # The reserve command
 @cli.group()
-def reserve():
+def reserve() -> None:
     pass
 
 
 @reserve.command()
-@click.option('--fqdn', help='Device name where to get interface to reserve')
-@click.option('--iface', help='Interface name to reserve')
-def interface(fqdn: str, iface: str):
+@click.option("--fqdn", help="Device name where to get interface to reserve")
+@click.option("--iface", help="Interface name to reserve")
+def reserve_interface(fqdn: str, iface: str) -> None:
     click.echo(f"Reserving interface: device ={fqdn}, interface name={iface}")
     reserved_iface = NetBoxClient().reserve_interface(fqdn, iface)
-    print(reserved_iface )
+    click.echo(reserved_iface)
 
 
-reserve.add_command(interface)
+reserve.add_command(reserve_interface)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     cli()