diff --git a/src/main/java/org/eclipsefoundation/marketplace/dao/impl/DefaultMongoDao.java b/src/main/java/org/eclipsefoundation/marketplace/dao/impl/DefaultMongoDao.java
index 892660e0314498ac6cf2869a06a491ea3ed51468..460817d00fa210460fdb21ceb6ce33fb210dd674 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/dao/impl/DefaultMongoDao.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/dao/impl/DefaultMongoDao.java
@@ -6,12 +6,18 @@
  */
 package org.eclipsefoundation.marketplace.dao.impl;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
+import java.util.stream.Collectors;
 
 import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Instance;
 import javax.inject.Inject;
 
+import org.bson.codecs.configuration.CodecProvider;
+import org.bson.conversions.Bson;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.eclipse.microprofile.health.HealthCheckResponse;
 import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
@@ -23,6 +29,7 @@ import org.eclipsefoundation.marketplace.namespace.DtoTableNames;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.mongodb.client.model.ReplaceOptions;
 import com.mongodb.client.result.DeleteResult;
 
 import io.quarkus.mongodb.ReactiveMongoClient;
@@ -49,6 +56,9 @@ public class DefaultMongoDao implements MongoDao {
 	@ConfigProperty(name = "mongodb.maintenance", defaultValue = "false")
 	boolean maintenanceFlag;
 
+	@Inject
+	Instance<CodecProvider> providers;
+
 	@Inject
 	ReactiveMongoClient mongoClient;
 
@@ -63,7 +73,8 @@ public class DefaultMongoDao implements MongoDao {
 
 		LOGGER.debug("Getting aggregate results");
 		// build base query
-		PublisherBuilder<T> builder = getCollection(q.getDocType()).aggregate(q.getPipeline(getLimit(q)), q.getDocType());
+		PublisherBuilder<T> builder = getCollection(q.getDocType()).aggregate(q.getPipeline(getLimit(q)),
+				q.getDocType());
 		// check if result set should be limited
 		if (q.getDTOFilter().useLimit()) {
 			builder = builder.limit(getLimit(q));
@@ -80,7 +91,25 @@ public class DefaultMongoDao implements MongoDao {
 		if (LOGGER.isDebugEnabled()) {
 			LOGGER.debug("Adding {} documents to MongoDB of type {}", documents.size(), q.getDocType().getSimpleName());
 		}
-		return getCollection(q.getDocType()).insertMany(documents);
+
+		// set up upserting to not fail on updates
+		ReplaceOptions ro = new ReplaceOptions().upsert(true).bypassDocumentValidation(true);
+
+		// maintain a list of updates
+		List<CompletionStage<?>> stages = new ArrayList<>(documents.size());
+		Bson filter = q.getFilter();
+		for (T doc : documents) {
+			if (filter == null) {
+				stages.add(getCollection(q.getDocType()).insertOne(doc));
+			} else {
+				stages.add(getCollection(q.getDocType()).replaceOne(filter, doc, ro));
+			}
+		}
+
+		// convert the stages to futures, and wrap them in a completable future
+		List<CompletableFuture<?>> all = stages.stream().map(CompletionStage::toCompletableFuture)
+				.collect(Collectors.toList());
+		return CompletableFuture.allOf(all.toArray(new CompletableFuture[all.size()]));
 	}
 
 	@Override
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/CatalogResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/CatalogResource.java
index 0aa35a0823ad6d47f990754710457918400dbf63..03454b235b75625765b18510c3eeedfdc396cd36 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/CatalogResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/CatalogResource.java
@@ -87,6 +87,9 @@ public class CatalogResource {
 	@PUT
 	@RolesAllowed({ "marketplace_catalog_put", "marketplace_admin_access" })
 	public Response putCatalog(Catalog catalog) {
+		if (catalog.getId() != null) {
+			params.addParam(UrlParameterNames.ID, catalog.getId());
+		}
 		MongoQuery<Catalog> q = new MongoQuery<>(params, dtoFilter);
 		// add the object, and await the result
 		StreamHelper.awaitCompletionStage(dao.add(q, Arrays.asList(catalog)));
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/CategoryResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/CategoryResource.java
index b343c314fe57312992e7b575cc7822a3bf5f9c4f..416acc1e38b4f066295e0a70e3b6607f0aa550e8 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/CategoryResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/CategoryResource.java
@@ -87,6 +87,9 @@ public class CategoryResource {
 	@PUT
 	@RolesAllowed({"marketplace_category_put", "marketplace_admin_access"})
 	public Response putCategory(Category category) {
+		if (category.getId() != null) {
+			params.addParam(UrlParameterNames.ID, category.getId());
+		}
 		MongoQuery<Category> q = new MongoQuery<>(params, dtoFilter);
 		// add the object, and await the result
 		StreamHelper.awaitCompletionStage(dao.add(q, Arrays.asList(category)));
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/ErrorReportResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/ErrorReportResource.java
index 5c8b1adc9d6c4417b5ead3ff67be41f4678fd879..7d4c2f0ba330b387a0fd27118497357ef4cb949a 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/ErrorReportResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/ErrorReportResource.java
@@ -11,12 +11,11 @@ import java.util.List;
 import java.util.Optional;
 
 import javax.annotation.security.PermitAll;
-import javax.annotation.security.RolesAllowed;
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
@@ -41,7 +40,7 @@ import org.slf4j.LoggerFactory;
  * @author Martin Lowe
  */
 @RequestScoped
-@Path("/error")
+@Path("/error_reports")
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public class ErrorReportResource {
@@ -87,9 +86,13 @@ public class ErrorReportResource {
 	 * @param errorReport the ErrorReport object to insert into the database.
 	 * @return response for the browser
 	 */
-	@PUT
-	@RolesAllowed("error_put")
+	@POST
+	@PermitAll
 	public Response putErrorReport(ErrorReport errorReport) {
+		// attach ID if present for update
+		if (errorReport.getId() != null) {
+			params.addParam(UrlParameterNames.ID, errorReport.getId());
+		}
 		MongoQuery<ErrorReport> q = new MongoQuery<>(params, dtoFilter);
 
 		// add the object, and await the result
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
index 9519ff493f5807e40fff9e1d296ee928ac4b8b9a..c49d8023e4d807e7c499497fff24c77fba16d75a 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
@@ -165,7 +165,7 @@ public class InstallResource {
 	 * @return response for the browser
 	 */
 	@POST
-	@RolesAllowed({ "marketplace_install_put", "marketplace_admin_access" })
+	@PermitAll
 	@Path("/{listingId}/{version}")
 	public Response postInstallMetrics(@PathParam("listingId") String listingId, @PathParam("version") String version,
 			Install installDetails) {
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/ListingResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/ListingResource.java
index d31a6153f8d4c65988e235df26f35fcf7e53d665..fa5cd87ec89574c8113487214cd867c19348c3a8 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/ListingResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/ListingResource.java
@@ -98,6 +98,9 @@ public class ListingResource {
 	@PUT
 	@RolesAllowed({ "marketplace_listing_put", "marketplace_admin_access" })
 	public Response putListing(Listing listing) {
+		if (listing.getId() != null) {
+			params.addParam(UrlParameterNames.ID, listing.getId());
+		}
 		MongoQuery<Listing> q = new MongoQuery<>(params, dtoFilter);
 
 		// add the object, and await the result
@@ -154,4 +157,4 @@ public class ListingResource {
 		// return the results as a response
 		return Response.ok().build();
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/ListingVersionResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/ListingVersionResource.java
index 9b074b875081187bd65edf3c5ccc7d840e3811f3..66f318ad967d8e13517d70f30c0d315a987997c2 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/ListingVersionResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/ListingVersionResource.java
@@ -10,6 +10,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
+import javax.annotation.security.RolesAllowed;
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
@@ -85,6 +86,9 @@ public class ListingVersionResource {
 	 */
 	@PUT
 	public Response putListingVersion(ListingVersion listingVersion) {
+		if (listingVersion.getId() != null) {
+			params.addParam(UrlParameterNames.ID, listingVersion.getId());
+		}
 		MongoQuery<ListingVersion> q = new MongoQuery<>(params, dtoFilter);
 		// add the object, and await the result
 		StreamHelper.awaitCompletionStage(dao.add(q, Arrays.asList(listingVersion)));
@@ -126,6 +130,7 @@ public class ListingVersionResource {
 	 * @return response for the browser
 	 */
 	@DELETE
+	@RolesAllowed({ "marketplace_version_delete", "marketplace_admin_access" })
 	@Path("/{listingVersionId}")
 	public Response delete(@PathParam("listingVersionId") String listingVersionId) {
 		params.addParam(UrlParameterNames.ID, listingVersionId);
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/MarketResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/MarketResource.java
index 44c710117eea26ae9eefe267d001b85a6ba82f95..aa0fd9593b5f838c366dc087bcaceb4e5f676b34 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/MarketResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/MarketResource.java
@@ -61,7 +61,7 @@ public class MarketResource {
 	DtoFilter<Market> dtoFilter;
 	@Inject
 	ResponseHelper responseBuider;
-
+	
 	@GET
 	@PermitAll
 	public Response select() {
@@ -85,8 +85,11 @@ public class MarketResource {
 	 * @return response for the browser
 	 */
 	@PUT
-	@RolesAllowed("market_put")
+	@RolesAllowed({ "marketplace_market_put", "marketplace_admin_access" })
 	public Response putMarket(Market market) {
+		if (market.getId() != null) {
+			params.addParam(UrlParameterNames.ID, market.getId());
+		}
 		MongoQuery<Market> q = new MongoQuery<>(params, dtoFilter);
 
 		// add the object, and await the result