diff --git a/hostd/src/api.rs b/hostd/src/api.rs
index edc0fcc..7f68d70 100644
--- a/hostd/src/api.rs
+++ b/hostd/src/api.rs
@@ -5,11 +5,13 @@ use std::sync::Arc;
 
 use crate::context::ControllerContext;
 use crate::machine;
+use crate::sysupdate;
 
 type ControllerApiDescription = ApiDescription<Arc<ControllerContext>>;
 
 pub fn api() -> Result<ControllerApiDescription> {
     let mut api = ControllerApiDescription::new();
     api.register(machine::describe)?;
+    api.register(sysupdate::list_versions)?;
     Ok(api)
 }
diff --git a/hostd/src/context.rs b/hostd/src/context.rs
index 8380c40..de20783 100644
--- a/hostd/src/context.rs
+++ b/hostd/src/context.rs
@@ -1,11 +1,9 @@
-use zbus::Connection;
-
 pub struct ControllerContext {
-    pub dbus: Connection,
+    pub dbus: zbus::Connection,
 }
 
 impl ControllerContext {
-    pub fn new(dbus: Connection) -> ControllerContext {
+    pub fn new(dbus: zbus::Connection) -> ControllerContext {
         ControllerContext { dbus }
     }
 }
diff --git a/hostd/src/lib.rs b/hostd/src/lib.rs
index 94f3a31..3b7a5eb 100644
--- a/hostd/src/lib.rs
+++ b/hostd/src/lib.rs
@@ -1,3 +1,4 @@
 pub mod api;
 pub mod context;
 pub mod machine;
+pub mod sysupdate;
diff --git a/hostd/src/machine.rs b/hostd/src/machine.rs
index 57e4440..a2926c2 100644
--- a/hostd/src/machine.rs
+++ b/hostd/src/machine.rs
@@ -29,7 +29,9 @@ pub async fn describe(
     let machine_id = hostnamed
         .machine_id()
         .await
-        .unwrap()
+        .map_err(|e| match e {
+            err => HttpError::for_internal_error(format!("Error: {}", err)),
+        })?
         // convert bytes to hex string
         .iter()
         .map(|&b| format!("{:02x}", b))
@@ -37,8 +39,5 @@ pub async fn describe(
 
     let machine_info = MachineInfo { machine_id };
 
-    tracing::info_span!("Hello, span hostd!");
-
-    tracing::info!(monotonic_counter.version_calls = 1);
     Ok(HttpResponseOk(machine_info))
 }
diff --git a/hostd/src/sysupdate.rs b/hostd/src/sysupdate.rs
new file mode 100644
index 0000000..43873cd
--- /dev/null
+++ b/hostd/src/sysupdate.rs
@@ -0,0 +1,52 @@
+use dropshot::{endpoint, HttpError, HttpResponseOk, RequestContext};
+use schemars::JsonSchema;
+use serde::Serialize;
+use std::sync::Arc;
+use trace_request::trace_request;
+
+use crate::context::ControllerContext;
+
+const SYSUPDATE_HOST_PATH: &str = "/org/freedesktop/sysupdate1/target/host";
+
+#[derive(Serialize, JsonSchema)]
+#[serde(rename_all = "camelCase")]
+struct SysUpdate {
+    current_version: String,
+    versions: Vec<String>,
+}
+
+#[endpoint {
+    method = GET,
+    path = "/list_versions",
+}]
+#[trace_request]
+pub async fn list_versions(
+    rqctx: RequestContext<Arc<ControllerContext>>,
+) -> Result<HttpResponseOk<SysUpdate>, HttpError> {
+    let sysupdate_target = zbus_systemd::sysupdate1::TargetProxy::builder(&rqctx.context().dbus)
+        .path(SYSUPDATE_HOST_PATH)
+        .unwrap()
+        .build()
+        .await
+        .map_err(|e| match e {
+            err => HttpError::for_internal_error(format!("Error: {}", err)),
+        })?;
+
+    let versions = sysupdate_target.list(0).await.map_err(|e| match e {
+        err => {
+            println!("Error: {}", err);
+            HttpError::for_internal_error(format!("Error: {}", err))
+        }
+    })?;
+
+    let current_version = sysupdate_target.get_version().await.map_err(|e| match e {
+        err => HttpError::for_internal_error(format!("Error: {}", err)),
+    })?;
+
+    let sysupdate = SysUpdate {
+        versions,
+        current_version,
+    };
+
+    Ok(HttpResponseOk(sysupdate))
+}