diff --git a/api.bs b/api.bs
index 3e8b23f..11f4b46 100644
--- a/api.bs
+++ b/api.bs
@@ -1876,18 +1876,26 @@ if the user has opted out of collection of diagnostic data.
# HTTP API # {#http-api}
+## Saving impressions ## {#http-api-impressions}
+
\`Save-Impression\` is a
[=structured header/dictionary|Dictionary Structured Header=]
set on a response requesting that the user agent invoke the
saveImpression() API.
-
-Save-Impression: conversion-sites=("advertiser.example"), conversion-callers=("intermediary.example"), histogram-index=2, match-value=12, lifetime-days=7
-
+conversion-sitesconversion-callershistogram-indexlifetime-days[=save-impression/histogram-index=]"] does not [=map/exist=] or
- is not an [=structured header/integer=] or is less than 0, return an error.
-1. Let |histogramIndex| be |dict|["[=save-impression/histogram-index=]"].
-1. Let |conversionSites| be |dict|["[=save-impression/conversion-sites=]"]
- [=map/with default=] an empty [=structured header/inner list=].
-1. If |conversionSites| is not an [=structured header/inner list=], or if any of |conversionSites|' [=list/items=] is not a [=structured header/string=], return an error.
-1. Let |conversionCallers| be |dict|["[=save-impression/conversion-callers=]"]
- [=map/with default=] an empty [=structured header/inner list=].
-1. If |conversionCallers| is not an [=structured header/inner list=], or if any of |conversionCallers|' [=list/items=] is not a [=structured header/string=], return an error.
-1. Let |matchValue| be |dict|["[=save-impression/match-value=]"] [=map/with default=] 0.
-1. If |matchValue| is not an [=structured header/integer=] or is less than 0, return an error.
-1. Let |lifetimeDays| be |dict|["[=save-impression/lifetime-days=]"] [=map/with default=] 30.
-1. If |lifetimeDays| is not an [=structured header/integer=] or is less than or equal to 0, return an error.
-1. Let |priority| be |dict|["[=save-impression/priority=]"] [=map/with default=] 0.
-1. If |priority| is not an [=structured header/integer=], return an error.
-1. Return a new {{AttributionImpressionOptions}} with the following items:
+1. Let |histogramIndex| be |dict|["[=save-impression/histogram-index=]"] [=map/with default=] `undefined`.
+1. If |histogramIndex| is not a non-negative [=structured header/integer=], return an error.
+1. Let |opts| be a new {{AttributionImpressionOptions}} with the following items:
: {{AttributionImpressionOptions/histogramIndex}}
:: |histogramIndex|
- : {{AttributionImpressionOptions/matchValue}}
- :: |matchValue|
- : {{AttributionImpressionOptions/conversionSites}}
- :: |conversionSites|
- : {{AttributionImpressionOptions/conversionCallers}}
- :: |conversionCallers|
- : {{AttributionImpressionOptions/lifetimeDays}}
- :: |lifetimeDays|
- : {{AttributionImpressionOptions/priority}}
- :: |priority|
+1. If |dict|["[=save-impression/conversion-sites=]"] [=map/exists=]:
+ 1. Let |conversionSites| be its [=map/value=].
+ 1. If |conversionSites| is not an [=structured header/inner list=], or if any of
+ |conversionSites|' [=list/items=] is not a [=structured header/string=],
+ return an error.
+ 1. Set |opts|.{{AttributionImpressionOptions/conversionSites}} to |conversionSites|.
+1. If |dict|["[=save-impression/conversion-callers=]"] [=map/exists=]:
+ 1. Let |conversionCallers| be its [=map/value=].
+ 1. If |conversionCallers| is not an [=structured header/inner list=], or if any of
+ |conversionCallers|' [=list/items=] is not a [=structured header/string=],
+ return an error.
+ 1. Set |opts|.{{AttributionImpressionOptions/conversionCallers}} to |conversionCallers|.
+1. If |dict|["[=save-impression/match-value=]"] [=map/exists=]:
+ 1. Let |matchValue| be its [=map/value=].
+ 1. If |matchValue| is not a non-negative [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionImpressionOptions/matchValue}} to |matchValue|.
+1. If |dict|["[=save-impression/lifetime-days=]"] [=map/exists=]:
+ 1. Let |lifetimeDays| be its [=map/value=].
+ 1. If |lifetimeDays| is not a positive [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionImpressionOptions/lifetimeDays}} to |lifetimeDays|.
+1. If |dict|["[=save-impression/priority=]"] [=map/exists=]:
+ 1. Let |priority| be its [=map/value=].
+ 1. If |priority| is not an [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionImpressionOptions/priority}} to |priority|.
+1. Return |opts|.
+## Measuring Conversions ## {#http-api-conversions}
+
+\`Measure-Conversion\` is a
+[=structured header/dictionary|Dictionary Structured Header=]
+set on a response requesting that the user agent invoke the
+measureConversion() API.
+
+aggregation-serviceepsilonhistogram-sizelookback-daysmatch-valuesimpression-sitesimpression-callerscreditvaluemax-valuereport-url[=measure-conversion/aggregation-service=]"] [=map/with default=] `undefined`.
+1. If |aggregationService| is not a [=structured header/string=], return an error.
+1. Let |histogramSize| be |dict|["[=measure-conversion/histogram-size=]"] [=map/with default=] `undefined`.
+1. If |histogramSize| is not a positive [=structured header/integer=], return an error.
+1. Let |reportUrlString| be |dict|["[=measure-conversion/report-url=]"] [=map/with default=] `undefined`.
+1. If |reportUrlString| is not a [=structured header/string=], return an error.
+1. Let |reportUrl| be the result of applying the [=URL parser=] to |reportUrlString|, with |baseUrl|.
+1. If |reportUrl| is failure, return an error.
+1. If |reportUrl| is not a [=potentially trustworthy URL=], return an error.
+1. If |reportUrl|'s [=url/scheme=] is not "`http`" or "`https`", return an error.
+1. Let |opts| be a new {{AttributionConversionOptions}} with the following items:
+ : {{AttributionConversionOptions/aggregationService}}
+ :: |aggregationService|
+ : {{AttributionConversionOptions/histogramSize}}
+ :: |histogramSize|
+1. If |dict|["[=measure-conversion/epsilon=]"] [=map/exists=]:
+ 1. Let |epsilon| be its [=map/value=].
+ 1. If |epsilon| is not a [=structured header/decimal=], return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/epsilon}} to |epsilon|.
+1. If |dict|["[=measure-conversion/lookback-days=]"] [=map/exists=]:
+ 1. Let |lookbackDays| be its [=map/value=].
+ 1. If |lookbackDays| is not a positive [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/lookbackDays}} to |lookbackDays|.
+1. If |dict|["[=measure-conversion/match-values=]"] [=map/exists=]:
+ 1. Let |matchValues| be its [=map/value=].
+ 1. If |matchValues| is not an [=structured header/inner list=], or if any of
+ |matchValues|' [=list/items=] is not a non-negative [=structured header/integer=],
+ return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/matchValues}} to |matchValues|.
+1. If |dict|["[=measure-conversion/impression-sites=]"] [=map/exists=]:
+ 1. Let |impressionSites| be its [=map/value=].
+ 1. If |impressionSites| is not an [=structured header/inner list=], or if any of
+ |impressionSites|' [=list/items=] is not a [=structured header/string=],
+ return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/impressionSites}} to |impressionSites|.
+1. If |dict|["[=measure-conversion/impression-callers=]"] [=map/exists=]:
+ 1. Let |impressionCallers| be its [=map/value=].
+ 1. If |impressionCallers| is not an [=structured header/inner list=], or if any of
+ |impressionCallers|' [=list/items=] is not a [=structured header/string=],
+ return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/impressionCallers}} to |impressionCallers|.
+1. If |dict|["[=measure-conversion/credit=]"] [=map/exists=]:
+ 1. Let |credit| be its [=map/value=].
+ 1. If |credit| is not an [=structured header/inner list=], or if any of
+ |credit|'s [=list/items=] is not a [=structured header/decimal=] or
+ [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/credit}} to |credit|.
+1. If |dict|["[=measure-conversion/value=]"] [=map/exists=]:
+ 1. Let |value| be its [=map/value=].
+ 1. If |value| is not a positive [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/value}} to |value|.
+1. If |dict|["[=measure-conversion/max-value=]"] [=map/exists=]:
+ 1. Let |maxValue| be its [=map/value=].
+ 1. If |maxValue| is not a positive [=structured header/integer=], return an error.
+ 1. Set |opts|.{{AttributionConversionOptions/maxValue}} to |maxValue|.
+1. Return (|opts|, |reportUrl|).
+
+