diff --git a/src/myaktion/handler/campaign.go b/src/myaktion/handler/campaign.go
index 3ca57ede6201dd7772ddcc25b68fc7b21b047af3..cfacb25aafd357ed698c1f83955654c215ce3be4 100644
--- a/src/myaktion/handler/campaign.go
+++ b/src/myaktion/handler/campaign.go
@@ -36,6 +36,79 @@ func GetCampaigns(w http.ResponseWriter, r *http.Request) {
 	sendJson(w, campaigns)
 }
 
+func GetCampaign(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
+	if err != nil {
+		log.Errorf("Failed to extract ID from request: %v", err)
+		http.Error(w, "Invalid campaign ID", http.StatusBadRequest)
+		return
+	}
+	campaign, err := service.GetCampaignByID(id)
+	if err != nil {
+		log.Errorf("Error retrieving campaign with ID %d: %v", id, err)
+		http.Error(w, "Campaign not found", http.StatusNotFound)
+		return
+	}
+	sendJson(w, campaign)
+}
+
+func UpdateCampaign(w http.ResponseWriter, r *http.Request) {
+	var campaign *model.Campaign
+	campaign, err := getCampaign(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	id, err := getId(r)
+	if err != nil {
+		log.Errorf("Failed to extract ID from request: %v", err)
+		http.Error(w, "Invalid campaign ID", http.StatusBadRequest)
+		return
+	}
+	campaign.ID = id
+	if err := service.UpdateCampaign(campaign); err != nil {
+		log.Errorf("Error updating campaign with ID %d: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	sendJson(w, campaign)
+}
+
+func DeleteCampaign(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
+	if err != nil {
+		log.Errorf("Failed to extract ID from request: %v", err)
+		http.Error(w, "Invalid campaign ID", http.StatusBadRequest)
+		return
+	}
+	if err := service.DeleteCampaign(id); err != nil {
+		log.Errorf("Error deleting campaign with ID %d: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	sendJson(w, result{Success: "Campaign deleted successfully"})
+}
+
+func AddDonation(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
+	if err != nil {
+		log.Errorf("Failed to extract ID from request: %v", err)
+		http.Error(w, "Invalid campaign ID", http.StatusBadRequest)
+		return
+	}
+	donation, err := getDonation(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	if err := service.AddDonation(id, donation); err != nil {
+		log.Errorf("Error adding donation to campaign with ID %d: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	sendJson(w, donation)
+}
+
 func getCampaign(r *http.Request) (*model.Campaign, error) {
 	var campaign model.Campaign
 	err := json.NewDecoder(r.Body).Decode(&campaign)
@@ -45,3 +118,13 @@ func getCampaign(r *http.Request) (*model.Campaign, error) {
 	}
 	return &campaign, nil
 }
+
+func getDonation(r *http.Request) (*model.Donation, error) {
+	var donation model.Donation
+	err := json.NewDecoder(r.Body).Decode(&donation)
+	if err != nil {
+		log.Errorf("Can't serialize request body to donation struct: %v", err)
+		return nil, err
+	}
+	return &donation, nil
+}
diff --git a/src/myaktion/main.go b/src/myaktion/main.go
index 6f7c8729c8c70f406b09d0e3263d5ae5ef1c4461..fd0f6512a83f9d27afdc1f58cace3567f40f32c0 100644
--- a/src/myaktion/main.go
+++ b/src/myaktion/main.go
@@ -30,6 +30,10 @@ func main() {
 	router.HandleFunc("/health", handler.Health).Methods("GET")
 	router.HandleFunc("/campaigns", handler.CreateCampaign).Methods("POST")
 	router.HandleFunc("/campaigns", handler.GetCampaigns).Methods("GET")
+	router.HandleFunc("/campaigns/{id}", handler.GetCampaign).Methods("GET")
+	router.HandleFunc("/campaigns/{id}", handler.UpdateCampaign).Methods("PUT")
+	router.HandleFunc("/campaigns/{id}", handler.DeleteCampaign).Methods("DELETE")
+	router.HandleFunc("/campaigns/{id}/donations", handler.AddDonation).Methods("POST")
 	if err := http.ListenAndServe(":8000", router); err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/myaktion/model/campaign.go b/src/myaktion/model/campaign.go
index 0451a19803b2109250372746d18f92758e4e25ee..47c8cd42fe5da7b724635ac643e28185e95933e3 100644
--- a/src/myaktion/model/campaign.go
+++ b/src/myaktion/model/campaign.go
@@ -9,6 +9,6 @@ type Campaign struct {
 	TargetAmount       float64    `gorm:"notNull;check:target_amount >= 10.0"`
 	DonationMinimum    float64    `gorm:"notNull;check:donation_minimum >= 1.0"`
 	AmountDonatedSoFar float64    `gorm:"-"`
-	Donation           []Donation `gorm:"foreignKey:CampaignID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
+	Donations          []Donation `gorm:"foreignKey:CampaignID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
 	Account            Account    `gorm:"embedded;embeddedPrefix:account_"`
 }
diff --git a/src/myaktion/scripts/start-mariadb.sh b/src/myaktion/scripts/start-mariadb.sh
index 2cd94cb5654af05956fbe4b8a9185349ee1ba765..d85a08b2ccb04cb3badb1ee9eedf7b47e895d9c6 100644
--- a/src/myaktion/scripts/start-mariadb.sh
+++ b/src/myaktion/scripts/start-mariadb.sh
@@ -1,2 +1,7 @@
  #!/usr/bin/env bash
- docker run -d -p 3306:3306 --name database -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=myaktion mariadb:10.5
\ No newline at end of file
+ docker run -d -p 3306:3306 --name database -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=myaktion mariadb:10.5
+
+# docker exec -it database /bin/bash (or use Docker Desktop)
+# mysql -u root -p (then enter 'root')
+# USE myaktion;
+# SHOW TABLES; DESCRIBE <table_name>; SELECT * FROM <table_name>; ...
\ No newline at end of file
diff --git a/src/myaktion/service/campaign.go b/src/myaktion/service/campaign.go
index 68ceaebacc3fa78e377d1bc679ca7385a1a38121..7e73ec4fdf4d2b14de3e0a0473f14f3b3df4e85b 100644
--- a/src/myaktion/service/campaign.go
+++ b/src/myaktion/service/campaign.go
@@ -26,3 +26,43 @@ func GetCampaigns() ([]model.Campaign, error) {
 	log.Tracef("Retrived: %v", campaigns)
 	return campaigns, nil
 }
+
+func GetCampaignByID(id uint) (*model.Campaign, error) {
+	var campaign model.Campaign
+	result := db.DB.Preload("Donations").First(&campaign, id)
+	if result.Error != nil {
+		return nil, result.Error
+	}
+	log.Tracef("Retrived: %v", campaign)
+	return &campaign, nil
+}
+
+func UpdateCampaign(campaign *model.Campaign) error {
+	result := db.DB.Save(campaign)
+	if result.Error != nil {
+		return result.Error
+	}
+	log.Infof("Successfully updated campaign with ID %v in database.", campaign.ID)
+	log.Tracef("Updated: %v", campaign)
+	return nil
+}
+
+func DeleteCampaign(id uint) error {
+	result := db.DB.Delete(&model.Campaign{}, id)
+	if result.Error != nil {
+		return result.Error
+	}
+	log.Infof("Successfully deleted campaign with ID %v from database.", id)
+	return nil
+}
+
+func AddDonation(campaignID uint, donation *model.Donation) error {
+	donation.CampaignID = campaignID
+	result := db.DB.Create(donation)
+	if result.Error != nil {
+		return result.Error
+	}
+	log.Infof("Successfully stored new donation with ID %v in database.", donation.ID)
+	log.Tracef("Stored: %v", donation)
+	return nil
+}