diff --git a/gso/services/kentik_client.py b/gso/services/kentik_client.py
index 1a6f7cc00624dd6a541a86b7a16e2f2f318a6c9e..edc1a8611120d32f916d4944711f918e8549f34f 100644
--- a/gso/services/kentik_client.py
+++ b/gso/services/kentik_client.py
@@ -4,13 +4,29 @@ import logging
 from typing import Any
 
 import requests
+from pydantic import BaseModel
+from requests import Response
 
-from gso.products.product_types.router import Router
+from gso.products.product_blocks.site import SiteTier
 from gso.settings import load_oss_params
 
 logger = logging.getLogger(__name__)
 
 
+class NewKentikDevice(BaseModel):
+    """API model for creating a new device in Kentik."""
+
+    device_name: str
+    device_description: str
+    sending_ips: list[str]
+    site_id: int
+    site_tier: SiteTier
+    device_snmp_ip: str
+    device_bgp_flowspec: bool
+    device_bgp_neighbor_ip: str
+    device_bgp_neighbor_ip6: str
+
+
 class KentikClient:
     """The client for Kentik that interacts with an external instance."""
 
@@ -23,19 +39,21 @@ class KentikClient:
             "Content-Type": "application/json",
         }
 
-    def _send_request(self, method, endpoint: str, data: dict[str, Any] | None = None) -> dict[str, Any]:
+    def _send_request(self, method, endpoint: str, data: dict[str, Any] | None = None) -> Response:
         url = self.config.api_base + endpoint
+        logger.debug("Kentik - Sending request", extra={"method": method, "endpoint": url, "form_data": data})
         result = requests.request(method, url, json=data, headers=self.headers)
+        logger.debug("Kentik - Received response", extra=result.__dict__)
 
-        return result.json()
+        return result
 
     def get_devices(self) -> list[dict[str, Any]]:
         """List all devices in Kentik."""
-        return [self._send_request("GET", "v5/devices")]
+        return [self._send_request("GET", "v5/devices").json()]
 
     def get_device(self, device_id: str) -> dict[str, Any]:
         """Get a device by ID."""
-        return self._send_request("GET", f"v5/device/{device_id}")
+        return self._send_request("GET", f"v5/device/{device_id}").json()
 
     def get_device_by_name(self, device_name: str) -> dict[str, Any]:
         """Fetch a device in Kentik by its :term:`FQDN`.
@@ -53,11 +71,11 @@ class KentikClient:
 
     def get_sites(self) -> list[dict[str, Any]]:
         """Get a list of all available sites in Kentik."""
-        return self._send_request("GET", "v5/sites")["sites"]
+        return self._send_request("GET", "v5/sites").json()["sites"]
 
     def get_site(self, site_id: str) -> dict[str, Any]:
         """Get a site by ID."""
-        return self._send_request("GET", f"v5/site/{site_id}")
+        return self._send_request("GET", f"v5/site/{site_id}").json()
 
     def get_site_by_name(self, site_slug: str) -> dict[str, Any]:
         """Get a Kentik site by its name.
@@ -75,7 +93,7 @@ class KentikClient:
 
     def get_plans(self) -> list[dict[str, Any]]:
         """Get all Kentik plans available."""
-        return self._send_request("GET", "v5/plans")["plans"]
+        return self._send_request("GET", "v5/plans").json()["plans"]
 
     def get_plan_by_name(self, plan_name: str) -> dict[str, Any]:
         """Get a Kentik plan by its name.
@@ -91,31 +109,38 @@ class KentikClient:
 
         return {}
 
-    def create_device(self, router: Router) -> dict[str, Any]:
+    def create_device(self, device: NewKentikDevice) -> dict[str, Any]:
         """Add a new device to Kentik."""
-        site_id = self.get_site_by_name(router.router.router_site.site_name)["id"]
-        plan_id = self.get_plan_by_name(self.config.billing_plans[router.router.router_site.site_tier])
+        plan_id = self.get_plan_by_name(self.config.billing_plans[device.site_tier])["id"]
         request_body = {
             "device": {
-                # Route selection missing
-                "deviceName": router.router.router_fqdn,
-                "deviceSubtype": self.config.device_type,
-                "sendingIps": [str(router.router.router_lo_ipv4_address)],
-                "deviceSampleRate": self.config.sample_rate,
-                "planId": plan_id,
-                "siteId": site_id,
-                "deviceSnmpIp": str(router.router.router_lo_ipv4_address),
-                "deviceSnmpCommunity": self.config.snmp_community,
-                "deviceBgpType": self.config.bgp_type,
-                "deviceBgpFlowspec": False,
-                "deviceBgpNeighborIp": str(router.router.router_lo_ipv4_address),
-                "deviceBgpNeighborIp6": str(router.router.router_lo_ipv6_address),
-                "deviceBgpNeighborAsn": str(self.config.ASN),
-                "deviceBgpPassword": self.config.md5_password,
+                **device.model_dump(exclude=set("site_tier")),
+                "device_type": self.config.device_type,
+                "device_subtype": self.config.device_type,
+                "minimize_snmp": self.config.minimize_snmp,
+                "device_sample_rate": self.config.sample_rate,
+                "plan_id": plan_id,
+                "device_snmp_community": self.config.snmp_community,
+                "device_bgp_type": self.config.bgp_type,
+                "bgp_lookup_strategy": self.config.bgp_lookup_strategy,
+                "device_bgp_neighbor_asn": str(self.config.ASN),
+                "device_bgp_password": self.config.md5_password,
             }
         }
 
-        return self._send_request("POST", "v5/device", request_body)
+        return self._send_request("POST", "v5/device", request_body).json()
+
+    def update_device(self, device_id: str, updated_device: dict[str, Any]) -> dict[str, Any]:
+        """Update an existing device in Kentik."""
+        return self._send_request("PUT", f"v5/device/{device_id}", updated_device).json()
+
+    def remove_device(self, device_id: str, *, archive: bool = True) -> None:
+        """Remove a device from Kentik.
+
+        :param str device_id: The Kentik internal ID of the device that is to be removed.
+        :param bool archive: Archive the device instead of completely deleting it.
+        """
+        if not archive:
+            self._send_request("DELETE", f"v5/device/{device_id}")
 
-    def remove_device(self, hostname: str) -> None:
-        """Remove a device from Kentik."""
+        self._send_request("DELETE", f"v5/device/{device_id}")