diff --git a/src/main/java/no/nibio/vips/logic/controller/session/ObservationTimeSeriesBean.java b/src/main/java/no/nibio/vips/logic/controller/session/ObservationTimeSeriesBean.java
index b911f8835e1776fc4233c30af6fcc025177ae0dd..cc178617f94fc1128fc82aebc4a4774269633246 100644
--- a/src/main/java/no/nibio/vips/logic/controller/session/ObservationTimeSeriesBean.java
+++ b/src/main/java/no/nibio/vips/logic/controller/session/ObservationTimeSeriesBean.java
@@ -143,6 +143,7 @@ public class ObservationTimeSeriesBean {
     public void deleteObservationTimeSeries(Integer id) {
         ObservationTimeSeries observationTimeSeries = em.find(ObservationTimeSeries.class, id);
         if (observationTimeSeries != null) {
+            // The app prevents deletion of time series with observations
             observationBean.deleteObservationsForObservationTimeSeries(observationTimeSeries);
             em.remove(observationTimeSeries);
         }
diff --git a/src/main/java/no/nibio/vips/logic/entity/Observation.java b/src/main/java/no/nibio/vips/logic/entity/Observation.java
index 92d6b90557429eecf02ee5649c6583fdba5dbd97..7d5a506af769de9b0a6b22a80ae92c1e0c6441e1 100755
--- a/src/main/java/no/nibio/vips/logic/entity/Observation.java
+++ b/src/main/java/no/nibio/vips/logic/entity/Observation.java
@@ -19,20 +19,7 @@ package no.nibio.vips.logic.entity;
 
 import java.io.Serializable;
 import java.util.Date;
-import javax.persistence.Basic;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-import javax.persistence.Transient;
+import javax.persistence.*;
 import javax.validation.constraints.NotNull;
 import javax.xml.bind.annotation.XmlRootElement;
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -41,9 +28,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.persistence.CascadeType;
-import javax.persistence.FetchType;
-import javax.persistence.OneToMany;
 import javax.validation.constraints.Size;
 import no.nibio.vips.logic.util.GISEntityUtil;
 import no.nibio.vips.gis.GISUtil;
@@ -62,6 +46,7 @@ import org.hibernate.annotations.TypeDefs;
 @Table(name = "observation")
 @XmlRootElement
 @TypeDefs( {@TypeDef( name= "StringJsonObject", typeClass = StringJsonUserType.class)})
+
 @NamedQueries({
     @NamedQuery(name = "Observation.findAll", query = "SELECT o FROM Observation o"),
     @NamedQuery(name = "Observation.findByObservationId", query = "SELECT o FROM Observation o WHERE o.observationId = :observationId"),
@@ -122,9 +107,18 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse
     private GISEntityUtil GISEntityUtil;
     private GISUtil GISUtil;
 
+    // Should be defined as an enum (WEB/APP), but PostgreSQLEnumType and hibernate6 seems to be necessary
+    // https://stackoverflow.com/questions/50818649/hibernate-and-java-and-postgres-enumeratedvalue-enumtype-string-caused-by
+    private String source;
+
     public Observation() {
+        this("WEB");
+    }
+
+    public Observation(String source) {
         this.GISEntityUtil = new GISEntityUtil();
         this.GISUtil = new GISUtil();
+        this.source = source;
     }
 
     public Observation(Integer observationId) {
@@ -304,6 +298,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse
                 ", observationIllustrationSet=" + observationIllustrationSet +
                 ", GISEntityUtil=" + GISEntityUtil +
                 ", GISUtil=" + GISUtil +
+                ", source=" + source +
                 '}';
     }
 
@@ -727,4 +722,12 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse
     public void setIsPositive(Boolean positive) {
         isPositive = positive;
     }
+
+    public String getSource() {
+        return source;
+    }
+
+    public void setSource(String source) {
+        this.source = source;
+    }
 }
diff --git a/src/main/java/no/nibio/vips/logic/service/ObservationService.java b/src/main/java/no/nibio/vips/logic/service/ObservationService.java
index 4e093d77a7a792cba057ff5ef2e22ad345dba4d1..3b1dacb611c2c75762e4766a591ffba706f5c5c8 100755
--- a/src/main/java/no/nibio/vips/logic/service/ObservationService.java
+++ b/src/main/java/no/nibio/vips/logic/service/ObservationService.java
@@ -924,11 +924,17 @@ public class ObservationService {
                         return Response.status(Status.NOT_FOUND).build();
                     }
                 } else {
-                    Observation mergeObs = ((Integer) mapFromApp.get("observationId")) > 0 ? observationBean.getObservation((Integer) mapFromApp.get("observationId")) : new Observation();
-                    // Trying to sync a non-existing observation
-                    if (mergeObs == null) {
-                        return Response.status(Status.NOT_FOUND).build();
+                    Integer observationId = (Integer) mapFromApp.get("observationId");
+                    Observation mergeObs;
+                    if(observationId > 0) {
+                        mergeObs = observationBean.getObservation(observationId);
+                        if (mergeObs == null) {
+                            return Response.status(Status.NOT_FOUND).build();
+                        }
+                    } else {
+                        mergeObs = new Observation("APP");
                     }
+
                     // Observation time series
                     if(mapFromApp.get("observationTimeSeriesId") != null) {
                         Integer observationTimeSeriesId = (Integer) mapFromApp.get("observationTimeSeriesId");
@@ -942,24 +948,23 @@ public class ObservationService {
                     mergeObs.setTimeOfObservation(oM.convertValue(mapFromApp.get("timeOfObservation"), new TypeReference<Date>() {
                     }));
                     mergeObs.setIsPositive(mapFromApp.get("isPositive") != null ? (Boolean) mapFromApp.get("isPositive") : false);
-                    mergeObs.setUserId(mapFromApp.get("userId") != null ? Integer.valueOf((Integer) mapFromApp.get("userId")) : user.getUserId());
+                    mergeObs.setUserId(mapFromApp.get("userId") != null ? (Integer) mapFromApp.get("userId") : user.getUserId());
                     mergeObs.setGeoinfo((String) mapFromApp.get("geoinfo"));
                     mergeObs.setLocationPointOfInterestId(mapFromApp.get("locationPointOfInterestId") != null ? (Integer) mapFromApp.get("locationPointOfInterestId") : null);
                     mergeObs.setObservationHeading(mapFromApp.get("observationHeading") != null ? (String) mapFromApp.get("observationHeading") : null);
                     mergeObs.setObservationText(mapFromApp.get("observationText") != null ? (String) mapFromApp.get("observationText") : null);
                     mergeObs.setBroadcastMessage(mapFromApp.get("broadcastMessage") != null ? (Boolean) mapFromApp.get("broadcastMessage") : false);
-                    mergeObs.setStatusTypeId(Integer.valueOf((Integer) mapFromApp.get("statusTypeId")));
+                    mergeObs.setStatusTypeId((Integer) mapFromApp.get("statusTypeId"));
                     // If the user has the role of observation approver, change to approved if set to pending
                     if (mergeObs.getStatusTypeId().equals(ObservationStatusType.STATUS_PENDING) && user.isObservationAuthority()) {
                         mergeObs.setStatusTypeId(ObservationStatusType.STATUS_APPROVED);
                     }
-                    mergeObs.setStatusChangedByUserId(mapFromApp.get("statusChangedByUserId") != null ? (Integer) mapFromApp.get("statusChangedByUserId") : null);
+                    mergeObs.setStatusChangedByUserId(mapFromApp.get("userId") != null ? (Integer) mapFromApp.get("userId") : null);
                     mergeObs.setStatusChangedTime(mapFromApp.get("timeOfObservation") != null ? oM.convertValue(mapFromApp.get("timeOfObservation"), new TypeReference<Date>() {
                     }) : null);
                     mergeObs.setStatusRemarks(mapFromApp.get("statusRemarks") != null ? (String) mapFromApp.get("statusRemarks") : null);
                     mergeObs.setIsQuantified(mapFromApp.get("isQuantified") != null ? (Boolean) mapFromApp.get("isQuantified") : false);
                     mergeObs.setLocationIsPrivate(mapFromApp.get("locationIsPrivate") != null ? (Boolean) mapFromApp.get("locationIsPrivate") : false);
-
                     Object polygonServiceValue = mapFromApp.get("polygonService");
                     if(polygonServiceValue != null && !polygonServiceValue.toString().isBlank()) {
                         PolygonService polygonService = oM.convertValue(mapFromApp.get("polygonService"), PolygonService.class);
@@ -974,7 +979,7 @@ public class ObservationService {
                     // Input check before storing
                     // Location must be set
                     if ((mergeObs.getGeoinfo() == null || mergeObs.getGeoinfo().trim().isEmpty()) && mergeObs.getLocationPointOfInterestId() == null) {
-                        return Response.status(Status.BAD_REQUEST).entity("The observation is missing location data.").build();
+                        return Response.status(Status.BAD_REQUEST).entity("{\"error\": \"The observation is missing location data.\"}").type(MediaType.APPLICATION_JSON).build();
                     }
 
                     boolean sendNotification = false;
@@ -995,7 +1000,6 @@ public class ObservationService {
                     // We need to get an observation Id before storing the illustrations!
                     mergeObs = observationBean.storeObservation(mergeObs);
 
-
                     // ObservationIllustrationSet
                     // Including data that may need to be stored
                     if (mapFromApp.get("observationIllustrationSet") != null) {
diff --git a/src/main/java/no/nibio/vips/logic/service/ObservationTimeSeriesService.java b/src/main/java/no/nibio/vips/logic/service/ObservationTimeSeriesService.java
index e074ee6fcfa1a763a4b025f82ac5594de087dbf5..e0c5d0a0b25b97756abaa9a457cb6b2adb896bbc 100644
--- a/src/main/java/no/nibio/vips/logic/service/ObservationTimeSeriesService.java
+++ b/src/main/java/no/nibio/vips/logic/service/ObservationTimeSeriesService.java
@@ -197,6 +197,7 @@ public class ObservationTimeSeriesService {
             Boolean isDeleted = (Boolean) mapFromApp.getOrDefault(DELETED, false);
             if (isDeleted) {
                 // If marked as deleted, delete the observation time series if it exists
+                // Observations in time series are also deleted, but the app currently prevents this.
                 if (observationTimeSeriesBean.getObservationTimeSeries(otsId) != null) {
                     observationTimeSeriesBean.deleteObservationTimeSeries(otsId);
                     LOGGER.info("ObservationTimeSeries with id={} deleted", otsId);