Decision records · Changes we propose
D-037 How is the ID of a record a party mints written, so that every party compares it the same way?
What we propose
A UUID in the RFC 9562 string form, which JSON Schema's uuid format checks.
As written
Every ID a party mints, and every reference to one, is any string, as the text types proposal_id and line_item_id: proposal_id, line_item_id, asset_id, correlation_id, idempotency_key, a commitment's proposal_id, requires' line items, and the id of every object option, which included[] and the pricing keys name it by.
The as-written variant takes the option opaque-string. Switch the type map to As written to see it.
Options
Why
The specification types these IDs as strings and says only that each is an identity. A party mints each one, and other parties and systems carry it back, so two independently minted IDs must not collide, and every party must compare an ID the same way. A UUID needs no coordination to be unique, and JSON Schema's uuid format checks its string form, which RFC 9562 reads without regard to case. An ID that another system keeps, such as a DSP seat or a registry entry, stays as that system writes it, and so does proposal_template_id, which links a proposal to the seller's own template and which the text calls opaque to buyers. A reference to a minted record, such as a commitment's proposal_id or requires.all_of[], carries the same identity, so it is a UUID too. With the open PRs, the text says an idempotency_key is opaque and that the seller MUST NOT interpret it. A UUID stays opaque: the schema checks only how it is written, and the seller still compares it for equality and reads nothing from it. The schema departs from the text, which lets the buyer write any string, and from the examples, which write readable names.
What we ask the specification to change
Write every ID a party mints as a UUID (RFC 9562), and every reference to one. That covers proposal_id, line_item_id, asset_id, correlation_id, idempotency_key, and the id of a property or an audience option. A UUID keeps idempotency_key opaque: a seller checks how it is written and compares it, and still reads nothing from it. The examples write readable names such as business-daily-display, which two sellers can mint alike.
The specification lines it rests on
Each line is quoted as the record pins it. Expand an item to read the quote.
main
§ 4.1, the
proposal_idrow L183 at 44dfaafproposal_id| String | immutable | Unique identity for the proposal object§ 5.1, the
line_item_idrow L217 at 44dfaafline_item_id| String | immutable | Identity within the proposal§ 5.10, the
correlation_idrow L350 at 44dfaafcorrelation_id| String | derived | One identity for this line item's commitment, carried across every system it touches§ 5.6.1, the
commitment.idempotency_keykey row L297 at 44dfaafidempotency_key| REQUIRED | Buyer-generated, unique per commitment attempt§ 5.4, the
assets[]row's description: the inline object L246 at 44dfaaf{ asset_id, format_ref, url_or_tag, submitted_at, approval_status }
§ 5.2, the
propertiesrow's description: the inline object L225 at 44dfaaf{ id, name, domains, supported_formats }
§ 5.3, the
audiencesrow's description: the inline object L233 at 44dfaaf{ id, name, taxonomy_ref, provenance, addressable_scale }
With the open PRs
§ 4.1, the
proposal_idrow L176 on main at 981a74eproposal_id| String | immutable | Unique identity for the proposal object§ 5.1, the
line_item_idrow L210 on main at 981a74eline_item_id| String | immutable | Identity within the proposal§ 5.10, the
correlation_idrow L343 on main at 981a74ecorrelation_id| String | derived | One identity for this line item's commitment, carried across every system it touches§ 5.6.1, the
commitment.idempotency_keykey row L290 on main at 981a74eidempotency_key| REQUIRED | Buyer-generated, unique per commitment attempt§ 5.6.1, a sentence L301 in #73
An
idempotency_keyis opaque and scoped to one buyer and seller pair.§ 5.6.1, a requirement L301 in #73
The seller MUST NOT interpret it.
§ 5.6.1, the
commitment.proposal_idkey row L291 in #73proposal_id| REQUIRED | The proposal the commitment is made against§ 5.6.3, the
requires.all_of[]key row L326 in #70all_of[]| Line items that MUST all be in the same commitment§ 5.6.3, the
requires.any_of[]key row L327 in #70any_of[]| Line items of which at least one MUST be in the same commitment§ 5.6.3, the
requires.min_commitment[]key row's meaning: the inline object L328 in #70{ line_item_id, basis, amount, currency }
§ 5.6.3, code block 1 L330-L336 in #70
requires: all_of: ["business-daily-display", "weather-app-ctv"] any_of: [] min_commitment: - { line_item_id: "business-daily-display", basis: spend, amount: 50000.00, currency: USD }
§ 5.4, the
assets[]row's description: the inline object L239 on main at 981a74e{ asset_id, format_ref, url_or_tag, submitted_at, approval_status }
§ 5.2, the
propertiesrow's description: the inline object L225 in #17{ id, name, domains, apps, supported_formats }
§ 5.3, the
audiencesrow's description: the inline object L226 on main at 981a74e{ id, name, taxonomy_ref, provenance, addressable_scale }
Examples that follow the text, not this change
| Example | Where | Why | Input |
|---|---|---|---|
code:5.6.3:1 | /requires/all_of/0 | The example follows the text, which states no form for all_of[]: it writes the readable name business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
code:5.6.3:1 | /requires/all_of/1 | The example follows the text, which states no form for all_of[]: it writes the readable name weather-app-ctv. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
code:5.6.3:1 | /requires/min_commitment/0/line_item_id | The example follows the text, which states no form for line_item_id: it writes the readable name business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-audio.yaml | /commitment/idempotency_key | The example follows the text, which states no form for idempotency_key: it writes the readable name agency-a-camp1-streaming-audio-a7c33e10. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-audio.yaml | /commitment/proposal_id | The example follows the text, which states no form for proposal_id: it writes the readable name examplepub-us-q4-2026-omni. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-audio.yaml | /correlation_id | The example follows the text, which types correlation_id as a String: it writes the readable name ep-q4-2026-commitment/streaming-audio. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-audio.yaml | /line_item_id | The example follows the text, which types line_item_id as a String: it writes the readable name streaming-audio. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-audio.yaml | /production/available/0/id | The example follows the text, which gives a production option no id: the example writes one, the readable name seller_built, as every object option carries. We propose a UUID for every ID a party mints, an object option's id included, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-audio.yaml | /production/available/1/id | The example follows the text, which gives a production option no id: the example writes one, the readable name buyer_supplied, as every object option carries. We propose a UUID for every ID a party mints, an object option's id included, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-audio.yaml | /production/included/0 | The example follows the text, which gives a production option no id: the example writes one, the readable name buyer_supplied, and included[] names the option by it. We propose a UUID id for every object option, as for every ID a party mints, so included[] names the option by that UUID. | main, open PRs |
examples/line-item-audio.yaml | /production/pricing | The example follows the text, which gives a production option no id: the example writes one, the readable name seller_built, and the pricing keys name the option by it. We propose a UUID id for every object option, as for every ID a party mints, so the pricing keys name the option by that UUID. | main, open PRs |
examples/line-item-ctv-bonus.yaml | /line_item_id | The example follows the text, which types line_item_id as a String: it writes the readable name weather-app-ctv-bonus. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-ctv-bonus.yaml | /properties/available/0 | The example follows the text, which states no form for an option's id: it writes the readable name weather-app. We propose a UUID for every ID a party mints, a catalog entry's id included. | open PRs |
examples/line-item-ctv-bonus.yaml | /properties/included/0 | The example follows the text, which states no form for an option's id: included[] names the property by the readable ID weather-app its available[] gives it. We propose a UUID for every ID a party mints, an option's id included, so included[] names the property by that UUID. | open PRs |
examples/line-item-ctv-bonus.yaml | /requires/all_of/0 | The example follows the text, which states no form for all_of[]: it writes the readable name business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-ctv-bonus.yaml | /requires/all_of/1 | The example follows the text, which states no form for all_of[]: it writes the readable name weather-app-ctv. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-ctv-bonus.yaml | /requires/min_commitment/0/line_item_id | The example follows the text, which states no form for line_item_id: it writes the readable name business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-ctv.yaml | /commitment/idempotency_key | The example follows the text, which states no form for idempotency_key: it writes the readable name agency-a-camp1-weather-app-ctv-3b7e0d52. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-ctv.yaml | /commitment/proposal_id | The example follows the text, which states no form for proposal_id: it writes the readable name examplepub-us-q4-2026-omni. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-ctv.yaml | /correlation_id | The example follows the text, which types correlation_id as a String: it writes the readable name ep-q4-2026-commitment/weather-app-ctv. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-ctv.yaml | /line_item_id | The example follows the text, which types line_item_id as a String: it writes the readable name weather-app-ctv. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-ctv.yaml | /properties/available/0 | The example follows the text, which states no form for an option's id: it writes the readable name weather-app. We propose a UUID for every ID a party mints, a catalog entry's id included. | main, open PRs |
examples/line-item-ctv.yaml | /properties/included/0 | The example follows the text, which states no form for an option's id: included[] names the property by the readable ID weather-app its available[] gives it. We propose a UUID for every ID a party mints, an option's id included, so included[] names the property by that UUID. | main, open PRs |
examples/line-item-display.yaml | /audiences/available/1 | The example follows the text, which states no form for an option's id and lists no terms for provenance: it writes the readable name ep:hnw-investors and the term modeled. We propose a UUID for every ID a party mints, a catalog entry's id included. We also propose namespaced terms in a field until the specification lists its core terms. | main, open PRs |
examples/line-item-display.yaml | /audiences/available/2 | The example follows the text, which states no form for an option's id and lists no terms for provenance: it writes the readable name ep:cfo-finance-leaders and the term first_party. We propose a UUID for every ID a party mints, a catalog entry's id included. We also propose namespaced terms in a field until the specification lists its core terms. | main, open PRs |
examples/line-item-display.yaml | /audiences/included/0 | The example follows the text, which states no form for an option's id: included[] writes the readable ID ep:smb-decision-makers. We propose a UUID for every ID a party mints. The entry names the option given as the catalog reference examplepub/audiences/smb-decision-makers@3, though, and that option carries no id, so a UUID alone doesn't name it either. What names an option given as a catalog reference is a point the text leaves open, listed with the examples that disagree with the text. | main, open PRs |
examples/line-item-display.yaml | /audiences/pricing | The example follows the text, which states no form for an option's id: the pricing keys name the audiences by the readable IDs ep:cfo-finance-leaders and ep:hnw-investors their available[] gives them. We propose a UUID for every ID a party mints, an option's id included, so the pricing keys name each audience by that UUID. | main, open PRs |
examples/line-item-display.yaml | /commitment/idempotency_key | The example follows the text, which states no form for idempotency_key: it writes the readable name agency-a-camp1-business-daily-display-8f42c1a9. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-display.yaml | /commitment/proposal_id | The example follows the text, which states no form for proposal_id: it writes the readable name examplepub-us-q4-2026-omni. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-display.yaml | /correlation_id | The example follows the text, which types correlation_id as a String: it writes the readable name ep-q4-2026-commitment/business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-display.yaml | /line_item_id | The example follows the text, which types line_item_id as a String: it writes the readable name business-daily-display. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
examples/line-item-display.yaml | /measurement_source/included/0 | The example follows the text, which gives a measurement source option no id: included[] names the option by its vendor, IAS, which no option of available[] carries as its id. We propose an id on every object option, a UUID as for every ID a party mints, so that included[] names the option by that UUID. | main, open PRs |
examples/line-item-display.yaml | /properties/available/0 | The example follows the text, which states no form for an option's id: it writes the readable name business-daily. We propose a UUID for every ID a party mints, a catalog entry's id included. | main, open PRs |
examples/line-item-display.yaml | /properties/available/1 | The example follows the text, which states no form for an option's id: it writes the readable name markets-weekly. We propose a UUID for every ID a party mints, a catalog entry's id included. | main, open PRs |
examples/line-item-display.yaml | /properties/included/0 | The example follows the text, which states no form for an option's id: included[] names the property by the readable ID business-daily its available[] gives it. We propose a UUID for every ID a party mints, an option's id included, so included[] names the property by that UUID. | main, open PRs |
examples/line-item-display.yaml | /properties/pricing | The example follows the text, which states no form for an option's id: the pricing keys name the property by the readable ID markets-weekly its available[] gives it. We propose a UUID for every ID a party mints, an option's id included, so the pricing keys name the property by that UUID. | main, open PRs |
examples/line-item-display.yaml | /reporting/included/0 | The example follows the text, which gives a reporting option no id: included[] names the option by its feed_type, aggregate, which no option of available[] carries as its id. We propose an id on every object option, a UUID as for every ID a party mints, so that included[] names the option by that UUID. | main, open PRs |
examples/line-item-display.yaml | /reporting/pricing | The example follows the text, which gives a reporting option no id: the pricing keys name the option by its feed_type, log_level. We propose an id on every object option, a UUID as for every ID a party mints, so that the pricing keys name the option by that UUID. | main, open PRs |
examples/line-item-rewarded-video.yaml | /line_item_id | The example follows the text, which types line_item_id as a String: it writes the readable name puzzle-games-rewarded. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/line-item-rewarded-video.yaml | /measurement_source/included/0 | The example follows the text, which gives a measurement source option no id: included[] names the option by its vendor, IAS, which no option of available[] carries as its id. We propose an id on every object option, a UUID as for every ID a party mints, so that included[] names the option by that UUID. | open PRs |
examples/line-item-rewarded-video.yaml | /properties/available/0 | The example follows the text, which states no form for an option's id: it writes the readable name puzzle-pack. We propose a UUID for every ID a party mints, a catalog entry's id included. | open PRs |
examples/line-item-rewarded-video.yaml | /properties/included/0 | The example follows the text, which states no form for an option's id: included[] names the property by the readable ID puzzle-pack its available[] gives it. We propose a UUID for every ID a party mints, an option's id included, so included[] names the property by that UUID. | open PRs |
examples/manifest.json | /proposals/0/proposal_id | The example follows the text, which types proposal_id as a String: it writes the readable name examplepub-us-q4-2026-omni. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | open PRs |
examples/proposal.yaml | /proposal_id | The example follows the text, which types proposal_id as a String: it writes the readable name examplepub-us-q4-2026-omni. We propose a UUID for every ID a party mints, such as 7c9e6679-7425-40de-944b-e07fc1f90ae7. | main, open PRs |
What it shapes
main: Uuid, AssetsEntry.approval_status, AssetsEntry.asset_id, AssetsEntry.format_ref, AssetsEntry.submitted_at, AssetsEntry.url_or_tag, AudiencesOption.addressable_scale, AudiencesOption.id, AudiencesOption.name, AudiencesOption.provenance, AudiencesOption.taxonomy_ref, Commitment.idempotency_key, LineItem.correlation_id, LineItem.line_item_id, LineItemSummaryPropertiesOption.name, PropertiesOption.domains, PropertiesOption.id, PropertiesOption.name, PropertiesOption.supported_formats, Proposal.proposal_id
With the open PRs: Uuid, AssetsEntry.approval_status, AssetsEntry.asset_id, AssetsEntry.format_ref, AssetsEntry.submitted_at, AssetsEntry.url_or_tag, AudiencesOption.addressable_scale, AudiencesOption.id, AudiencesOption.name, AudiencesOption.provenance, AudiencesOption.taxonomy_ref, Commitment.idempotency_key, Commitment.proposal_id, LineItem.correlation_id, LineItem.line_item_id, LineItemSummaryPropertiesOption.name, MinCommitmentEntry.amount, MinCommitmentEntry.basis, MinCommitmentEntry.currency, MinCommitmentEntry.line_item_id, PropertiesOption.apps, PropertiesOption.domains, PropertiesOption.id, PropertiesOption.name, PropertiesOption.supported_formats, Proposal.proposal_id, Requires.all_of, Requires.any_of