diff --git a/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java
index dd59717afd96208dc9e6e6dfb2734cc2617f9607..ae5129376ea696e8bb007240e00c2b7c8bacc050 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java
@@ -166,16 +166,11 @@ public class DisaggCalc {
        */
       Path out;
       if (siteColumns.size() == allColumns.size()) {
+
         checkArgument(
             modelImts.containsAll(config.hazard.imts),
             "Config specifies IMTs not supported by model");
-
-        // List<Imt> imts = config.imts;
-
-        // Path out = calc(model, config, sites, imtImlMaps, log);
-
         double returnPeriod = config.disagg.returnPeriod;
-
         out = calcRp(model, config, sites, returnPeriod, log);
 
       } else {
@@ -189,19 +184,9 @@ public class DisaggCalc {
             sites.size() == imls.size(),
             "Sites and spectra lists different sizes");
         log.info("Spectra: " + imls.size()); // 1:1 with sites
-
         out = calcIml(model, config, sites, imls, log);
-      }
-
-      // List<Map<Imt, Double>> imtImlMaps = readSpectra(siteFile, imts,
-      // colsToSkip);
-      // log.info("Spectra: " + imtImlMaps.size());
 
-      // checkArgument(sites.size() == imtImlMaps.size(), "Sites and spectra
-      // lists different sizes");
-      // Spectra should be checked against IMTs supported by model GMMs
-
-      // Path out = calc(model, config, sites, imls, log);
+      }
 
       log.info(PROGRAM + ": finished");
 
@@ -346,13 +331,13 @@ public class DisaggCalc {
   }
 
   /* Hazard curves are already in log-x space. */
-  static final Interpolator IML_INTERPOLATER = Interpolator.builder()
+  private static final Interpolator IML_INTERPOLATER = Interpolator.builder()
       .logy()
       .decreasingY()
       .build();
 
