diff --git a/gradle.properties b/gradle.properties
index 7961ce99a669dfb81ce4e8e6e8436fb2e4b3b9d3..cb06f8f26b77edd164e23c43d752185c93c3bfb1 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,8 +10,8 @@ micronautRxVersion = 2.1.1
 micronautPluginVersion = 3.1.1
 nodePluginVersion = 3.0.1
 nodeVersion = 16.3.0
-nshmpLibVersion = 0.8.2
-nshmpWsUtilsVersion = 0.1.3
+nshmpLibVersion = 0.9.1
+nshmpWsUtilsVersion = 0.1.7
 shadowVersion = 7.1.2
 spotbugsVersion = 4.7.0
 spotlessVersion = 6.0.4
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/DisaggEpsilon.java b/src/main/java/gov/usgs/earthquake/nshmp/DisaggEpsilon.java
index 066a6fca23ea3a14413174a8f95692d5c76f6067..2b9e4075f44828de95cb813a19663d9b0c3164e2 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/DisaggEpsilon.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/DisaggEpsilon.java
@@ -251,6 +251,7 @@ public class DisaggEpsilon {
       Site site = sites.get(i);
       Map<Imt, Double> spectrum = rtrSpectra.get(i);
 
+      // use IMLs from site spectra
       Hazard hazard = HazardCalcs.hazard(model, config, site, exec);
       Disaggregation disagg = Disaggregation.atImls(hazard, spectrum, exec);
 
@@ -261,7 +262,9 @@ public class DisaggEpsilon {
             site,
             imt,
             spectrum.get(imt));
-        Response response = new Response(imtMetadata, disagg.toJsonCompact(imt));
+        Response response = new Response(
+            imtMetadata,
+            disagg.toJson(imt, false, true, true, false));
         responses.add(response);
       }
       Result result = new Result(responses);
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
index fd844d51d73793c66972b6e11cc5d9e989d01b89..1120be8504341bf5e2b843fb4b3615f2f9216869 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
@@ -98,26 +98,6 @@ public final class Metadata {
     }
   }
 
