diff --git a/internal/db/db.go b/internal/db/db.go
index 7dc34d2df19e50c0c329cded5937f492733fa74c..8cc412bc340dc439868564185bddca567e9a1dd6 100644
--- a/internal/db/db.go
+++ b/internal/db/db.go
@@ -131,12 +131,13 @@ func RunWithinTransaction(rlog log.Ext1FieldLogger, tx *sqlx.Tx, fn func(*sqlx.T
 }
 
 // ParseError parses the passed error for a sql.ErrNoRows
-func ParseError(err error) (bool, error) {
-	if err == nil {
-		return true, nil
+func ParseError(e error) (found bool, err error) {
+	if e == nil {
+		found = true
+		return
 	}
-	if errors.Is(err, sql.ErrNoRows) {
-		err = nil
+	if !errors.Is(err, sql.ErrNoRows) {
+		err = e
 	}
-	return false, err
+	return
 }
diff --git a/internal/endpoints/notification/calendar/calendar.go b/internal/endpoints/notification/calendar/calendar.go
index a3ef84799c8fa5a253150130f4c8defb58a4eea3..e0d03777c0350bd05a7ef6641f934b8b908dce5c 100644
--- a/internal/endpoints/notification/calendar/calendar.go
+++ b/internal/endpoints/notification/calendar/calendar.go
@@ -37,10 +37,6 @@ import (
 	"github.com/oidc-mytoken/server/internal/utils/logger"
 )
 
-//TODO events from eventservice
-
-//TODO not found errors
-
 // HandleGetICS returns a calendar ics by its id
 func HandleGetICS(ctx *fiber.Ctx) error {
 	rlog := logger.GetRequestLogger(ctx)
@@ -48,7 +44,11 @@ func HandleGetICS(ctx *fiber.Ctx) error {
 	cid := ctx.Params("id")
 	info, err := calendarrepo.GetByID(rlog, nil, cid)
 	if err != nil {
-		return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
+		_, e := db.ParseError(err)
+		if e != nil {
+			return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
+		}
+		return model.NotFoundErrorResponse("calendar not found").Send(ctx)
 	}
 	ctx.Set(fiber.HeaderContentType, "text/calendar")
 	ctx.Set(fiber.HeaderContentDisposition, fmt.Sprintf(`attachment; filename="%s"`, info.Name))
@@ -115,7 +115,16 @@ func HandleAdd(ctx *fiber.Ctx) error {
 				resData.TokenUpdate = tokenUpdate
 				res.Response = resData
 			}
-			return usedRestriction.UsedOther(rlog, tx, mt.ID)
+			if err = usedRestriction.UsedOther(rlog, tx, mt.ID); err != nil {
+				return err
+			}
+			return eventService.LogEvent(
+				rlog, tx, eventService.MTEvent{
+					Event: eventpkg.FromNumber(eventpkg.CalendarCreated, calendarInfo.Name),
+					MTID:  mt.ID,
+				},
+				*ctxutils.ClientMetaData(ctx),
+			)
 		},
 	); err != nil {
 		return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
@@ -162,7 +171,16 @@ func HandleDelete(ctx *fiber.Ctx) error {
 					Cookies: []*fiber.Cookie{cookies.MytokenCookie(tokenUpdate.Mytoken)},
 				}
 			}
-			return usedRestriction.UsedOther(rlog, tx, mt.ID)
+			if err = usedRestriction.UsedOther(rlog, tx, mt.ID); err != nil {
+				return err
+			}
+			return eventService.LogEvent(
+				rlog, tx, eventService.MTEvent{
+					Event: eventpkg.FromNumber(eventpkg.CalendarDeleted, name),
+					MTID:  mt.ID,
+				},
+				*ctxutils.ClientMetaData(ctx),
+			)
 		},
 	); err != nil {
 		return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
@@ -187,7 +205,11 @@ func HandleGet(ctx *fiber.Ctx) error {
 	}
 	info, err := calendarrepo.Get(rlog, nil, mt.ID, calendarName)
 	if err != nil {
-		return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
+		_, e := db.ParseError(err)
+		if e != nil {
+			return model.ErrorToInternalServerErrorResponse(err).Send(ctx)
+		}
+		return model.NotFoundErrorResponse("calendar not found").Send(ctx)
 	}
 	return ctx.Redirect(info.ICSPath)
 }
@@ -234,7 +256,16 @@ func HandleList(ctx *fiber.Ctx) error {
 				resData.TokenUpdate = tokenUpdate
 				res.Response = resData
 			}
-			return usedRestriction.UsedOther(rlog, tx, mt.ID)
+			if err = usedRestriction.UsedOther(rlog, tx, mt.ID); err != nil {
+				return err
+			}
+			return eventService.LogEvent(
+				rlog, tx, eventService.MTEvent{
+					Event: eventpkg.FromNumber(eventpkg.CalendarListed, ""),
+					MTID:  mt.ID,
+				},
+				*ctxutils.ClientMetaData(ctx),
+			)
 		},
 	)
 	return res.Send(ctx)
@@ -253,9 +284,7 @@ func HandleCalendarEntryViaMail(ctx *fiber.Ctx) error {
 	}
 
 	var req pkg.AddMytokenToCalendarRequest
-	fmt.Println(string(ctx.Body()))
 	if err := errors.WithStack(ctx.BodyParser(&req)); err != nil {
-		fmt.Println(errorfmt.Full(err))
 		return model.ErrorToBadRequestErrorResponse(err).Send(ctx)
 	}
 
@@ -412,7 +441,11 @@ func HandleAddMytoken(ctx *fiber.Ctx) error {
 		rlog, func(tx *sqlx.Tx) error {
 			info, err := calendarrepo.Get(rlog, tx, id, calendarName)
 			if err != nil {
-				res = model.ErrorToInternalServerErrorResponse(err)
+				_, e := db.ParseError(err)
+				if e != nil {
+					res = model.ErrorToInternalServerErrorResponse(err)
+				}
+				res = model.NotFoundErrorResponse("calendar not found")
 				return err
 			}
 			if err = calendarrepo.AddMytokenToCalendar(rlog, tx, id, info.ID); err != nil {
diff --git a/internal/model/response.go b/internal/model/response.go
index 06898711e89d4c5203ad671e3334a088d3ffc801..a98ac49a604609d27e01fcdea1e21862cdcbbeca 100644
--- a/internal/model/response.go
+++ b/internal/model/response.go
@@ -45,6 +45,17 @@ func ErrorToBadRequestErrorResponse(err error) *Response {
 	}
 }
 
+// NotFoundErrorResponse returns a error response for a not found error
+func NotFoundErrorResponse(msg string) *Response {
+	return &Response{
+		Status: fiber.StatusNotFound,
+		Response: api.Error{
+			Error:            "not_found",
+			ErrorDescription: msg,
+		},
+	}
+}
+
 // ResponseNYI is the server response when something is not yet implemented
 var ResponseNYI = Response{
 	Status:   fiber.StatusNotImplemented,
diff --git a/internal/mytoken/event/pkg/event.go b/internal/mytoken/event/pkg/event.go
index 7e8f6510b858553a2064ac6d8799ec79edda77a3..8591215b9d54a39152f8d595d1ab0941399bbfa2 100644
--- a/internal/mytoken/event/pkg/event.go
+++ b/internal/mytoken/event/pkg/event.go
@@ -126,5 +126,8 @@ const (
 	NotificationUnsubscribed
 	NotificationSubscribedOther
 	NotificationUnsubscribedOther
+	CalendarCreated
+	CalendarListed
+	CalendarDeleted
 	maxEvent
 )