RTB Architecture

    Schain, ads.txt and sellers.json together: how a buyer verifies a supply path, node by node

    Published · Last updated
    Next scheduled review:

    The SupplyChain object, or schain, lists every seller that handled a bid request. ads.txt shows which seller accounts a publisher authorised, and sellers.json shows which company owns each account. A buyer joins the three on two keys, the system domain and the seller ID, to check the path before bidding.

    Contents

    Key facts

    • The two newer standards are twins. IAB Tech Lab's OpenRTB working group finalised sellers.json and the SupplyChain object together on 31 July 2019, both at version 1.0 (IAB Tech Lab, sellers.json page). ads.txt reached version 1.1 in 2022 (ads.txt 1.1).
    • Carrying a chain is not the same as passing checks. A HUMAN Security diagnostic of 1 November 2023 found that 79% of requests carried a SupplyChain object, but only 42% of those objects passed full validation (vendor figures, reported by PPC Land, 6 September 2026).
    • IAB Tech Lab wants a chain on every request. Its Programmatic Best Practices draft of 16 September 2026 says: "Support schain and ensure an schain object is included in each bid request" (public comment draft).
    • Version 1.1 is in draft. A development branch of IAB Tech Lab's Supply-Chain-Validation repository holds SupplyChain 1.1 and sellers.json 1.1 texts dated June and July 2026. They add unpaid "technical hops" and are not released (dev branch commits).
    • Signing is not part of the daily check. IAB Tech Lab's page, last updated 14 February 2024, calls ads.cert 2.0 "ready for adoption". OpenRTB 2.6 has no field for it (IAB Tech Lab, ads.cert).
    Jump to the table

    Definition

    Supply path verification: the check a buyer runs on each SupplyChain node in a bid request. It confirms that the node's seller account exists in the advertising system's sellers.json and is authorised in the publisher's ads.txt, and that every node links to the one before it. See the glossary entries for the SupplyChain object, sellers.json and ads.txt.

    sellers.json vs ads.txt vs schain: who publishes what

    Each standard answers a different question, and each is published by a different party. That separation is the point. A fraudster would have to forge three independent records at once.

    6 of 6 rows

    Columns (4)

    Published by

    The publisher or app developer

    Each SSP, exchange or other advertising system

    Each seller, inside the bid request

    Location

    /ads.txt on the site's root domain; /app-ads.txt on the developer domain

    /sellers.json on the system's root domain

    source.schain in OpenRTB 2.6

    Question it answers

    Which accounts may sell my inventory?

    Who is the company behind each account I pay?

    Which accounts did this request pass through?

    Key fields

    System domain, account ID, DIRECT or RESELLER, OWNERDOMAIN, MANAGERDOMAIN

    seller_id, seller_type, name, domain

    complete, nodes[] with asi, sid, hp

    Current version

    1.1

    1.0 (1.1 in draft)

    1.0 (1.1 in draft)

    Changes

    When a seat is added or dropped

    When a seller signs up or leaves

    On every request

    Published by

    ads.txt (and app-ads.txt)

    The publisher or app developer

    sellers.json

    Each SSP, exchange or other advertising system

    SupplyChain object (schain)

    Each seller, inside the bid request

    Location

    ads.txt (and app-ads.txt)

    /ads.txt on the site's root domain; /app-ads.txt on the developer domain

    sellers.json

    /sellers.json on the system's root domain

    SupplyChain object (schain)

    source.schain in OpenRTB 2.6

    Question it answers

    ads.txt (and app-ads.txt)

    Which accounts may sell my inventory?

    sellers.json

    Who is the company behind each account I pay?

    SupplyChain object (schain)

    Which accounts did this request pass through?

    Key fields

    ads.txt (and app-ads.txt)

    System domain, account ID, DIRECT or RESELLER, OWNERDOMAIN, MANAGERDOMAIN

    sellers.json

    seller_id, seller_type, name, domain

    SupplyChain object (schain)

    complete, nodes[] with asi, sid, hp

    Current version

    ads.txt (and app-ads.txt)

    1.1

    sellers.json

    1.0 (1.1 in draft)

    SupplyChain object (schain)

    1.0 (1.1 in draft)

    Changes

    ads.txt (and app-ads.txt)

    When a seat is added or dropped

    sellers.json

    When a seller signs up or leaves

    SupplyChain object (schain)

    On every request

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    The file formats, field rules and crawler behaviour are explained on our ads.txt and sellers.json validator page, which also checks your files. This page stays on the combination: how a buyer joins the three, and what breaks the join.

    The join keys: how the three standards connect

    Three keys link the records, and two more fields tell you how to read the result. The sellers.json specification says seller_id "is the same ID that appears in an ads.txt file and in the SupplyChain.nodes array sid property", and "in most cases" also in publisher.id (sellers.json 1.0).

    5 of 5 rows

    Columns (5)

    Advertising system

    asi

    Field 1

    Host of the file (https://{asi}/sellers.json)

    The exchange that sent it, for the last node

    Seller account

    sid

    Field 2

    seller_id

    site.publisher.id or app.publisher.id, for the last node

    Previous hop

    The asi of the node before

    n/a

    domain of an INTERMEDIARY seller

    n/a

    Ownership

    First node

    OWNERDOMAIN, MANAGERDOMAIN

    domain of a PUBLISHER seller

    site.domain or the app bundle

    Relationship

    n/a

    DIRECT or RESELLER

    seller_type PUBLISHER, INTERMEDIARY or BOTH

    n/a

    Advertising system

    In schain

    asi

    In ads.txt

    Field 1

    In sellers.json

    Host of the file (https://{asi}/sellers.json)

    In the bid request

    The exchange that sent it, for the last node

    Seller account

    In schain

    sid

    In ads.txt

    Field 2

    In sellers.json

    seller_id

    In the bid request

    site.publisher.id or app.publisher.id, for the last node

    Previous hop

    In schain

    The asi of the node before

    In ads.txt

    n/a

    In sellers.json

    domain of an INTERMEDIARY seller

    In the bid request

    n/a

    Ownership

    In schain

    First node

    In ads.txt

    OWNERDOMAIN, MANAGERDOMAIN

    In sellers.json

    domain of a PUBLISHER seller

    In the bid request

    site.domain or the app bundle

    Relationship

    In schain

    n/a

    In ads.txt

    DIRECT or RESELLER

    In sellers.json

    seller_type PUBLISHER, INTERMEDIARY or BOTH

    In the bid request

    n/a

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    The "previous hop" key is easy to miss. For an INTERMEDIARY or BOTH seller, the sellers.json domain "should be the root domain name of the seller's Sellers.json file" (sellers.json 1.0). So when a reseller sells into an exchange, the exchange's entry for it points back to the reseller's own system, which is the asi of the node before.

    A complete chain, verified end to end

    Here is one impression bought through a reseller. Example Media GmbH owns news.example. It sells through its seat pub-1047 on SSP Alpha. SSP Alpha resells the impression into Exchange Beta, where SSP Alpha holds seat 88123. Exchange Beta sends the request to the buyer. All names use the reserved .example domain.

    The bid request (OpenRTB 2.6). Exchange Beta is the sender, so its node is last and its seat matches publisher.id.

    {
      "id": "e7a1c3d5-2b4f-4a69-8c10-9d3e5f7a1b2c",
      "imp": [
        { "id": "1", "banner": { "format": [{ "w": 300, "h": 250 }] } }
      ],
      "site": {
        "domain": "news.example",
        "page": "https://news.example/markets/rates",
        "publisher": { "id": "88123" }
      },
      "source": {
        "tid": "0b7d3e9a-6c21-4f58-9e04-3a1c8b5d7f92",
        "schain": {
          "ver": "1.0",
          "complete": 1,
          "nodes": [
            { "asi": "ssp-alpha.example", "sid": "pub-1047", "rid": "a91f0c77", "hp": 1 },
            { "asi": "exchange-beta.example", "sid": "88123", "rid": "e7a1c3d5-2b4f-4a69-8c10-9d3e5f7a1b2c", "hp": 1 }
          ]
        }
      },
      "at": 1,
      "tmax": 300
    }

    6 of 6 rows

    Columns (3)

    complete

    1

    Every node back to the inventory owner is present

    nodes[0]

    ssp-alpha.example, pub-1047

    The first sale: the publisher's own seat on SSP Alpha

    nodes[1]

    exchange-beta.example, 88123

    The resale: SSP Alpha's seat on Exchange Beta; last node = sender

    rid

    Each seller's own request ID

    Lets each seller trace its leg in logs

    hp

    1 on both

    Both nodes are in the payment flow, as version 1.0 requires

    site.publisher.id

    88123

    Matches the last node's sid

    complete

    Value

    1

    What it claims

    Every node back to the inventory owner is present

    nodes[0]

    Value

    ssp-alpha.example, pub-1047

    What it claims

    The first sale: the publisher's own seat on SSP Alpha

    nodes[1]

    Value

    exchange-beta.example, 88123

    What it claims

    The resale: SSP Alpha's seat on Exchange Beta; last node = sender

    rid

    Value

    Each seller's own request ID

    What it claims

    Lets each seller trace its leg in logs

    hp

    Value

    1 on both

    What it claims

    Both nodes are in the payment flow, as version 1.0 requires

    site.publisher.id

    Value

    88123

    What it claims

    Matches the last node's sid

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    The publisher's ads.txt at news.example.

    # news.example/ads.txt
    OWNERDOMAIN=examplemedia.example
    ssp-alpha.example, pub-1047, DIRECT
    exchange-beta.example, 88123, RESELLER

    SSP Alpha's sellers.json lists the publisher's seat as a PUBLISHER account.

    {
      "version": "1.0",
      "contact_email": "supply@ssp-alpha.example",
      "sellers": [
        {
          "seller_id": "pub-1047",
          "seller_type": "PUBLISHER",
          "name": "Example Media GmbH",
          "domain": "examplemedia.example"
        }
      ]
    }

    Exchange Beta's sellers.json lists SSP Alpha's seat as an INTERMEDIARY whose domain is SSP Alpha's own system.

    {
      "version": "1.0",
      "contact_email": "sellers@exchange-beta.example",
      "sellers": [
        {
          "seller_id": "88123",
          "seller_type": "INTERMEDIARY",
          "name": "SSP Alpha Inc.",
          "domain": "ssp-alpha.example"
        }
      ]
    }

    The verification, check by check.

    7 of 7 rows

    Columns (4)

    1

    Last node is the sender

    nodes[1].asi = Exchange Beta; nodes[1].sid = publisher.id 88123

    Pass

    2

    Last node exists in sellers.json

    exchange-beta.example/sellers.json has 88123, INTERMEDIARY

    Pass

    3

    Hops link up

    Seller 88123's domain ssp-alpha.example = nodes[0].asi

    Pass

    4

    First node exists in sellers.json

    ssp-alpha.example/sellers.json has pub-1047, PUBLISHER

    Pass

    5

    First node is the owner

    Seller pub-1047's domain examplemedia.example = OWNERDOMAIN

    Pass: owner found, so complete 1 is believable

    6

    ads.txt authorises node 1

    Line ssp-alpha.example, pub-1047, DIRECT; DIRECT pairs with PUBLISHER

    Pass

    7

    ads.txt authorises node 2

    Line exchange-beta.example, 88123, RESELLER; RESELLER pairs with INTERMEDIARY

    Pass

    1

    Check

    Last node is the sender

    Data compared

    nodes[1].asi = Exchange Beta; nodes[1].sid = publisher.id 88123

    Result

    Pass

    2

    Check

    Last node exists in sellers.json

    Data compared

    exchange-beta.example/sellers.json has 88123, INTERMEDIARY

    Result

    Pass

    3

    Check

    Hops link up

    Data compared

    Seller 88123's domain ssp-alpha.example = nodes[0].asi

    Result

    Pass

    4

    Check

    First node exists in sellers.json

    Data compared

    ssp-alpha.example/sellers.json has pub-1047, PUBLISHER

    Result

    Pass

    5

    Check

    First node is the owner

    Data compared

    Seller pub-1047's domain examplemedia.example = OWNERDOMAIN

    Result

    Pass: owner found, so complete 1 is believable

    6

    Check

    ads.txt authorises node 1

    Data compared

    Line ssp-alpha.example, pub-1047, DIRECT; DIRECT pairs with PUBLISHER

    Result

    Pass

    7

    Check

    ads.txt authorises node 2

    Data compared

    Line exchange-beta.example, 88123, RESELLER; RESELLER pairs with INTERMEDIARY

    Result

    Pass

    Download JSON

    Table by AdSovereign, CC BY 4.0.

    The rules behind checks 5 to 7 come from IAB Tech Lab's implementation guidance. It tells buyers to compare the sellers.json domain with OWNERDOMAIN for an owner and with MANAGERDOMAIN for a manager, and to treat any other domain as a reseller. It also expects that, for inventory sold by a manager, "the domain listed in MANAGERDOMAIN is also that of the node representing the originating publisher in a complete supply chain object".

    An incomplete chain, and what a buyer can still check

    A chain is incomplete when an upstream seller did not support the object. The specification tells the first seller that does support it to create the object, set complete to 0 and add its own node (SupplyChain object, implementation details). The request below is the same impression arriving with only Exchange Beta's node.

    {
      "id": "5d2e8b10-7a4c-4f93-b6e1-0c9a3f5d7e28",
      "imp": [
        { "id": "1", "banner": { "format": [{ "w": 300, "h": 250 }] } }
      ],
      "site": {
        "domain": "news.example",
        "publisher": { "id": "88123" }
      },
      "source": {
        "schain": {
          "ver": "1.0",
          "complete": 0,
          "nodes": [
            { "asi": "exchange-beta.example", "sid": "88123", "rid": "5d2e8b10-7a4c-4f93-b6e1-0c9a3f5d7e28", "hp": 1 }
          ]
        }
      },
      "at": 1,
      "tmax": 300
    }

    The buyer can still run checks 1, 2 and 7: Exchange Beta sent it, seat 88123 exists, and the publisher's ads.txt lists the seat as RESELLER. It cannot see who sold to SSP Alpha's seat, or whether the owner is in the path at all. A buyer can price that gap or skip the impression. A buyer that declines can say why with no-bid reason 16, "Incomplete SupplyChain", from the list that OpenRTB 2.6 points to (OpenRTB 3.0, List: No-Bid Reason Codes):

    { "id": "5d2e8b10-7a4c-4f93-b6e1-0c9a3f5d7e28", "seatbid": [], "nbr": 16 }

    Code 17, "Blocked SupplyChain Node", covers the other common decision: the chain is complete but contains a seller the buyer refuses to pay. Codes 11 and 12 report ads.txt authorisation that is unavailable or violated.

    Seven checks a buyer runs on every node

    The worked example generalises into a routine. Run it from the last node backwards, because the last node is the only one you can tie to the connection you received.

    1. Parse and sanity-check the object. The ver field reads "1.0" and complete is 0 or 1. Every node has asi, sid and hp set to 1. Each sid is at most 64 characters, and each asi is a root domain without https:// (OpenRTB 2.6, SupplyChainNode).
    2. Tie the last node to the sender. Its asi must be the exchange you are connected to, and its sid must equal site.publisher.id or app.publisher.id.
    3. Look up each node in sellers.json. Fetch https://{asi}/sellers.json from cache and find seller_id equal to sid. A missing entry makes the node unverifiable; a confidential entry hides the name but still proves the seat exists.
    4. Link each hop to the one before. For node n, an INTERMEDIARY or BOTH seller's domain should equal the asi of node n-1.
    5. Find the owner. When complete is 1, the first node's seller should be PUBLISHER or BOTH, with a domain that matches ads.txt OWNERDOMAIN, or MANAGERDOMAIN for the right country.
    6. Check authorisation in ads.txt or app-ads.txt. Each paid node's asi and sid should appear as field 1 and field 2. DIRECT should pair with PUBLISHER, RESELLER with INTERMEDIARY.
    7. Apply passthrough and policy rules. If the last node is is_passthrough 1, the spec expects you to hold an account relationship with that seller. Then apply your own blocklist, and log the outcome with the request ID.

    Steps 3 to 6 depend on files you crawl, not on the request, so cache them. The specifications tell consumers to honour HTTP Expires headers and otherwise refresh after 7 days (sellers.json 1.0). Supply path teams then use the results to rank paths, which is the subject of demand path optimization and of supply path optimization in general.

    Where schain sits, and who adds the nodes

    The object is the same in every version; only its address changes. OpenRTB 2.6 puts it in source.schain, 2.5 in source.ext.schain, and 2.4 or earlier in ext.schain (SupplyChain object). Prebid Server converts between the 2.5 and 2.6 locations in both directions (convert_up.go). Google's OpenRTB guide documents source.schain (Google Authorized Buyers). The full version comparison is in OpenRTB 2.5 vs 2.6 vs 3.0, and the field in context in OpenRTB 2.6 explained.

    Who adds a node follows one rule: each seller appends itself and never removes others. The specification calls it invalid for a reseller to copy the object without inserting its own node (SupplyChain object). An SSP cannot add an upstream intermediary it does not know about, so the publisher or its wrapper operator must declare it. Prebid's documentation says this directly for managed Prebid.js setups (Prebid schain module).

    Prebid.js changed how that declaration works in version 10, released on 1 July 2025 (Prebid.js 10.0.0). Since then the schain is treated as first-party data: the module copies its config into ortb2.source.ext.schain, and ortb2.source.schain takes precedence if both are set. A bidder-specific chain is now merged after the global nodes. Prebid.js 11.45 added firstPartyData.replaceGlobalSchain to restore the old replace behaviour (Prebid schain module). Header bidding setups in general are covered in header bidding explained, and server-side hosting in the Prebid Server self-hosting guide.

    For VAST tags and other non-OpenRTB calls, the chain is serialised into one URL parameter, schain, with nodes separated by !. The exact format and an example are on the validator page. CTV stitching adds its own wrinkles, described in SSAI and CTV ad serving.

    SupplyChain 1.1: the draft that adds technical hops

    Version 1.0 lists only companies in the payment flow. A server-side wrapper, an open bidding provider or an SSAI platform can route the request without being paid by the next node, so it never appears. The draft 1.1 text changes that. It says the chain "discloses any entity that has custody of the bid request", which it calls "technical hops", and marks unpaid hops with hp 0 (dev branch implementation guidance).

    The draft also sets new rules. Order follows the outbound sequence. Two consecutive hp 0 nodes from the same company collapse into one. No ads.txt entry is required for hp 0 nodes, but a sellers.json entry is "strongly recommended" for every node. Its examples cover web wrappers, mobile SDKs and six CTV paths. A paired draft renames the sellers.json file to version 1.1 (commit of 18 June 2026).

    Treat this as a preview. On 9 November 2026 the 1.1 texts lived only in the dev branch, and IAB Tech Lab's public comment page did not list them (IAB Tech Lab, releases in public comment). If you validate chains, make hp 0 a warning rather than an error now, so the day 1.1 ships does not break your parser.

    ads.cert: where signing stands in November 2026

    The three files prove who is allowed to sell. They do not prove that a request really came from the system named in the last node. Cryptographic signing was meant to close that gap, and it has had two lives.

    The first, ads.cert 1.0 "Signed Bid Requests", lived inside OpenRTB 3.0 as the ds, dsmap, cert and digest fields of the Source object. The 3.0 text says these "should be considered" beta, like the ads.cert document itself (OpenRTB 3.0, Object: Source). The fields exist only in 3.0, so OpenRTB 2.x traffic cannot carry them.

    The second, ads.cert 2.0, signs the HTTP connection rather than the payload. Companies publish keys in DNS as "Call Signs", and "Authenticated Connections" signs server-to-server calls of any format.

    IAB Tech Lab's page says Authenticated Connections "is ready for adoption", lists Authenticated Delivery and Authenticated Devices as future work, and was last updated on 14 February 2024 (IAB Tech Lab, ads.cert). The open-source code was last pushed on 5 July 2023 (IABTechLab/adscert). Index Exchange described a proof of concept with Publica, Google Display & Video 360 and Oracle Moat in January 2022 (IAB Tech Lab blog, 27 January 2022). We found no public adoption figures.

    Without signing, the seven checks above and each buyer's own fraud signals are what remains. Signing is an option between partners who agree on it.

    Common mistakes

    1. Copying the chain without adding your node. The specification calls this invalid. If you resell and cannot add yourself, drop the object instead.
    2. Setting complete to 1 when you created the object mid-path. Only the originating seller may start a chain with complete 1. A reseller that builds a missing chain must use 0.
    3. A last sid that differs from publisher.id. Buyers tie the chain to the connection through this match. Different IDs for the same seat break check 2.
    4. asi written as a URL or a subdomain. Use the root domain, the same value as ads.txt field 1, for example ssp-alpha.example, not https://bid.ssp-alpha.example.
    5. A seat missing from sellers.json. Every system named in a node should publish an entry for its sid. A missing entry turns a valid chain into an unverifiable one.
    6. An intermediary domain that does not point back. For INTERMEDIARY and BOTH sellers, domain should be the root domain of that seller's own sellers.json, so the hop can be linked.
    7. DIRECT lines for seats the publisher does not control. IAB Tech Lab's guidance tells SSPs to check field 3 because they know the real relationship (implementation guidance).
    8. Two chains in one request. Sending source.schain and source.ext.schain with different nodes leaves the buyer guessing. Mirror one value.
    9. Bidder-specific chains in Prebid.js after an upgrade. Since Prebid.js 10 they merge with the global chain, so a node can appear twice if you configured both. Check the output or set replaceGlobalSchain on 11.45 or later.
    10. Rejecting hp 0 outright. Version 1.0 requires hp 1, but the 1.1 draft introduces hp 0 for technical hops. Flag it; do not crash on it.

    Files can be generated with the ads.txt generator and checked with the validator. Running your own exchange adds a sellers.json of your own, covered in the private ad exchange setup guide. The publisher independence hub collects the related pages.

    FAQ

    What is schain in OpenRTB?
    It is the SupplyChain object, a list of every seller account that handled the bid request, in order. Each node gives the advertising system's domain (asi), the seller's account ID there (sid) and whether the node is in the payment flow (hp). In OpenRTB 2.6 it sits in source.schain (OpenRTB 2.6).
    What is the difference between sellers.json and ads.txt?
    The publisher writes ads.txt to authorise accounts; each exchange writes sellers.json to identify the companies behind the accounts it pays. The first is a text file on the site's domain, and the second is a JSON file on the exchange's domain. They share the account ID, which also appears as sid in the SupplyChain object (sellers.json 1.0).
    What does complete mean in the SupplyChain object?
    A value of 1 claims the chain runs all the way back to the owner of the site or app. A value of 0 means at least one upstream seller is missing, usually because it did not support the object. Buyers can verify a 1 by matching the first node to the publisher's OWNERDOMAIN or MANAGERDOMAIN.
    What does hp mean in schain?
    hp says whether the node is in the payment flow: with 1, the system in asi pays the seller in sid, who pays the previous node. Version 1.0 requires 1 on every node (OpenRTB 2.6, SupplyChainNode). The 1.1 draft adds hp 0 for unpaid technical hops.
    Does every bid request need an schain?
    OpenRTB 2.6 marks schain as "recommended", not required. IAB Tech Lab's Programmatic Best Practices draft of 16 September 2026 goes further and asks for an schain object in each bid request (public comment draft). A buyer may treat a missing chain as a reason to bid lower or not at all.

    How this works on owned infrastructure

    A supply chain is only as trustworthy as the weakest file in it, and most failures are operational: a seat added to an exchange but not to sellers.json, a node appended twice after a wrapper upgrade. When you run the exchange yourself, you own one of the three records and one node in every chain. AdSovereign is an enterprise RTB stack (DSP, SSP, exchange, DMP and clean room) designed to run inside your own perimeter. Its exchange is built to serve sellers.json from the same account data that appends your node, and its bidder can run the seven node checks before pricing. The architecture page shows where supply-path checks sit, and integrations lists the partners whose files are crawled.

    Sources

    1. IAB Tech Lab, "OpenRTB SupplyChain object" (version 1.0). https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/supplychainobject.md
    2. IAB Tech Lab, "Sellers.json" specification, version 1.0 (July 2019). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/main/sellers-json.md
    3. IAB Tech Lab, "ads.txt" specification, version 1.1. https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/main/ads.txt%20v1.1.md
    4. IAB Tech Lab, "Ads.txt Implementation Guidance" (OWNERDOMAIN, MANAGERDOMAIN, buyer guidance; main branch, accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/main/Implementation%20Guidance.md
    5. IAB Tech Lab, "Supply Chain Validation: Implementation Guidance" with SupplyChain 1.1 draft examples (dev branch, commits 18 June to 9 July 2026). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/dev/Implementation%20Guidance.md
    6. IAB Tech Lab, Supply-Chain-Validation commit history, dev branch (accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/commits/dev
    7. IAB Tech Lab, sellers.json and SupplyChain object page (finalised 31 July 2019). https://iabtechlab.com/sellers-json/
    8. IAB Tech Lab, "OpenRTB API Specification Version 2.6", objects Source, SupplyChain and SupplyChainNode (accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md
    9. IAB Tech Lab, "OpenRTB Specification v3.0" (Source object, ads.cert fields, no-bid reason codes). https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/OpenRTB%20v3.0%20FINAL.md
    10. IAB Tech Lab Programmatic Governance Council, "Programmatic Best Practices, Version 1.0, Public Comment" (16 September 2026). https://iabtechlab.com/wp-content/uploads/2026/09/Public-Comment-Programmatic-Best-Practices-v1-1.pdf
    More sources (9)
    1. IAB Tech Lab, "IAB Tech Lab Releases currently in Public Comment" (accessed 9 November 2026). https://iabtechlab.com/iab-tech-lab-standard-updates-currently-in-public-comment/
    2. IAB Tech Lab, ads.cert page (last updated 14 February 2024). https://iabtechlab.com/ads-cert/
    3. IAB Tech Lab blog, Rob Hazan (Index Exchange), "Public Release of Ads.cert: Securing the CTV Supply Chain" (27 January 2022). https://iabtechlab.com/blog/public-release-ads-cert-securing-ctv-supply-chain/
    4. IAB Tech Lab, adscert open-source repository (last push 5 July 2023). https://github.com/IABTechLab/adscert
    5. Prebid.org, "Supply Chain Object Module" documentation (accessed 9 November 2026). https://docs.prebid.org/dev-docs/modules/schain.html
    6. Prebid, Prebid.js release 10.0.0 (1 July 2025). https://github.com/prebid/Prebid.js/releases/tag/10.0.0
    7. Prebid, prebid-server, openrtb_ext/convert_up.go (accessed 9 November 2026). https://github.com/prebid/prebid-server/blob/master/openrtb_ext/convert_up.go
    8. Google, Authorized Buyers "OpenRTB Integration" guide (last updated 15 October 2026). https://developers.google.com/authorized-buyers/rtb/openrtb-guide
    9. PPC Land, "SupplyChain object" (6 September 2026; cites HUMAN Security's diagnostic of 1 November 2023). https://ppc.land/supplychain-object/
    Changelog
    • 9 November 2026. First edition. Covers SupplyChain 1.0, sellers.json 1.0, ads.txt 1.1, the 1.1 drafts in the dev branch, the Programmatic Best Practices draft and ads.cert status. Next review 9 February 2027.