<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" version="3" ipr="trust200902" category="exp" submissionType="IETF" docName="draft-dierken-conditional-access-http-00" xml:lang="en">
  <front>
    <title abbrev="Conditional Access for HTTP">Conditional Access for HTTP</title>
    <author fullname="S. Mike Dierken" initials="M." surname="Dierken">
      <organization>paywalls.net</organization>
      <address>
        <email>mike@paywalls.net</email>
      </address>
    </author>
    <date year="2026" month="March" day="17"/>
    <area>ART</area>
    <keyword>HTTP</keyword>
    <keyword>conditional access</keyword>
    <keyword>pricing</keyword>
    <keyword>automation</keyword>
    <keyword>AI agents</keyword>
    <abstract>
      <t>This document introduces conditional access to resources based on pricing constraints signaled via request and response headers. An origin states the conditions for serving a resource, and a client states the constraints under which it will accept it.</t>
      <t>This specification applies this conditional access approach using standard HTTP request and response semantics while staying interoperable with intermediaries. It introduces a <tt>Pricing</tt> response header field that communicates current pricing terms and an <tt>If-Price-LTE</tt> request header field that allows a client to declare a maximum acceptable price.</t>
      <t>When a request is served under such conditions, the response includes a <tt>Response-Id</tt> header identifying the served response context. This identifier can be used for reconciliation, auditing, and downstream usage reporting.</t>
      <t>This specification defines access condition signaling only. Accounting and usage reporting may be implemented using a companion protocol such as <tt>usage-log</tt>.</t>
    </abstract>
  </front>

  <middle>
    <section numbered="true" toc="default">
      <name>Status of This Memo</name>
      <t>This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.</t>
      <t>Internet-Drafts are working documents of the Internet Engineering Task Force (IETF).</t>
    </section>

    <section numbered="true" toc="default">
      <name>Introduction</name>
      <t>HTTP provides mechanisms for conditional requests and access control, including authentication, authorization, rate limiting, and representation-state preconditions. These mechanisms allow servers to express conditions based on identity, resource state, or server capacity. However, HTTP does not currently provide a standardized mechanism for expressing economic or policy conditions under which a resource may be served. This specification introduces such a mechanism while remaining compatible with existing HTTP conditional request semantics.</t>
      <t>Many web resources today are accessed under conditions such as:</t>
      <ul spacing="normal">
        <li>usage pricing</li>
        <li>quota limits</li>
        <li>licensing terms</li>
        <li>contractual access policies</li>
      </ul>
      <t>Historically, these conditions have often been implemented using JavaScript or proprietary APIs layered above HTTP. This approach works well for browsers but creates interoperability problems for automated clients and intermediaries that interact directly with HTTP semantics.</t>
      <t>Automation systems, APIs, and AI agents increasingly retrieve web content without executing JavaScript. In such environments, access conditions implemented through client-side code cannot be reliably expressed or enforced.</t>
      <t>This document defines a protocol mechanism that allows an origin server to explicitly communicate access conditions using HTTP metadata. Clients can then declare the conditions under which they are willing to receive the resource.</t>
      <t>This mechanism restores capabilities historically implemented through JavaScript paywalls and tracking pixels into explicit HTTP protocol semantics suitable for automated clients and intermediaries.</t>
      <t>Access conditions may be dynamic and may vary across time, identity, or other policy factors. Because the <tt>Pricing</tt> field explicitly communicates the minimum acceptable price, clients typically have little incentive to probe for lower prices. However, clients may issue repeated requests to observe changes in pricing across time, identities, or other request characteristics. This specification therefore allows servers to publish stability metadata such as <tt>valid_until</tt> and <tt>next_floor</tt> while still enabling efficient price discovery.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Representation Lifecycle</name>
      <t>Conditional access introduces a lifecycle for served representations:</t>
      <ol spacing="normal">
        <li>Access conditions are communicated.</li>
        <li>The client declares acceptable conditions.</li>
        <li>The origin serves the representation if conditions are satisfied.</li>
        <li>The served response receives a durable identifier.</li>
      </ol>
      <t>The identifier allows the served response to be referenced later for purposes such as:</t>
      <ul spacing="normal">
        <li>auditing and reconciliation</li>
        <li>operational diagnostics</li>
        <li>downstream usage reporting</li>
      </ul>
      <t>A separate protocol may be used to report downstream usage, which is particularly applicable to cached representations.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Terminology</name>
      <dl newline="false" spacing="normal">
        <dt>Origin</dt>
        <dd>The server hosting the resource.</dd>
        <dt>Client</dt>
        <dd>A software agent requesting the resource.</dd>
        <dt>Access Conditions</dt>
        <dd>Constraints under which the origin is willing to serve a representation.</dd>
        <dt>Response Context</dt>
        <dd>The specific instance of a response served by the origin.</dd>
      </dl>
    </section>

    <section numbered="true" toc="default">
      <name>Protocol Overview</name>
      <t>This specification introduces two HTTP header fields:</t>
      <ul spacing="normal">
        <li><tt>Pricing</tt></li>
        <li><tt>If-Price-LTE</tt></li>
      </ul>
      <t>It also defines the <tt>Response-Id</tt> response header used to identify served responses.</t>
      <t>A typical interaction proceeds as follows:</t>
      <ol spacing="normal">
        <li>A client requests a resource.</li>
        <li>The origin communicates current access conditions.</li>
        <li>The client declares acceptable conditions.</li>
        <li>The origin serves the resource if conditions are satisfied.</li>
      </ol>
    </section>

    <section numbered="true" toc="default">
      <name>Price Discovery</name>
      <t>A client may request a resource without declaring an acceptable price.</t>
      <t>Example:</t>
      <sourcecode type="http"><![CDATA[
GET /resource HTTP/1.1
Host: example.com
Authorization: Bearer agt_XYZ
]]></sourcecode>
      <t>If the resource requires payment or another access condition, the origin may respond:</t>
      <sourcecode type="http"><![CDATA[
HTTP/1.1 402 Payment Required
Pricing: floor=0.02, valid_until=@1743595200, next_floor=0.05, effective=@1743552000, currency="USD", unit="request"
]]></sourcecode>
      <t>The <tt>Pricing</tt> field communicates a price quote for accessing the resource. A quote may include the current minimum acceptable price (<tt>floor</tt>) as well as additional metadata describing the stability or evolution of that price.</t>

      <section numbered="true" toc="default">
        <name>Price Quote Metadata</name>
        <t>Servers MAY include additional metadata describing the stability and evolution of pricing conditions. These fields allow clients to make informed decisions and to understand when pricing is expected to remain stable or change.</t>
        <dl newline="false" spacing="normal">
          <dt>floor</dt>
          <dd>The minimum acceptable price at the time the response is generated.</dd>
          <dt>valid_until</dt>
          <dd>Timestamp indicating how long the current price quote is expected to remain valid.</dd>
          <dt>next_floor</dt>
          <dd>Indicates the minimum acceptable price that will apply after the next scheduled price change.</dd>
          <dt>effective</dt>
          <dd>Timestamp indicating when <tt>next_floor</tt> becomes active.</dd>
        </dl>
        <t>Together, these members describe the lifecycle of a price quote. The current quote applies when the response is generated. When <tt>next_floor</tt> and <tt>effective</tt> are present, they describe the next scheduled pricing change. When <tt>valid_until</tt> is present, it indicates how long the current quote is expected to remain stable.</t>
        <t>Servers SHOULD ensure that <tt>valid_until</tt> intervals are long enough to provide useful stability information and reduce unnecessary repeated requests.</t>
        <t>Example:</t>
        <sourcecode type="http"><![CDATA[
HTTP/1.1 402 Payment Required
Pricing: floor=0.02, valid_until=@1743595200, next_floor=0.05, effective=@1743552000, currency="USD", unit="request"
]]></sourcecode>
        <t>This response indicates that the current floor price is 0.02. After the effective time, the minimum acceptable price will be at least 0.05.</t>
      </section>
    </section>

    <section numbered="true" toc="default">
      <name>Conditional Access Request</name>
      <t>A client may include a constraint declaring the maximum acceptable price.</t>
      <t>Example:</t>
      <sourcecode type="http"><![CDATA[
GET /resource HTTP/1.1
Host: example.com
Authorization: Bearer agt_XYZ
If-Price-LTE: 0.03; currency=USD; unit=request
]]></sourcecode>
      <t>If the constraint is satisfied, the origin may serve the response.</t>
      <sourcecode type="http"><![CDATA[
HTTP/1.1 200 OK
Pricing: applied=0.02, currency="USD", unit="request"
Response-Id: resp_82fd
]]></sourcecode>
      <t>If the constraint is not satisfied:</t>
      <sourcecode type="http"><![CDATA[
HTTP/1.1 402 Payment Required
Pricing: floor=0.05, currency="USD", unit="request"
]]></sourcecode>
      <t>When price quote metadata such as <tt>valid_until</tt> is present, clients should treat the quote as stable within that interval and can use that metadata to avoid unnecessary repeated requests made only to observe whether pricing has changed.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Pricing Header</name>
      <t><tt>Pricing</tt> communicates pricing conditions and related quote metadata for the resource.</t>
      <t>The field value is an RFC 8941 Structured Field Dictionary.</t>
      <t>Example:</t>
      <sourcecode type="http"><![CDATA[
Pricing: floor=0.02, currency="USD", unit="request"
]]></sourcecode>
      <t>Possible members include:</t>
      <dl newline="false" spacing="normal">
        <dt>floor</dt>
        <dd>minimum acceptable price</dd>
        <dt>valid_until</dt>
        <dd>Timestamp indicating how long the current price quote is expected to remain valid.</dd>
        <dt>next_floor</dt>
        <dd>Indicates the minimum acceptable price that will apply after the next scheduled price change.</dd>
        <dt>effective</dt>
        <dd>Timestamp indicating when <tt>next_floor</tt> becomes active.</dd>
        <dt>applied</dt>
        <dd>price applied to a served response</dd>
        <dt>currency</dt>
        <dd>ISO-4217 currency</dd>
        <dt>unit</dt>
        <dd>normalization unit</dd>
      </dl>
      <t>The <tt>applied</tt> member MUST appear when the resource is served under conditional access.</t>
      <t>The <tt>applied</tt> member MUST NOT appear in responses that do not serve the resource.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Price Quote Stability</name>
      <t>Because the <tt>Pricing</tt> field explicitly communicates the minimum acceptable price (<tt>floor</tt>), clients typically have little incentive to probe for lower prices. However, clients may issue repeated requests to observe changes in pricing across time, identities, or other request characteristics. Servers concerned about such behavior may publish stability metadata such as <tt>valid_until</tt> or <tt>next_floor</tt>.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Response Identifier</name>
      <t><tt>Response-Id</tt> identifies the origin-served response context.</t>
      <t>Example:</t>
      <sourcecode type="http"><![CDATA[
Response-Id: resp_7Y2f
]]></sourcecode>
      <t>The identifier is opaque to clients.</t>
      <t>A <tt>Response-Id</tt> value is assigned by the origin and MUST uniquely identify the served response context.</t>
      <t>Servers SHOULD include a <tt>Response-Id</tt> when serving a response under conditional access.</t>
      <t>The identifier can be used for:</t>
      <ul spacing="normal">
        <li>auditing</li>
        <li>reconciliation</li>
        <li>downstream usage reporting</li>
      </ul>
    </section>

    <section numbered="true" toc="default">
      <name>Pricing Units</name>
      <t>This specification defines two units:</t>
      <sourcecode><![CDATA[
request
cpm
]]></sourcecode>
      <t><tt>cpm</tt> represents price per 1000 requests.</t>
      <t>Servers MUST normalize units when evaluating <tt>If-Price-LTE</tt>.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Response Semantics</name>
      <dl newline="false" spacing="normal">
        <dt>200</dt>
        <dd>resource served</dd>
        <dt>402</dt>
        <dd>price constraint not satisfied</dd>
        <dt>403</dt>
        <dd>access disallowed</dd>
        <dt>429</dt>
        <dd>rate limited</dd>
      </dl>
    </section>

    <section numbered="true" toc="default">
      <name>Authentication</name>
      <t>Conditional access based on economic or policy conditions typically requires identifying the client.</t>
      <t>Authentication mechanisms may include:</t>
      <ul spacing="normal">
        <li>OAuth bearer tokens</li>
        <li>mutual TLS</li>
        <li>other HTTP authentication schemes</li>
      </ul>
      <t>The authentication method is outside the scope of this specification.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Interaction with Caching</name>
      <t>Served responses may be cached according to normal HTTP semantics.</t>
      <t>Cached representations may later be used without contacting the origin.</t>
      <t>A <tt>Response-Id</tt> allows the served response context to be referenced by downstream usage reporting mechanisms when such reporting is implemented.</t>
      <t>Pricing metadata such as <tt>valid_until</tt>, <tt>floor</tt>, or <tt>next_floor</tt> describes the server's view of pricing conditions at the time the response was generated. These fields do not modify HTTP caching semantics. Intermediaries and caches MUST continue to follow standard HTTP caching rules when determining response freshness.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Relationship to Usage Reporting</name>
      <t>Conditional access defines the terms under which a representation may be served.</t>
      <t>In deployments where cached representations are reused without contacting the origin, accounting may require reporting downstream usage.</t>
      <t>The pricing terms defined by this specification apply only to conditional access to a representation. They do not define or constrain any separate conditions that may apply to downstream usage of a served or cached representation. Any such usage policies are outside the scope of this specification.</t>
      <t>Such reporting can be implemented using a companion protocol such as <tt>usage-log</tt>.</t>
      <t>Usage reporting mechanisms are outside the scope of this specification.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Security Considerations</name>
      <t>Origins should authenticate clients before serving resources under conditional access.</t>
    </section>

    <section numbered="true" toc="default">
      <name>Privacy Considerations</name>
      <t>Conditional access mechanisms operate at the client or operator level and do not require identifying individual end users.</t>
      <t>Deployments should avoid including user-level identifiers in access metadata unless required for the application.</t>
    </section>

    <section numbered="true" toc="default">
      <name>IANA Considerations</name>
      <t>This document requests registration of the following HTTP header fields:</t>
      <ul spacing="normal">
        <li><tt>Pricing</tt></li>
        <li><tt>If-Price-LTE</tt></li>
        <li><tt>Response-Id</tt></li>
      </ul>
    </section>
  </middle>
</rfc>
