Blog · Protocol

Authorized Buyers vs OpenRTB is a spec request plus at 3 and imp.ext.billing_id.

Authorized Buyers vs OpenRTB is not a different auction protocol. It is OpenRTB plus a documented profile: request at of 3 means fixed price on that path, and each impression needs imp.ext.billing_id. The specification's own at values are 1, 2, and 500 or greater.

at 3 on the request is the profile, not the spec

In the OpenRTB specification, at 1 is first price and at 2 is second price plus. Omitted, the default is 2. Values of 500 or greater are exchange-specific. Deal.at 3 is a different field: on a deal, 3 means the deal bidfloor is the fixed price. That deal override does not make request-level at 3 legal in a spec-only check.

Google Authorized Buyers documents request at 3 as fixed price and requires imp.ext.billing_id. RTBlint applies that on top of the spec when you pass --profile google-ab, or when you pick Google AB in the tester. A spec pass can reject the fixed-price auction type the buyer path uses. A google-ab pass can accept at 3 and still fail because billing_id is missing. Run the profile you speak, and run spec when a partner also consumes the plain object.

Do not copy at 3 onto a Prebid or TAM request and call it Authorized Buyers. Those assemblies are different bodies. The profile is not implied by the fact that Google is somewhere in the stack. Open Bidding builds its own request. The comparison of who builds the JSON is the three paths post.

billing_id is not a deal id

imp.ext.billing_id is the Authorized Buyers billing identifier on the impression. Deal.id is the commercial deal. A preferred deal or a guaranteed deal still uses Deal.at and guar inside pmp. Putting the billing id in Deal.id, or omitting ext.billing_id because a deal id is present, fails the profile while the spec object can look complete.

Spec JSON wants integer flags. at as a string fails a typed parser on every profile. Protobuf JSON is a separate dialect for the 28 bool flags. at itself stays an integer in both. Set dialect and profile as two choices. The CI action takes both: profile: google-ab and dialect: spec-json or proto-json.

Pin the OpenRTB snapshot separately. The profile adds Google's extras. It does not pick 2.5 versus 2.6-202505. A google-ab request can still carry regs.ext.gdpr and fail a 2.6 pin for a moved field. Validate snapshot, dialect, and profile together on the builder output, not on a sample edited until the badge turned green.

Other profiles are not this one

prebid-server, xandr, and magnite are different extras. Prebid Server refuses wseat and bseat and wants a bidder or a stored request on the impression. Authorized Buyers wants billing_id and allows request at 3. Turning on google-ab for a Prebid Server body, or prebid-server for an Authorized Buyers body, produces a red job that describes the wrong exchange. Name the profile in the CI step next to the fixture that builder emits.

Deal.at 3 remains the way a preferred or guaranteed deal encodes a fixed price inside pmp, on any profile. That can sit on an Authorized Buyers request that also has request at 3 and a billing_id. They are two fixed-price mechanisms. The deal price is Deal.bidfloor in Deal.bidfloorcur. The request auction type is at. Read both. A test that only sets one of them does not prove the IO.

The tester profile dropdown includes Google AB. Set it before you trust a pass on a payload that uses at 3. A spec pass on that file is allowed to complain. A google-ab pass that never looked for billing_id is the job you did not configure. RTBlint is not Google. The profile is the published extra, not a live call to Authorized Buyers.

What to run

  • Spec check: at is 1, 2, or 500 and above. Request at 3 is not that list.
  • Authorized Buyers check: --profile google-ab, at 3 allowed, imp.ext.billing_id required.
  • Do not treat Deal.at 3 as permission to set request at 3.
  • Do not put the billing id in Deal.id.
  • Pin spec-version as well as the profile.
  • A spec-only CI job will not notice a missing billing_id.

Fixed price on the deal is not fixed price on the request

A programmatic guaranteed or preferred deal uses Deal.at 3 inside pmp. That is legal OpenRTB. Request at 3 is the Authorized Buyers extra. A fixture that only sets the deal flag will pass spec and fail google-ab if billing_id is missing and the request at is 3. A fixture that only sets request at 3 will fail spec and pass the profile only when billing_id is present. Build the fixture from the serializer that production uses.

Dialect stays independent. Integer flags for spec JSON, bools for protobuf JSON, and at as an integer in both. A bool at is wrong everywhere. Pin spec-version, dialect, and profile in the same CI step so a green badge names all three. The tester has the same three controls. Set them before you read the result.

Further reading