-  // this should be in a factory
-  private static Map<Imt, Double> imlsForReturnPeriod(
+  /** Compute the return period intercepts from a hazard result. */
+  public static Map<Imt, Double> imlsForReturnPeriod(
       Hazard hazard,
       double returnPeriod) {
 
@@ -360,7 +345,6 @@ public class DisaggCalc {
     Map<Imt, Double> imls = new EnumMap<>(Imt.class);
     for (Entry<Imt, XySequence> entry : hazard.curves().entrySet()) {
       double iml = IML_INTERPOLATER.findX(entry.getValue(), rate);
-      // remove exp below by transforming disagg-epsilon to log earlier
       imls.put(entry.getKey(), Math.exp(iml));
     }
     return imls;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java
index 27ab4200b2d48cab86285d437dffc3bb24170e31..0642f7b0c8246e6c773a0766664f1d3d30a90d8b 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java
@@ -5,10 +5,10 @@ import static com.google.common.base.Preconditions.checkArgument;
 import java.util.Map;
 import java.util.Set;
 
+import gov.usgs.earthquake.nshmp.calc.DataType;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.ServletUtil;
-
 import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -92,14 +92,20 @@ public class DisaggController {
       @Schema(
           minimum = "150",
           maximum = "3000") @PathVariable double returnPeriod,
-      @Schema() @QueryValue @Nullable Set<Imt> imt) {
+      @QueryValue @Nullable Set<Imt> imt,
+      @Schema(allowableValues = {
+          "DISAGG_DATA",
+          "GMM",
+          "SOURCE" }) @QueryValue @Nullable Set<DataType> out) {
     try {
       Set<Imt> imts = HazardService.readImts(http);
+      Set<DataType> dataTypes = HazardService.readDataTypes(http);
       DisaggService.RequestRp request = new DisaggService.RequestRp(
           http,
           longitude, latitude, vs30,
           returnPeriod,
-          imts);
+          imts,
+          dataTypes);
       return DisaggService.getDisaggRp(request);
     } catch (Exception e) {
       return ServletUtil.error(
@@ -113,6 +119,7 @@ public class DisaggController {
    * @param longitude Longitude in the range [-360..360]°.
    * @param latitude Latitude in decimal degrees [-90..90]°.
    * @param vs30 Site Vs30 value in the range [150..3000] m/s.
+   * @param out The data types to output
    */
   @Operation(
       summary = "Disaggregate hazard at specified IMLs",
@@ -133,7 +140,11 @@ public class DisaggController {
           maximum = "90") @PathVariable double latitude,
       @Schema(
           minimum = "150",
-          maximum = "3000") @PathVariable double vs30) {
+          maximum = "3000") @PathVariable double vs30,
+      @Schema(allowableValues = {
+          "DISAGG_DATA",
+          "GMM",
+          "SOURCE" }) @QueryValue @Nullable Set<DataType> out) {
 
     /*
      * Developer notes:
@@ -146,10 +157,12 @@ public class DisaggController {
     try {
       Map<Imt, Double> imtImlMap = http.getParameters().asMap(Imt.class, Double.class);
       checkArgument(!imtImlMap.isEmpty(), "No IMLs supplied");
+      Set<DataType> dataTypes = HazardService.readDataTypes(http);
       DisaggService.RequestIml request = new DisaggService.RequestIml(
           http,
           longitude, latitude, vs30,
-          imtImlMap);
+          imtImlMap,
+          dataTypes);
       return DisaggService.getDisaggIml(request);
     } catch (Exception e) {
       return ServletUtil.error(
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
index 842194aaa68257ee447de8a9611b85dcbc2c475d..d3934908844a3f93d413581138335d215c4f154b 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
@@ -16,6 +16,7 @@ import com.google.common.base.Stopwatch;
 import com.google.common.collect.Range;
 
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
+import gov.usgs.earthquake.nshmp.calc.DataType;
 import gov.usgs.earthquake.nshmp.calc.Disaggregation;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.HazardCalcs;
@@ -27,7 +28,6 @@ import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.ServletUtil;
 import gov.usgs.earthquake.nshmp.www.hazard.HazardService.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Parameter;
-
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import jakarta.inject.Singleton;
@@ -55,7 +55,7 @@ public final class DisaggService {
   private static Range<Double> imlRange = Range.closed(0.0001, 8.0);
 
   /** HazardController.doGetMetadata() handler. */
-  public static HttpResponse<String> getMetadata(HttpRequest<?> request) {
+  static HttpResponse<String> getMetadata(HttpRequest<?> request) {
     var url = request.getUri().toString();
     var usage = new Metadata(ServletUtil.model());
     var response = ResponseBody.usage()
@@ -69,7 +69,7 @@ public final class DisaggService {
   }
 
   /** HazardController.doGetDisaggIml() handler. */
-  public static HttpResponse<String> getDisaggIml(RequestIml request)
+  static HttpResponse<String> getDisaggIml(RequestIml request)
       throws InterruptedException, ExecutionException {
     var stopwatch = Stopwatch.createStarted();
     var disagg = calcDisaggIml(request);
@@ -89,7 +89,7 @@ public final class DisaggService {
   }
 
   /** HazardController.doGetDisaggRp() handler. */
-  public static HttpResponse<String> getDisaggRp(RequestRp request)
+  static HttpResponse<String> getDisaggRp(RequestRp request)
       throws InterruptedException, ExecutionException {
     var stopwatch = Stopwatch.createStarted();
     var disagg = calcDisaggRp(request);
@@ -116,7 +116,7 @@ public final class DisaggService {
    *
    */
 
-  static Disaggregation calcDisaggIml(RequestIml request)
+  private static Disaggregation calcDisaggIml(RequestIml request)
       throws InterruptedException, ExecutionException {
 
     HazardModel model = ServletUtil.model();
@@ -124,6 +124,7 @@ public final class DisaggService {
     // modify config to include service endpoint arguments
     CalcConfig config = CalcConfig.copyOf(model.config())
         .imts(request.imls.keySet())
+        // .dataTypes(request.dataTypes)
         .build();
 
     // TODO this needs to pick up SiteData, centralize
@@ -152,7 +153,7 @@ public final class DisaggService {
     return disagg;
   }
 
-  static Disaggregation calcDisaggRp(RequestRp request)
+  private static Disaggregation calcDisaggRp(RequestRp request)
       throws InterruptedException, ExecutionException {
 
     HazardModel model = ServletUtil.model();
@@ -160,6 +161,7 @@ public final class DisaggService {
     // modify config to include service endpoint arguments
     CalcConfig config = CalcConfig.copyOf(model.config())
         .imts(request.imts)
+        // .dataTypes(request.dataTypes)
         .build();
 
     // TODO this needs to pick up SiteData, centralize
@@ -176,6 +178,9 @@ public final class DisaggService {
         ServletUtil.TASK_EXECUTOR);
 
     Hazard hazard = hazFuture.get();
+    // Map<Imt, Double> imls = DisaggCalc.imlsForReturnPeriod(
+    // hazard,
+    // request.returnPeriod);
 
     CompletableFuture<Disaggregation> disaggfuture = CompletableFuture.supplyAsync(
         () -> Disaggregation.atReturnPeriod(
@@ -195,19 +200,22 @@ public final class DisaggService {
     final double latitude;
     final double vs30;
     final Map<Imt, Double> imls;
+    final Set<DataType> dataTypes;
 
     RequestIml(
         HttpRequest<?> http,
         double longitude,
         double latitude,
         double vs30,
-        Map<Imt, Double> imls) {
+        Map<Imt, Double> imls,
+        Set<DataType> dataTypes) {
 
       this.http = http;
       this.longitude = longitude;
       this.latitude = latitude;
       this.vs30 = vs30;
       this.imls = imls;
+      this.dataTypes = dataTypes;
     }
   }
 
@@ -219,6 +227,7 @@ public final class DisaggService {
     final double vs30;
     final double returnPeriod;
     final Set<Imt> imts;
+    final Set<DataType> dataTypes;
 
     RequestRp(
         HttpRequest<?> http,
@@ -226,7 +235,8 @@ public final class DisaggService {
         double latitude,
         double vs30,
         double returnPeriod,
-        Set<Imt> imts) {
+        Set<Imt> imts,
+        Set<DataType> dataTypes) {
 
       this.http = http;
       this.longitude = longitude;
@@ -236,6 +246,7 @@ public final class DisaggService {
       this.imts = imts.isEmpty()
           ? ServletUtil.model().config().hazard.imts
           : imts;
+      this.dataTypes = dataTypes;
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
index f668b016e76468c696e0759fa3cee55077c2451e..5b41bbe78540a551a49dcb1f5239f1580a32e763 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
@@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Stopwatch;
 
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
+import gov.usgs.earthquake.nshmp.calc.DataType;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.HazardCalcs;
 import gov.usgs.earthquake.nshmp.calc.Site;
@@ -38,7 +39,6 @@ import gov.usgs.earthquake.nshmp.www.ServletUtil;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Parameter;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
-
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import jakarta.inject.Singleton;
@@ -155,7 +155,7 @@ public final class HazardService {
     }
   }
 
-  public static final class Request {
+  static final class Request {
 
     final transient HttpRequest<?> http;
     final double longitude;
@@ -347,12 +347,19 @@ public final class HazardService {
 
   /* Read the 'imt' query values; can be comma-delimited. */
   static Set<Imt> readImts(HttpRequest<?> http) {
-    return http.getParameters()
-        .getAll("imt")// TODO where are key strings?
-        .stream()
+    return http.getParameters().getAll("imt").stream()
         .map(s -> s.split(","))
         .flatMap(Arrays::stream)
         .map(Imt::valueOf)
         .collect(toCollection(() -> EnumSet.noneOf(Imt.class)));
   }
+
+  /* Read the 'imt' query values; can be comma-delimited. */
+  static Set<DataType> readDataTypes(HttpRequest<?> http) {
+    return http.getParameters().getAll("out").stream()
+        .map(s -> s.split(","))
+        .flatMap(Arrays::stream)
+        .map(DataType::valueOf)
+        .collect(toCollection(() -> EnumSet.noneOf(DataType.class)));
+  }
 }