Guides

Migrating to SupplyChain v1.1: hp=0 custody nodes, checklist and pitfalls

SupplyChain has been at version 1.0 since 2019, which is long enough that most implementations treat its rules as facts rather than as one document's decisions. Version 1.1 is in public comment and changes the one rule everybody hardcoded: that every node in the chain is in the payment flow. This is the migration checklist, for both sides of an integration.

The change, in one sentence

Entities that take technical custody of a bid request but never touch the money can now appear in the same nodes array as everybody else, marked with hp=0.

It is the smallest change that could work. No parallel array, no new object type, no extension field. The systems it names are already in every path and disclosed in none of them: header bidding wrappers, publisher ad servers, server-side ad insertion platforms, SDKs.

Why the field was inert

hp has always been a required integer on every node: 1 for in the payment flow, 0 for not. But 1.0 also says the property should always be 1, so it has been a boolean with one legal value for six years. Builders hardcode it, validators assert it, and buy-side audit walks every node against sellers.json because in a 1.0 chain every node is a seller account. Those three habits are what the migration is about. Field definitions are in the schain reference.

What else moves with it

  • ver carries a new value, so any comparison against the literal string 1.0 needs to accept 1.1 or reject it loudly.
  • complete gains new enumerations, so the flag stops being a plain boolean. Read the final text before branching on it.
  • ads.txt scope narrows. Custody nodes are not expected to pass ads.txt validation. Referencing a sellers.json entry for a non-payment handler is described as strongly recommended rather than required.
  • sellers.json wording changes around the INTERMEDIARY seller type and the is_passthrough parameter.
  • Documentation moves. Implementation guidance consolidates into the Supply-Chain-Validation repository and the original OpenRTB Supply Chain Object page is deprecated.

If you build chains (sell side, wrappers, SSAI, SDKs)

  1. Find every hardcoded hp: 1. Each one is now a claim your code has not evaluated. Decide per system whether it is in the payment flow and make the answer configuration rather than a constant.
  2. Decide whether you are a custody node. If your system receives and forwards a bid request without being paid for the inventory, you are exactly what hp=0 was added to describe. Appending your node is the point of the release.
  3. Append once. Longer chains mean more appenders and more chances that two systems write the same hop. Adjacent duplicate nodes fail path checks and read as padding. RTBlint reports it as openrtb.schain.duplicate_node.
  4. Publish a sellers.json entry for the custody identity. Not required, strongly recommended, and the difference between a node a buyer can resolve and one that makes your chain look unverifiable.
  5. Never emit a placeholder. An empty asi or sid satisfies a schema check and identifies nothing. Fail the node instead. That is openrtb.schain.node.identifier_empty, and it is an error rather than a warning because one broken node poisons the whole chain.
  6. Coordinate the version bump. The rollout guidance is staged testing with a receiving partner, not a unilateral switch.

If you read chains (buy side, SPO, verification)

  1. Accept ver 1.1 or reject it with a logged reason. The option you cannot afford is the third one, where an unrecognised version routes the chain into an unhandled branch and the request proceeds without it. RTBlint flags unexpected values as openrtb.schain.ver_unexpected.
  2. Split hop counting from money counting. Any policy phrased as reject chains longer than N has to say which N it means before longer chains start arriving. If the policy is about extraction, count hp=1 nodes.
  3. Scope ads.txt authorization to the payment path. Running it over hp=0 nodes manufactures violations that are artifacts of your own reader.
  4. Stop requiring every node to resolve in sellers.json. Reasonable under 1.0, too strict under 1.1.
  5. Re-baseline your supply path scoring. A partner that adopts 1.1 will suddenly present a longer chain for identical inventory. If your model penalises length without filtering on hp, you will down-rank the partners who disclosed more.
  6. Use the custody data. Duplicate bid detection gets materially better when the same request arriving by two routes carries evidence of which systems it crossed.

What to grep for

The migration is mostly a search-and-decide exercise, and these five patterns find almost all of it in a typical stack:

hp.*[:=]\s*1          # hardcoded payment-flow claims
"1\.0"                # ver comparisons that will reject 1.1
schain.*length        # hop-count policies that need an hp filter
adsTxt|ads_txt        # authorization checks to scope to hp=1
sellers\.json         # per-node resolution that should stop being required

Every hit is a decision rather than a mechanical replacement, which is why this is worth doing before a partner starts sending 1.1 chains rather than during the incident that follows.

The chain before and after

1.0  (publisher ad server, SSAI, exchange: only two get paid)
"nodes": [
  { "asi": "pubadserver.example", "sid": "8842",   "hp": 1 },
  { "asi": "exchange.example",    "sid": "pub-42", "hp": 1 }
]

1.1  (same path, custody disclosed)
"nodes": [
  { "asi": "pubadserver.example", "sid": "8842",   "hp": 1 },
  { "asi": "ssai.example",        "sid": "net-19", "hp": 0 },
  { "asi": "exchange.example",    "sid": "pub-42", "hp": 1 }
]

The second chain is longer and more honest. Whether that is rewarded or punished depends entirely on what the reader on the other end does with length, which is why the reader checklist above matters as much as the builder one.

Where to check and where to comment

Paste a request into the bid request tester, run the CLI over a corpus of what you emit today, or give an agent the MCP server so it validates its own output. Background on the surrounding artifacts is in the supply chain trust stack and the field reference is at the schain doc. The analysis of what breaks is in the post on nodes that never touch the money.

Public comment runs through 21 August 2026 in the Supply-Chain-Validation repository, which carries sub-issues for the open questions. A parser-level objection lands better there than in a support ticket six months from now.