-  public static String busyMessage(String url, long hits, long misses) {
-    Busy busy = new Busy(url, hits, misses);
-    return ServletUtil.GSON.toJson(busy);
-  }
-
-  static final String BUSY_MESSAGE = "Server busy. Please try again later. " +
-      "We apologize for any inconvenience while we increase capacity.";
-
-  private static class Busy {
-
-    final String status = Status.BUSY.toString();
-    final String request;
-    final String message;
-
-    private Busy(String request, long hits, long misses) {
-      this.request = request;
-      this.message = BUSY_MESSAGE + String.format(" (%s,%s)", hits, misses);
-    }
-  }
-
   public static String errorMessage(String url, Throwable e, boolean trace) {
     Error error = new Error(url, e, trace);
     return ServletUtil.GSON.toJson(error);
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
index 32468d63800dcfd4989430a8b607ecfa65e62ef3..89f03a87b3a4d52e36b209be6f79799729b46a51 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
@@ -24,12 +24,11 @@ import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Parameter;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
@@ -53,8 +52,13 @@ public final class HazardService {
   public static HttpResponse<String> handleDoGetMetadata(HttpRequest<?> request) {
     var url = request.getUri().getPath();
     try {
-      var usage = new RequestMetadata(ServletUtil.model());// SourceServices.ResponseData();
-      var response = new Response<>(Status.USAGE, NAME, url, usage, url);
+      var usage = new RequestMetadata(ServletUtil.model());
+      var response = ResponseBody.usage()
+          .name(NAME)
+          .url(url)
+          .request(url)
+          .response(usage)
+          .build();
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -82,7 +86,7 @@ public final class HazardService {
     }
   }
 
-  static Response<RequestData, ResponseData> process(
+  static ResponseBody<RequestData, ResponseData> process(
       HttpRequest<?> request,
       RequestData data)
       throws InterruptedException, ExecutionException {
@@ -322,7 +326,7 @@ public final class HazardService {
       return this;
     }
 
-    Response<RequestData, ResponseData> build() {
+    ResponseBody<RequestData, ResponseData> build() {
       var hazards = new ArrayList<HazardResponse>();
 
       for (Imt imt : totalMap.keySet()) {
@@ -347,7 +351,12 @@ public final class HazardService {
       Object server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       var response = new ResponseData(new ResponseMetadata(server), List.copyOf(hazards));
 
-      return new Response<>(Status.SUCCESS, NAME, request, response, url);
+      return ResponseBody.<RequestData, ResponseData> success()
+          .name(NAME)
+          .url(url)
+          .request(request)
+          .response(response)
+          .build();
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService2.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService2.java
index 3e58e39dd09e3a90e60e10be299ba559e66e3d04..63fb4261bd5c38b37aea9926f00c787e3cdbd1d1 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService2.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService2.java
@@ -24,12 +24,11 @@ import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Parameter;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
@@ -53,7 +52,12 @@ public final class HazardService2 {
     var url = request.getUri().getPath();
     try {
       var usage = new RequestMetadata(ServletUtil.model());// SourceServices.ResponseData();
-      var response = new Response(Status.USAGE, NAME, url, usage, url);
+      var response = ResponseBody.usage()
+          .name(NAME)
+          .url(url)
+          .request(url)
+          .response(usage)
+          .build();
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -75,7 +79,7 @@ public final class HazardService2 {
 
       // var data = new RequestData(query);
 
-      Response<RequestData, ResponseData> response = process(request, args);
+      ResponseBody<RequestData, ResponseData> response = process(request, args);
       String svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
 
@@ -84,7 +88,7 @@ public final class HazardService2 {
     }
   }
 
-  static Response<RequestData, ResponseData> process(
+  static ResponseBody<RequestData, ResponseData> process(
       HttpRequest<?> request,
       RequestData data) throws InterruptedException, ExecutionException {
 
@@ -323,7 +327,7 @@ public final class HazardService2 {
       return this;
     }
 
-    Response<RequestData, ResponseData> build() {
+    ResponseBody<RequestData, ResponseData> build() {
       var hazards = new ArrayList<HazardResponse>();
 
       for (Imt imt : totalMap.keySet()) {
@@ -348,7 +352,12 @@ public final class HazardService2 {
       Object server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       var response = new ResponseData(new ResponseMetadata(server), List.copyOf(hazards));
 
-      return new Response<>(Status.SUCCESS, NAME, request, response, url);
+      return ResponseBody.<RequestData, ResponseData> success()
+          .name(NAME)
+          .url(url)
+          .request(request)
+          .response(response)
+          .build();
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
index e0772386ad74e3ec67898e042a095f92423431d7..0312e7359a0af379d43fdd55c8a5903edce67a2a 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
@@ -16,12 +16,11 @@ import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.RateController;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata.DefaultParameters;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
@@ -60,8 +59,8 @@ public final class RateService {
   public static HttpResponse<String> handleDoGetUsage(HttpRequest<?> request, Service service) {
     try {
       var response = metadata(request, service);
-      var svcResponse = ServletUtil.GSON.toJson(response);
-      return HttpResponse.ok(svcResponse);
+      var json = ServletUtil.GSON.toJson(response);
+      return HttpResponse.ok(json);
     } catch (Exception e) {
       return ServicesUtil.handleError(e, service.name, request.getUri().getPath());
     }
@@ -96,22 +95,26 @@ public final class RateService {
     }
   }
 
-  static Response<String, Usage> metadata(HttpRequest<?> request, Service service) {
+  static ResponseBody<String, Usage> metadata(HttpRequest<?> request, Service service) {
     var parameters = service == Service.RATE ? new RateParameters() : new ProbabilityParameters();
     var usage = new Usage(service, parameters);
     var url = request.getUri().getPath();
-    return new Response<>(Status.USAGE, service.name, url, usage, url);
+    return ResponseBody.<String, Usage> usage()
+        .name(service.name)
+        .url(url)
+        .request(url)
+        .response(usage)
+        .build();
   }
 
-  static Response<RequestData, ResponseData> processRequest(
+  static ResponseBody<RequestData, ResponseData> processRequest(
       HttpRequest<?> request,
       Service service,
       RequestData data) throws InterruptedException, ExecutionException {
     var timer = Stopwatch.createStarted();
     var rates = calc(service, data);
     var responseData = new ResponseData(new ResponseMetadata(service, data), rates, timer);
-    return Response.<RequestData, ResponseData> builder()
-        .success()
+    return ResponseBody.<RequestData, ResponseData> success()
         .name(service.name)
         .request(data)
         .response(responseData)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
index a3e6d6a37efc79187c2629651abfd3abc419bfcb..b2da3f0917178c67b8acb98f9da86f899e1ec652 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
@@ -11,9 +11,8 @@ import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.HazardCalcs;
 import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 
 import io.micronaut.http.HttpResponse;
 
@@ -24,7 +23,12 @@ public class ServicesUtil {
       String name,
       String url) {
     var msg = e.getMessage() + " (see logs)";
-    var svcResponse = new Response<>(Status.ERROR, name, url, msg, url);
+    var svcResponse = ResponseBody.error()
+        .name(name)
+        .url(url)
+        .request(url)
+        .response(msg)
+        .build();
     var gson = new GsonBuilder().setPrettyPrinting().create();
     var response = gson.toJson(svcResponse);
     e.printStackTrace();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceLogicTreesService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceLogicTreesService.java
index 823445be91ee7b52663a7445da3d05412b373a4a..3d0dfe0a7055376d3b5e764e252f23ca80f4f265 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceLogicTreesService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceLogicTreesService.java
@@ -1,9 +1,8 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
 import gov.usgs.earthquake.nshmp.model.Models;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.SourceLogicTreesController;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -25,7 +24,12 @@ public class SourceLogicTreesService {
 
     try {
       var trees = Models.trees(ServletUtil.model());
-      var response = new Response<>(Status.SUCCESS, NAME, url, trees, url);
+      var response = ResponseBody.success()
+          .name(NAME)
+          .url(url)
+          .request(url)
+          .response(trees)
+          .build();
       return HttpResponse.ok(ServletUtil.GSON.toJson(response));
     } catch (Exception e) {
       return ServicesUtil.handleError(e, NAME, url);
@@ -39,7 +43,12 @@ public class SourceLogicTreesService {
     try {
       var tree = Models.tree(ServletUtil.model(), id);
       var requestData = new RequestData(id);
-      var response = new Response<>(Status.SUCCESS, NAME, requestData, tree, url);
+      var response = ResponseBody.success()
+          .name(NAME)
+          .url(url)
+          .request(requestData)
+          .response(tree)
+          .build();
       return HttpResponse.ok(ServletUtil.GSON.toJson(response));
     } catch (Exception e) {
       return ServicesUtil.handleError(e, NAME, url);
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
index 7db7d76b57225955fe04edd5288ee220b1f0d9a6..83910b2fc623cd7b27e81855da5263435cb87d65 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
@@ -11,10 +11,9 @@ import gov.usgs.earthquake.nshmp.gmm.Gmm;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.gmm.NehrpSiteClass;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
-import gov.usgs.earthquake.nshmp.www.meta.Status;
 
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -48,10 +47,14 @@ public class SourceServices {
   public static HttpResponse<String> handleDoGetUsage(HttpRequest<?> request) {
     var url = request.getUri().getPath();
     try {
-      var response = new Response<>(
-          Status.USAGE, NAME, url, new ResponseData(), url);
-      var jsonString = GSON.toJson(response);
-      return HttpResponse.ok(jsonString);
+      var response = ResponseBody.usage()
+          .name(NAME)
+          .url(url)
+          .request(url)
+          .response(new ResponseData())
+          .build();
+      var json = GSON.toJson(response);
+      return HttpResponse.ok(json);
     } catch (Exception e) {
       return ServicesUtil.handleError(e, NAME, url);
     }