diff --git a/main/main.go b/main/main.go
index 11db3bbf04ece07fc559c37582cb91ed74e8b674..d134b2b81a47e18a46fd18048b839053afddd00b 100644
--- a/main/main.go
+++ b/main/main.go
@@ -31,7 +31,10 @@ func main() {
 	router.HandleFunc("/health", handler.Health).Methods("GET")
 	router.HandleFunc("/campaign", handler.CreateCampaign).Methods("POST")
 	router.HandleFunc("/campaigns", handler.GetCampaigns).Methods("GET")
-	router.HandleFunc("/campaign/{id}", handler.GetCampaign2).Methods("GET")
+	router.HandleFunc("/campaigns/{id}", handler.GetCampaign).Methods("GET")
+	router.HandleFunc("/campaigns/{id}", handler.DeleteCampaign).Methods("DELETE")
+	router.HandleFunc("/campaigns/{id}", handler.UpdateCampaign).Methods("PUT")
+	router.HandleFunc("/campaigns/{id}/donation", handler.AddDonation).Methods("POST")
 	if err := http.ListenAndServe(":8000", router); err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/myaktion/handler/campaign.go b/src/myaktion/handler/campaign.go
index 3315e491ce72cfeac923aec1674edf1f2cf5660c..936d94963f2ae0d4ac998a858d3948fe11c39f8e 100644
--- a/src/myaktion/handler/campaign.go
+++ b/src/myaktion/handler/campaign.go
@@ -11,14 +11,13 @@ import (
 )
 
 func CreateCampaign(w http.ResponseWriter, r *http.Request) {
-	var campaign *model.Campaign
-	campaign, err := GetCampaign(r)
+	campaign, err := getCampaign(r)
 	if err != nil {
 		http.Error(w, err.Error(), http.StatusBadRequest)
 		return
 	}
-	if err := service.CreateCampaign(campaign); err != nil {
-		log.Errorf("Error calling service CreateCampaign: %v", err)
+	if err = service.CreateCampaign(campaign); err != nil {
+		log.Printf("Error calling service CreateCampaign: %v", err)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
@@ -28,37 +27,81 @@ func CreateCampaign(w http.ResponseWriter, r *http.Request) {
 func GetCampaigns(w http.ResponseWriter, _ *http.Request) {
 	campaigns, err := service.GetCampaigns()
 	if err != nil {
-		log.Errorf("Error calling service GetCampaigns: %v", err)
+		log.Printf("Error calling service GetCampaigns: %v", err)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	sendJson(w, campaigns)
 }
 
-func GetCampaign(r *http.Request) (*model.Campaign, error) {
-	var campaign model.Campaign
-	err := json.NewDecoder(r.Body).Decode(&campaign)
+func GetCampaign(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
 	if err != nil {
-		log.Errorf("Can't serialize request body to campaign struct: %v", err)
-		return nil, err
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
 	}
-	return &campaign, nil
+	campaign, err := service.GetCampaign(id)
+	if err != nil {
+		log.Errorf("Failure retrieving campaign with ID %v: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if campaign == nil {
+		http.Error(w, "404 campaign not found", http.StatusNotFound)
+		return
+	}
+	sendJson(w, campaign)
 }
 
-func GetCampaign2(w http.ResponseWriter, r *http.Request) {
-	id, idErr := getId(r)
-	if idErr != nil {
-		log.Errorf("Error calling service getId: %v", idErr)
-		http.Error(w, idErr.Error(), http.StatusInternalServerError)
+func UpdateCampaign(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
 		return
 	}
+	campaign, err := getCampaign(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	campaign, err = service.UpdateCampaign(id, campaign)
+	if err != nil {
+		log.Errorf("Failure updating campaign with ID %v: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if campaign == nil {
+		http.Error(w, "404 campaign not found", http.StatusNotFound)
+		return
+	}
+	sendJson(w, campaign)
+}
 
-	resCampaign, err := service.GetCampaign2(id)
+func DeleteCampaign(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
 	if err != nil {
-		log.Errorf("Error calling service GetCampaign: %v", err)
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	campaign, err := service.DeleteCampaign(id)
+	if err != nil {
+		log.Errorf("Failure deleting campaign with ID %v: %v", id, err)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
-	log.Infof("Campaign with the ID %v was printed", resCampaign.ID)
-	sendJson(w, resCampaign)
+	if campaign == nil {
+		http.Error(w, "404 campaign not found", http.StatusNotFound)
+		return
+	}
+	sendJson(w, result{Success: "OK"})
+}
+
+func getCampaign(r *http.Request) (*model.Campaign, error) {
+	var campaign model.Campaign
+	err := json.NewDecoder(r.Body).Decode(&campaign)
+	if err != nil {
+		log.Errorf("Can't serialize request body to campaign struct: %v", err)
+		return nil, err
+	}
+	return &campaign, nil
 }
diff --git a/src/myaktion/handler/donation.go b/src/myaktion/handler/donation.go
new file mode 100644
index 0000000000000000000000000000000000000000..b7c4a6faa60f007690f52b627335b99a7a9acc57
--- /dev/null
+++ b/src/myaktion/handler/donation.go
@@ -0,0 +1,42 @@
+package handler
+
+import (
+	"encoding/json"
+	"net/http"
+
+	log "github.com/sirupsen/logrus"
+
+	"gitlab.reutlingen-university.de/albrecht/myaktion-go/src/myaktion/model"
+	"gitlab.reutlingen-university.de/albrecht/myaktion-go/src/myaktion/service"
+)
+
+func AddDonation(w http.ResponseWriter, r *http.Request) {
+	id, err := getId(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	donation, err := getDonation(r)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	// TODO: if the campaign doesn't exist, return 404 - don't show FK error
+	err = service.AddDonation(id, donation)
+	if err != nil {
+		log.Errorf("Failure adding donation to campaign with ID %v: %v", id, err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	sendJson(w, donation)
+}
+
+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/service/campaign.go b/src/myaktion/service/campaign.go
index 61eb1f6090e4b7b38b0bccd16f9c8ac67ef374a4..04115b69197748b1ebf29a6326b23b308e8269a5 100644
--- a/src/myaktion/service/campaign.go
+++ b/src/myaktion/service/campaign.go
@@ -1,7 +1,7 @@
 package service
 
 import (
-	"errors"
+	"fmt"
 
 	log "github.com/sirupsen/logrus"
 
@@ -21,8 +21,8 @@ func CreateCampaign(campaign *model.Campaign) error {
 	campaign.ID = actCampaignId
 	campaignStore[actCampaignId] = campaign
 	actCampaignId += 1
-	log.Infof("Successfully stored new campaign with ID %v in database.", campaign.ID)
-	log.Tracef("Stored: %v", campaign)
+	log.Printf("Successfully stored new campaign with ID %v in database.", campaign.ID)
+	log.Printf("Stored: %v", campaign)
 	return nil
 }
 
@@ -31,19 +31,41 @@ func GetCampaigns() ([]model.Campaign, error) {
 	for _, campaign := range campaignStore {
 		campaigns = append(campaigns, *campaign)
 	}
-	log.Tracef("Retrieved: %v", campaigns)
 	return campaigns, nil
 }
 
-func GetCampaign2(requestedID uint) (model.Campaign, error) {
-	var resCampaign model.Campaign
-	for _, campaign := range campaignStore {
-		if campaign.ID == requestedID {
-			resCampaign = *campaign
-			log.Tracef("Retrieved: %v", resCampaign)
+func GetCampaign(id uint) (*model.Campaign, error) {
+	campaign := campaignStore[id]
+	if campaign == nil {
+		return nil, fmt.Errorf("no campaign with ID %d", id)
+	}
+	log.Tracef("Retrieved: %v", campaign)
+	return campaign, nil
+}
+
+func UpdateCampaign(id uint, campaign *model.Campaign) (*model.Campaign, error) {
+	existingCampaign, err := GetCampaign(id)
+	if err != nil {
+		return existingCampaign, err
+	}
+	existingCampaign.Name = campaign.Name
+	existingCampaign.OrganizerName = campaign.OrganizerName
+	existingCampaign.TargetAmount = campaign.TargetAmount
+	existingCampaign.DonationMinimum = campaign.DonationMinimum
+	entry := log.WithField("ID", id)
+	entry.Info("Successfully updated campaign.")
+	entry.Tracef("Updated: %v", campaign)
+	return existingCampaign, nil
+}
 
-			return resCampaign, nil
-		}
+func DeleteCampaign(id uint) (*model.Campaign, error) {
+	campaign, err := GetCampaign(id)
+	if err != nil {
+		return campaign, err
 	}
-	return resCampaign, errors.New("keine Campaign mit der ID wurde gefunden")
+	delete(campaignStore, id)
+	entry := log.WithField("ID", id)
+	entry.Info("Successfully deleted campaign.")
+	entry.Tracef("Deleted: %v", campaign)
+	return campaign, nil
 }
diff --git a/src/myaktion/service/donation.go b/src/myaktion/service/donation.go
new file mode 100644
index 0000000000000000000000000000000000000000..32c19a96ac4529762eed9bb038c8bba6122f7642
--- /dev/null
+++ b/src/myaktion/service/donation.go
@@ -0,0 +1,19 @@
+package service
+
+import (
+	log "github.com/sirupsen/logrus"
+
+	"gitlab.reutlingen-university.de/albrecht/myaktion-go/src/myaktion/model"
+)
+
+func AddDonation(campaignId uint, donation *model.Donation) error {
+	campaign, err := GetCampaign(campaignId)
+	if err != nil {
+		return err
+	}
+	campaign.Donations = append(campaign.Donations, *donation)
+	entry := log.WithField("ID", campaignId)
+	entry.Info("Successfully added new donation to campaign.")
+	entry.Tracef("Stored: %v", donation)
+	return nil
+}