diff --git a/backend/api_test.go b/backend/api_test.go
index 40aab9c..597d14c 100644
--- a/backend/api_test.go
+++ b/backend/api_test.go
@@ -5,7 +5,7 @@ import (
 )
 import "github.com/gavv/httpexpect/v2"
 
-func startServer(t *testing.T) {
+func startServer(t *testing.T) *httpexpect.Expect {
 	config := ServerConfig{
 		Datasource: ":memory:",
 		Port:       "8181",
@@ -13,13 +13,30 @@ func startServer(t *testing.T) {
 	}
 	go start(t.Context(), &config)
 	<-config.Started
+	return httpexpect.Default(t, "http://localhost:8181/api")
 }
 
 func TestGetUsers(t *testing.T) {
-	startServer(t)
-	e := httpexpect.Default(t, "http://localhost:8181/api")
+	e := startServer(t)
 	result := e.GET("/users").Expect().Status(200).JSON()
 	result.Array().Length().IsEqual(2)
 	result.Path("$[0].name").InList("Seeseemelk", "Huffle")
 	result.Path("$[1].name").InList("Seeseemelk", "Huffle")
 }
+
+func TestGetUser(t *testing.T) {
+	e := startServer(t)
+	result := e.GET("/user/1").Expect().Status(200).JSON().Object()
+	result.Value("name").IsEqual("Seeseemelk")
+	result.Value("id").IsEqual(1)
+}
+
+func TestGetUserUnknown(t *testing.T) {
+	e := startServer(t)
+	e.GET("/user/999").Expect().Status(404)
+}
+
+func TestGetUserBadId(t *testing.T) {
+	e := startServer(t)
+	e.GET("/user/bad-id").Expect().Status(400)
+}
diff --git a/backend/db.go b/backend/db.go
index 98ead12..b479b8a 100644
--- a/backend/db.go
+++ b/backend/db.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"errors"
 	"gitea.seeseepuff.be/seeseemelk/mysqlite"
 	"log"
 )
@@ -42,3 +43,17 @@ func (db *Db) GetUsers() ([]User, error) {
 	}
 	return users, nil
 }
+
+func (db *Db) GetUser(id int) (*User, error) {
+	user := &User{}
+
+	err := db.db.Query("select id, name from users where id = ?").
+		Bind(id).ScanSingle(&user.ID, &user.Name)
+	if errors.Is(err, mysqlite.ErrNoRows) {
+		return nil, nil
+	}
+	if err != nil {
+		return nil, err
+	}
+	return user, nil
+}
diff --git a/backend/go.mod b/backend/go.mod
index fadfbae..55f7dee 100644
--- a/backend/go.mod
+++ b/backend/go.mod
@@ -3,7 +3,7 @@ module allowance_planner
 go 1.24.2
 
 require (
-	gitea.seeseepuff.be/seeseemelk/mysqlite v0.9.0
+	gitea.seeseepuff.be/seeseemelk/mysqlite v0.10.0
 	github.com/gavv/httpexpect/v2 v2.17.0
 	github.com/gin-gonic/gin v1.10.0
 )
diff --git a/backend/go.sum b/backend/go.sum
index 52f8d93..8942a76 100644
--- a/backend/go.sum
+++ b/backend/go.sum
@@ -1,5 +1,5 @@
-gitea.seeseepuff.be/seeseemelk/mysqlite v0.9.0 h1:GaU2DSrgDfZEqST3HdnNgfKSI4sNXvMm8SSfeMvBxA4=
-gitea.seeseepuff.be/seeseemelk/mysqlite v0.9.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE=
+gitea.seeseepuff.be/seeseemelk/mysqlite v0.10.0 h1:xvbSZvLcHWlt+P4SE7vcgw3kih0kLrCqkOo/eXlbcSg=
+gitea.seeseepuff.be/seeseemelk/mysqlite v0.10.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE=
 github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4=
 github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w=
 github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
diff --git a/backend/main.go b/backend/main.go
index 4c3454e..295e717 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -8,6 +8,7 @@ import (
 	"log"
 	"net/http"
 	"os"
+	"strconv"
 )
 
 //go:embed migrations/*.sql
@@ -30,18 +31,36 @@ func getUsers(c *gin.Context) {
 	c.IndentedJSON(http.StatusOK, users)
 }
 
-func main() {
-	config := ServerConfig{
-		Datasource: os.Getenv("DB_PATH"),
+func getUser(c *gin.Context) {
+	userIdStr := c.Param("userId")
+	userId, err := strconv.Atoi(userIdStr)
+	if err != nil {
+		log.Printf("Invalid user ID: %v", err)
+		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
+		return
 	}
-	start(context.Background(), &config)
+
+	user, err := db.GetUser(userId)
+	if err != nil {
+		log.Printf("Error getting user: %v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error"})
+		return
+	}
+	if user == nil {
+		c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
+		return
+	}
+
+	c.IndentedJSON(http.StatusOK, user)
 }
 
 func start(ctx context.Context, config *ServerConfig) {
 	db = NewDb(config.Datasource)
 	defer db.db.MustClose()
+
 	router := gin.Default()
 	router.GET("/api/users", getUsers)
+	router.GET("/api/user/:userId", getUser)
 
 	srv := &http.Server{
 		Addr:    ":" + config.Port,
@@ -61,3 +80,10 @@ func start(ctx context.Context, config *ServerConfig) {
 		log.Fatalf("Server forced to shutdown: %v", err)
 	}
 }
+
+func main() {
+	config := ServerConfig{
+		Datasource: os.Getenv("DB_PATH"),
+	}
+	start(context.Background(), &config)
+}