Programmatic transparency field guide
app-ads.txt, sellers.json & SupplyChain
A file can be valid and a bid request can still be inconsistent. This guide shows publishers, app and CTV owners, SSPs, DSPs and partnership teams how to connect property identity, seller authorization, legal-entity disclosure and the transaction path before opening or scaling a programmatic test.
The three questions
Each signal answers a different part of the supply story
app-ads.txt, sellers.json and the OpenRTB SupplyChain object are related, but they are not substitutes. Treating one successful lookup as proof of the entire path creates blind spots. The useful question is whether all three signals agree for the specific app, account and request being evaluated.
app-ads.txt
Authorization: which advertising systems and account IDs has the app developer publicly authorized to sell or resell the app’s inventory?
sellers.json
Identity: which legal entity is represented by an account ID in an advertising system, and what seller type is declared for that account?
SupplyChain
Transaction path: which selling systems and seller IDs participated in this bid request, in what order, and is the declared chain complete?
Signal 01
Discover app-ads.txt from the app store—not from a spreadsheet
For mobile and CTV inventory, discovery begins with the actual app identity. Start with the bundle or store identifier carried in the bid request and locate the authoritative store listing. Compare the request’s app bundle and store URL with that listing. Similar names, copied icons and related developer accounts are not enough; the identifiers must lead to the intended property.
From the store listing, obtain the developer website URL. app-ads.txt links apps to a web resource controlled by the developer, so a document found on a domain supplied only in onboarding material is not the same evidence. Canonicalize the developer URL according to the standard’s discovery rules, then request /app-ads.txt at the resulting domain over HTTPS. If the listed developer URL uses a meaningful subdomain, the standard includes fallback behavior to the registrable root domain when the subdomain does not host the file.
Record the full discovery path: bid-request app ID, store URL, store listing, developer URL, canonicalized domain, final app-ads.txt URL, status code, content type, redirect destination and retrieval time. That chain matters because a syntactically correct file on the wrong domain does not authorize the app being tested. For a portfolio of apps, perform the lookup per listing rather than assuming one successful domain applies to every property.
Read the record
Match the advertising-system domain and account ID exactly
An authorized seller record contains the advertising system’s canonical domain, the publisher or reseller account ID in that system, the relationship type and an optional certification-authority ID. The first two fields are the practical join keys. Preserve account IDs as strings: leading zeroes, capitalization and punctuation can matter, and a human-friendly account name is not a replacement for the value used in transactions.
| Record field | What to verify | Cross-check against |
|---|---|---|
| Advertising-system domain | Canonical domain issued by the SSP or exchange | asi and the host of /sellers.json |
| Account ID | Exact seller or reseller identifier used by that system | seller_id, sid and relevant request ID |
| Relationship | DIRECT or RESELLER based on account control | Commercial ownership and seller-type context |
| Certification ID | Optional identifier for the advertising system | Applicable authority records; do not infer quality from presence alone |
Ignore comments when parsing records, but retain them in a review copy because they can help the publisher explain sections or changes. Detect malformed separators, duplicate lines, hidden characters and stale accounts. A duplicate is usually harmless to parsing, yet it can reveal that ownership of the file or partner list is not being maintained cleanly.
Relationship semantics
DIRECT and RESELLER describe account control
DIRECT indicates that the publisher or content owner directly controls the specified account on the named advertising system. RESELLER indicates that the publisher has authorized another entity to control that account and resell the publisher’s inventory through the named system. These labels describe the relationship to that account; they are not rankings, quality scores or universal statements about how many commercial parties exist elsewhere in the path.
Do not assign DIRECT merely because a partner communicates directly with the publisher, sends an endpoint, or appears as the last hop to a buyer. Ask who controls the account represented by field two. Likewise, RESELLER is not automatically an error. It can represent an authorized arrangement, but the corresponding entity and transaction path should be identifiable through sellers.json and the SupplyChain.
One frequent review mistake is comparing DIRECT/RESELLER mechanically with PUBLISHER/INTERMEDIARY in sellers.json as if the words were interchangeable. They answer related but distinct questions. The app-ads.txt relationship is declared by the property owner for an account in an advertising system; sellers.json describes the selling entity represented by that system’s seller ID and whether the inventory sold under it is owned, intermediated or both. Investigate an apparent conflict using the account contract and payment path rather than changing a label to make a dashboard green.
Signal 02
Use sellers.json to resolve IDs into entities
Every advertising system named in an authorized seller record or SupplyChain node should publish a sellers.json file at its canonical domain. Find the entry whose seller_id exactly matches the app-ads.txt account ID or SupplyChain sid. For a non-confidential entry, inspect the declared legal-entity name, business domain and seller_type. The specification permits one entity to have multiple IDs, but one seller ID must not represent multiple paid entities.
PUBLISHER indicates that inventory sold through the account is on a property owned by the named entity and the advertising system pays that entity directly. INTERMEDIARY indicates that the inventory is not owned by the named entity or that the advertising system does not pay the named entity directly. BOTH means both kinds of inventory can transact through the account. This is why a domain match alone cannot settle the relationship: the seller type and the specific inventory context still matter.
A confidential entry may omit identity fields when is_confidential is set, so record that the lookup is intentionally limited rather than reporting the seller ID as absent. Confidentiality does not erase the need for the ID to exist, nor does it prove the path is acceptable to a buyer. It means the public record alone cannot complete the identity review. Partnership teams should agree what supporting information can be shared privately and who is permitted to see it.
Signal 03
Read the SupplyChain as an ordered request-level path
The SupplyChain object travels with a bid request. Its nodes array is ordered from the initial selling system and seller toward the entity sending the request. Each node requires asi, the advertising-system domain; sid, the seller ID in that system; and hp, the payment-participation field. In SupplyChain version 1.0, hp should be set to 1. Optional fields can help correlate a request, but identity should resolve through the advertising system’s sellers.json where published.
The complete value deserves literal interpretation. A value of 1 declares that the chain contains every node back to the owner of the site, app or other inventory medium. In that case, the first node should represent the originating seller and the last node should represent the entity sending the bid request. A value of 0 says the chain begins at the first known node, not necessarily at the property owner. It is a disclosure of incompleteness, not permission to guess the missing parties.
When a reseller receives an existing SupplyChain, it should preserve the object and its completeness value while appending its own node. If it receives inventory without a SupplyChain and creates one, it should mark the chain incomplete and include its known node. During testing, save the object from an actual bid request, not a manually prepared example. Confirm that every asi serves the relevant sellers.json and every sid resolves there to one entity.
First node
Originating seller when complete; first known seller when incomplete.
Middle nodes
Intermediaries participating in the direct payment flow, in order.
Last node
The entity responsible for sending the bid request to the buyer.
Cross-check workflow
Validate one property, one route and one live request at a time
A useful review produces a traceable decision, not just three screenshots. Work through the sequence below for each app and commercial route included in the proposed test.
- 01
Anchor the property
Capture the bundle or store ID and store URL from a live OpenRTB sample. Open the store listing and verify that the identifiers, developer name and property match the onboarding description.
- 02
Follow the developer link
Use the developer website in the store metadata to derive the app-ads.txt location. Record redirects and reject a file discovered only through a partner-supplied URL when the store path points elsewhere.
- 03
Find the authorization
Locate the exact advertising-system domain and account ID expected for the route. Confirm whether the publisher has correctly declared account control as DIRECT or RESELLER.
- 04
Resolve the seller
Retrieve sellers.json from the advertising-system domain and match the account ID to
seller_id. Record seller type, name, domain and confidentiality status without filling gaps by assumption. - 05
Trace the live chain
Extract
source.schainfrom the same kind of request intended for the test. Check version, completeness, node order and each requiredasi,sidandhpvalue. - 06
Join every node
For each node, retrieve the advertising system’s sellers.json and resolve its
sid. Compare the resulting entities and roles with the authorized route and commercial explanation. - 07
Write the conclusion and retest condition
Separate confirmed matches, confirmed mismatches and unavailable evidence. Name the owner of each correction, the exact signal that must change, the cache or crawl delay to allow, and the live sample required to close the review. Re-run the full chain after the fix rather than checking only the edited file.
This workflow complements a broader OpenRTB integration review. Authorization and identity are essential, but partners still need to align request fields, formats, geography, traffic scope, endpoints, timeouts, reporting and test controls.
Common mismatches
Treat mismatches as specific evidence gaps
Store and request identify different apps
The bundle, store ID or store URL in traffic does not resolve to the property described in onboarding. Pause that source until the request identity is corrected and a fresh sample is available.
Developer domain does not serve the file
The store listing points to a domain with no accessible app-ads.txt, an error document, an unsuitable redirect or a non-text response. Confirm the listing and hosting setup before adding more seller records.
Authorized ID is absent from sellers.json
The app-ads.txt line names an account that the advertising system does not publish. Check for transcription, whitespace, case or stale-account issues, then ask the system owner to confirm the canonical ID.
SupplyChain node does not resolve
An asi host lacks sellers.json, or its sid is not present. Identify which party inserted the node and correct the source data instead of deleting evidence from a downstream report.
Completeness conflicts with the path
A chain marked complete begins with an intermediary or omits a known payment participant. Ask for the originating path and node-construction logic; do not silently relabel the chain based on expectation.
Public identity is limited
A confidential sellers.json record prevents public entity resolution. Document the limitation and decide whether approved private evidence can satisfy the buyer’s review policy for that route.
Launch packet
Package the evidence before traffic starts
A launch packet should make the proposed route understandable to commercial and technical reviewers without requiring them to reconstruct it from chat messages. Build one row per app and route, and date every retrieved public file because the records can change between onboarding and launch.
- App name, platform, bundle or store ID, authoritative store URL and developer domain
- Final app-ads.txt URL, retrieval timestamp and the exact authorized record for the route
- Advertising-system domain, seller ID, sellers.json name, domain, seller type and confidentiality status
- Representative OpenRTB request with sensitive values redacted, including the full SupplyChain object
- Node-by-node resolution table, commercial path summary, known limitations and open questions
- Owners for file changes, request changes and retest approval, plus an agreed review date
For app and CTV owners evaluating monetization routes, the AdSelect publisher partnership overview explains the wider source information reviewed before a controlled test. For connected-TV-specific property and playback context, continue with the CTV advertising partnership guide.
OpenRTB integration
Move from supply-path review to request examples, protocol alignment, traffic controls and a measured endpoint test.
Review the integration process →Inventory quality
See how identity, sample traffic and available evidence are reviewed for the specific source and period.
Explore the quality approach →More AdSelect resources
Continue with practical resources for OpenRTB readiness and programmatic video operations.
Browse all resources →Review a specific opportunity
Bring the property, route and live sample.
Tell the AdSelect Team whether you are bringing supply or demand, the app or CTV property involved, the proposed OpenRTB route, target markets and the transparency evidence already available.
Schedule a Partnership Call