Validated Actor Inventory (VAI)
Technical specification
Validated Actor Inventory (VAI) is a publisher-originated, pre-bid classification signal used to route traffic into different monetization paths and tiers (for example: premium, standard, conservative, or suppressed). It is most valuable when it enables segmentation and routing—not blanket blocking.
VAI describes:
- Validated Actor Type (VAT): who or what is most likely responsible for the request
- Actor Confidence Tier (ACT): how confident the classification is at the time of evaluation
This document explains what the signal is, how it is generated, how it is verified, and how to pass it into your programmatic stack.
Audience and goals
This spec is written for publishers (product, ad ops, and engineering). The goal is to make VAI:
- Practical: clear integration steps and operational guidance
- Verifiable: cryptographically authenticatable end-to-end
- Cache-friendly: no HTML variation and minimal origin changes
- Privacy-preserving: no user identification and no cross-site identifiers
Core concepts
1) Validated Actor Type (VAT)
VAT expresses which category of actor the impression is intended to influence.
| Value | Meaning | Common examples |
|---|---|---|
HUMAN | Likely human attention | Typical users in browsers |
AI_AGENT | AI system retrieving content on behalf of a user | AI assistants, research agents, summarization tools |
SHARING | Social sharing and preview bots | Link preview generators, social card fetchers |
OTHER | Non-human automation not intended to influence a person | Crawlers, scrapers, monitoring, QA, renderers |
VAT is a classification, not an identity claim.
2) Actor Confidence Tier (ACT)
ACT is an explicit confidence tier describing certainty in the VAT assignment.
| Value | Meaning | Typical use |
|---|---|---|
ACT-1 | High confidence | Premium routing / strongest assumptions |
ACT-2 | Medium confidence | Standard routing / tolerant strategies |
ACT-3 | Low or indeterminate confidence | Conservative routing / limited monetization |
Publishers and buyers can choose how to treat each tier (route, discount, exclude, analyze separately, etc.).
Signal requirements (normative)
The keywords MUST, SHOULD, and MAY are used as described in RFC 2119.
A VAI assertion:
- MUST include
vatandact - MUST be produced server-side by publisher-controlled infrastructure (edge/CDN/gateway/origin)
- MUST be cryptographically signed
- MUST be time-bound (short TTL) to limit replay
- MUST be bound to the publisher inventory domain (
dom) (and MAY be additionally bound to coarse request context) - MUST NOT contain user identity, persistent user identifiers, or cross-site IDs
Transport and endpoints
VAI is designed to be easy to deploy without fragmenting cache or requiring origin template changes.
Endpoint: GET /pw/vai.json
Returns the current request’s classification plus a signed assertion suitable for downstream verification.
Recommended response (application/json):
{
"iss": "https://paywalls.net",
"aud": "vai",
"dom": "example.com",
"vat": "HUMAN",
"act": "ACT-2",
"did": "01J...ULID",
"iat": 1736629940,
"exp": 1736630040,
"kid": "2026-01-a",
"assertion": "BASE64URL_JWS"
}
Field definitions:
| Field | Type | Notes |
|---|---|---|
iss | string | required. Issuer identifier (prototype commonly uses https://paywalls.net). |
aud | string | required. Audience identifier (canonical: "vai"). |
dom | string | required. Inventory domain binding (the request hostname, e.g. example.com). |
vat | string | required. One of HUMAN, AI_AGENT, SHARING, OTHER. |
act | string | required. One of ACT-1, ACT-2, ACT-3. |
assertion | string | required. JWS/JWT-like token (details below). |
iat | number | recommended. Issued-at (epoch seconds). |
exp | number | required. Expiry (epoch seconds). |
kid | string | required. Key identifier used to sign assertion. |
did | string | optional. Short-lived decision identifier for debugging/analytics (MUST NOT be user-stable). |
Normative rule:
- The clear-text fields (
iss,aud,dom,vat,act,did,iat,exp) MUST match the correspondingassertionclaims.
TTL guidance: exp - iat SHOULD be between 30 and 120 seconds.
Endpoint: GET /pw/vai.js
Returns a small JavaScript payload that exposes the VAI object to client-side integrations.
Recommended behavior:
- The script sets
window.__PW_VAI__to the same object shape returned by/pw/vai.json. - The script does not set cookies or localStorage.
Example usage in an HTML template:
<script src="/pw/vai.js"></script>
This enables header bidding wrappers to read a normalized object without needing additional calls.
Assertion format and cryptographic verification
VAI assertions are designed to be verified by intermediaries (SSPs, verification partners) and/or buyers.
Signing format
The assertion value SHOULD be a JWS compact serialization token (JWT-style) containing a JSON payload.
- Algorithm SHOULD be EdDSA (Ed25519) or ES256.
- Algorithm MUST NOT be
none.
Header (example):
{ "alg": "EdDSA", "typ": "JWT", "kid": "2026-01-a" }
Payload claims (recommended):
vat(string, required)act(string, required)iss(string, required): issuer identifier (publisher or service)aud(string, required): audience identifier (canonical:"vai")iat(number, recommended)exp(number, required)dom(string, required): inventory domain binding (the request hostname, e.g.,example.com)jti(string, recommended): unique token id (short-lived) to improve replay detectiondid(string, optional): decision/debug id (short-lived)
Binding guidance:
- The assertion MUST be bound to the serving domain (
dom). - The assertion MAY be additionally bound to coarse request context (for example, path class or site section). It MUST NOT be bound to user identifiers.
Verification steps (SSP/buyer)
A verifier SHOULD:
- Parse the JWS header and payload.
- Resolve the public key via
kidfrom the publisher’s JWKS endpoint. - Verify the signature.
- Validate time bounds:
iat <= now <= expwith a small clock skew tolerance (e.g., 5–15s). - Validate
dommatches the inventory domain. - Confirm
vatandactare in the allowed enum sets.
If any checks fail, the verifier should treat the signal as unverified and ignore it or downgrade it according to policy.
Key distribution (JWKS)
Publishers MUST provide a public key set for verifiers.
Endpoint: GET /pw/jwks.json
Recommended response (application/json):
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"kid": "2026-01-a",
"use": "sig",
"alg": "EdDSA",
"x": "BASE64URL_PUBLIC_KEY"
}
]
}
Operational guidance:
- Keys SHOULD be cacheable (e.g.,
Cache-Control: public, max-age=3600). - Publishers SHOULD support key rotation by serving multiple keys during transitions.
- Assertions MUST reference the active signing key via
kid.
Passing VAI into the programmatic stack
VAI is intended to be carried as publisher-originated metadata that survives through:
- header bidding wrappers
- ad servers
- OpenRTB bid requests
- SSP and exchange routing
Recommended OpenRTB mapping
VAI SHOULD be placed in OpenRTB site.ext (or app.ext) as a namespaced object.
Example:
{
"site": {
"domain": "example.com",
"ext": {
"pw_vai": {
"iss": "https://paywalls.net",
"aud": "vai",
"dom": "example.com",
"vat": "HUMAN",
"act": "ACT-2",
"kid": "2026-01-a",
"exp": 1736630040,
"assertion": "BASE64URL_JWS"
}
}
}
}
Notes:
- The
assertionSHOULD be included so downstream parties can verify authenticity. - Intermediaries SHOULD NOT rewrite
vat/act; they MAY add their own separate fields if needed.
Prebid.js / wrapper integration (example)
Load /pw/vai.js early (it sets window.__PW_VAI__), then attach the fields you need to ORTB2:
<script src="/pw/vai.js"></script>
var vai = window.__PW_VAI__;
// If VAI isn't available yet, proceed without it.
if (!vai) {
// pbjs.requestBids(); // continue without pw_vai
return;
}
pbjs.setConfig({
ortb2: {
site: {
ext: {
pw_vai: vai
}
}
}
});
Caching and performance
VAI is designed to avoid cache fragmentation.
/pw/vai.jsonMUST NOT be cached by browsers, CDNs, or intermediaries (useCache-Control: private, no-store, max-age=0)./pw/vai.jsMUST NOT be cached by browsers, CDNs, or intermediaries (useCache-Control: private, no-store, max-age=0).- Pages and HTML responses SHOULD NOT vary by VAT/ACT.
Because the assertion is short-lived, the integration can be implemented without per-user storage.
Privacy and compliance posture
VAI is designed as a traffic-origin classification signal, not an identity system.
VAI implementations:
- MUST NOT include:
- IP addresses
- full user agents
- stable user IDs
- cookies, localStorage IDs, or fingerprinting outputs
- SHOULD minimize request-derived entropy in the assertion payload
Publishers should treat VAI like other operational metadata used to route demand (similar to brand-safety or contextual signals), not as personal data.
Recommended publisher routing policies (non-normative)
Different publishers will route differently. A common starting point:
HUMAN+ACT-1: eligible for premium demand pathsHUMAN+ACT-2: eligible for standard demand pathsACT-3: eligible for conservative demand paths or limited monetizationAI_AGENT: may be excluded from ads, routed to specific deals, or used for future licensing modelsSHARING: may serve ads if the preview generates downstream human traffic; some publishers excludeOTHER: typically excluded from ads (to prevent dilution)
VAI is most valuable when it enables segmentation, not blanket blocking.
Troubleshooting checklist
If partners report “missing or unverifiable VAI,” check:
- Endpoints reachable:
/pw/vai.json,/pw/vai.js, and/pw/jwks.jsonreturn 200. - Time bounds:
expis in the future; TTL is 30–120s; clocks are correct. - Key rotation:
kidin assertions exists in JWKS. - Domain binding:
dommatches the inventory domain used in OpenRTB. - Propagation: wrapper passes
pw_vaithrough to the SSP unchanged. - Size limits: ensure the assertion doesn’t exceed platform limits; prefer compact keys and short claims.
FAQ
Is VAI a fraud score?
No. VAI describes traffic origin (actor type) and confidence. It complements IVT/fraud tooling.
Does VAI identify users?
No. VAI must not include user identity or stable identifiers.
Does this require changing our HTML templates?
Usually no. Many publishers can deploy VAI at the edge via /pw/vai.js and wrapper configuration.
Can buyers trust the signal?
When the assertion is verified against the publisher’s JWKS, buyers can treat it as authenticated publisher-originated metadata.
Getting started
- If you want a lightweight pilot, start by implementing
/pw/vai.json+ JWKS, then attachpw_vaiinto OpenRTB via your wrapper. - For support, share:
- a sample bid request containing
site.ext.pw_vai - the JWKS URL
- a sample
assertionandkid
- a sample bid request containing