| Internet-Draft | terms.txt | September 2026 |
| Chowdhury | Expires 14 March 2027 | [Page] |
The Robots Exclusion Protocol lets an origin ask automated clients not to fetch certain paths. It cannot express who is asking, for what purpose, under what terms, or at what price, and it provides no server-side enforcement. This document specifies terms.txt, a file at a well-known location in the style of robots.txt that states, per path and per purpose, whether automated access is allowed, charged, or denied, at what use level, at what price, and whether a user's delegation is required. It also specifies the HTTP exchange that enforces the file at the origin: requests signed with Web Bot Auth, a signed declaration of intent, delegation tokens and payment vouchers bound to the authenticated identifier, payment negotiation signaled with Problem Details, and origin-signed receipts. The document states which properties the exchange enforces before delivery, which it can only audit afterward, and which remain contractual.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 14 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The open web has operated on an implicit bargain: an origin admits crawlers, and search engines return visitors. Automated clients that fetch content to train models or to answer questions directly break that bargain, because the fetch still happens while the referral does not. Origins have responded with the only tool they widely hold, the Robots Exclusion Protocol [RFC9309], which has proven inadequate in four ways. Its vocabulary of allow and disallow cannot distinguish fetching for indexing from fetching for training from fetching to answer a live request. It cannot state a price, a license, or a condition. It depends on the client identifying itself truthfully in a free-text User-Agent field. And it supplies no enforcement, so an origin that wishes to admit an archive but refuse a commercial training crawler has no way to say so and no way to check.¶
Recent work addresses parts of this problem separately. Web Bot Auth [I-D.ietf-webbotauth-httpsig-protocol] lets an automated client sign its requests with HTTP Message Signatures [RFC9421] using keys published under an identifier it names, so an origin can verify that the holder of a published key signed the request. The AI Preferences work [I-D.ietf-aipref-vocab] [I-D.ietf-aipref-attach] defines a vocabulary for how content may be used and a way to attach those preferences to content, but by charter it expresses preferences and does not enforce them. Content delivery networks have shipped proprietary mechanisms that classify crawlers by purpose, return HTTP 402 to charged crawlers, and revoke the standing of operators that misbehave, but those mechanisms apply to an origin only because it routes traffic through a particular company.¶
This document composes these pieces into one exchange that any origin can enforce. An origin publishes a terms.txt file (Section 4) stating its terms per path and per purpose. A client fetches the file, then sends requests that are signed with Web Bot Auth, carry a signed declaration of purpose and use (Section 5.1), and, when the terms require it, carry a delegation token binding the request to a user's entitlements (Section 5.2) or a payment voucher (Section 5.3). The origin verifies the signature, checks the declaration against its terms, and either serves the content with a signed receipt (Section 6.1) or refuses with a status code and a Problem Details body [RFC9457] that states why, including the price and terms when payment is required.¶
A signature over a declared purpose proves who made the declaration and that it was not altered in transit. It does not prove that the declaration is true. A signed receipt proves that content was delivered under stated terms. It does not prove what the recipient did with the content afterward. Once content leaves the origin, HTTP cannot govern its use.¶
This document is therefore precise about three tiers. Properties in the first tier are enforced before delivery: the authenticated Web Bot Auth identifier of the requester, the freshness and uniqueness of the request, the binding of the signature to the full target URI, the presence and integrity of the declared intent, the validity and scope of a delegation, the match between the declaration and the terms, and the presence of a valid, unspent payment. Properties in the second tier are auditable after delivery: whether declared purpose matched observed behavior, which the receipt log and the signed declaration make attributable. Properties in the third tier are contractual: what a recipient does with lawfully delivered content, including whether it trains a model on it. This document makes the terms of the third tier explicit, attributable, and priced. It does not make them self-executing, and implementers MUST NOT describe it as doing so.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
This document applies to requests with the GET and HEAD methods. Requests with other methods are out of scope unless they also satisfy Section 5.4.¶
This document uses the terms "origin", "user agent", "intermediary", "field", and "resource" as defined in [RFC9110], and "Structured Field", "Dictionary", "String", and "Token" as defined in [RFC9651]. It uses "operator", "Signature Agent", and "key directory" as defined in [I-D.ietf-webbotauth-httpsig-protocol].¶
Before its first request to an origin, an agent obtains its operator's signing key and, when needed, a delegation token from the user's identity provider and a payment voucher from a settlement service. It MAY fetch the origin's terms.txt file to learn what is required. The exchange then proceeds as follows.¶
Unsigned requests, and signed requests that carry no Access-Intent field, are governed per path by the Unsigned directive of the applicable terms: served on paths marked allow, refused with a signature challenge on paths marked challenge, and refused on paths marked deny. No receipt is issued for them.¶
An origin publishes its terms at the well-known URI [RFC8615] "/.well-known/terms.txt". The resource MUST be served with the media type text/plain and the UTF-8 charset. It SHOULD be cacheable, and origins are encouraged to set a Cache-Control max-age of at least one hour so that clients fetch it infrequently.¶
Origins SHOULD include a Link field [RFC8288] with the relation type "access-terms" (Section 13.3) on responses to automated clients, pointing at the terms resource, so that a client that did not fetch the file in advance learns where it is.¶
The file applies to the origin at which it is served, in the sense of [RFC6454]. It does not apply to other origins, including other ports or schemes at the same host.¶
The file is a sequence of lines. Each non-empty, non-comment line is a field name, a colon, and a value, optionally followed by a comment. Field names are case-insensitive. Header fields precede one or more Path blocks. A Path block begins with a Path line and continues until the next Path line or the end of the file. The grammar in ABNF [RFC5234] is as follows; the final line of a file MAY omit its line terminator.¶
terms-file = *( header-line / skip ) 1*path-block
header-line = ( version-hdr / terms-id-hdr / receipt-keys-hdr
/ payment-hdr / purposes-hdr / uses-hdr ) end
version-hdr = "Version:" WS 1*DIGIT
terms-id-hdr = "Terms-Id:" WS id
receipt-keys-hdr = "Receipt-Keys:" WS uri
payment-hdr = "Payment:" WS method [ WS uri ]
purposes-hdr = "Purposes:" WS purpose *( WS purpose )
uses-hdr = "Uses:" WS use-level *( WS use-level )
path-block = path-line *( unsigned-line / purpose-line / skip )
path-line = "Path:" WS path-prefix end
unsigned-line = "Unsigned:" WS ( "allow" / "challenge" / "deny" ) end
purpose-line = "Purpose:" WS purpose WS decision *( WS option ) end
decision = "allow" / "charge" / "deny"
option = price / use-option / delegation-option
price = amount WS currency "/" unit
amount = 1*DIGIT [ "." 1*DIGIT ]
currency = 3ALPHA
unit = id
use-option = "use=" use-level
delegation-option = "delegation=" scope
use-level = "immediate" / "reference" / "full"
purpose = id
scope = id
method = id
id = 1*( ALPHA / DIGIT / "-" / "_" / "." / ":" )
path-prefix = "/" *( VCHAR-nohash )
uri = <absolute-URI or path-absolute, RFC 3986>
end = [ WS ] [ comment ] EOL
skip = [ WS ] [ comment ] EOL
comment = "#" *VCHAR
VCHAR-nohash = %x21-22 / %x24-7E
WS = 1*WSP
EOL = [ CR ] LF
¶
A "#" and everything after it on a line is a comment and is ignored; a path-prefix therefore cannot contain "#". Lines that do not match the grammar MUST cause the entire file to be rejected; an origin whose file fails to parse has stated no terms, and clients MUST treat it as if no terms.txt were present. A header field other than Payment that appears more than once is a parse error.¶
A request matches the Path block whose path-prefix is the longest prefix of the request's path component. Before comparison, both the request path and each path-prefix are normalized as in [RFC9309]: percent-encoded octets that correspond to unreserved characters [RFC3986] are decoded, hexadecimal digits in remaining percent-encodings are uppercased, and percent-encoded reserved characters such as "%2F" are left encoded, since decoding them would change the path's structure. Comparison is then byte-wise. A request that matches no block has no terms and MUST be treated by the origin according to its local policy; this document RECOMMENDS treating it as if the block "Path: /" with "Unsigned: allow" and no Purpose lines applied, which serves unsigned traffic and refuses every declared purpose.¶
Within a block:¶
A purpose that has no Purpose line in the matching block is refused. Origins that wish to admit a purpose must say so.¶
Purpose names are registered in the registry established in Section 13.5. The initial registry contains:¶
The last two are included because measurements of robots.txt deployment show that origins reacting to commercial training crawlers block archives and research crawlers as collateral damage, since the Robots Exclusion Protocol cannot distinguish them. Giving them names lets an origin admit them explicitly.¶
The registry is independent of the AI Preferences vocabulary, whose own text notes that it does not yet have working group consensus. Where a name here has an analogue there, the registry entry says so; the names are not claimed to be identical.¶
A use level describes how much of the fetched content the agent declares it will reproduce to its own users. "immediate" means a short excerpt or a fact extracted from the content. "reference" means a summary or a paraphrase with attribution. "full" means reproduction of the content in whole or substantial part. The levels are ordered, and a terms ceiling of a given level admits declarations at that level and below. The three levels are those of a proposed extension to the Content Signals convention [CONTENT-SIGNALS] described in [CLOUDFLARE-AI-OPTIONS]; the convention itself defines the categories ai-train, search, and ai-input and does not define use levels. Adopting the extension's names lets an origin that already publishes that signal in robots.txt state enforceable terms in the same words.¶
# /.well-known/terms.txt Version: 1 Terms-Id: 2026-09-01 Receipt-Keys: /.well-known/http-message-signatures-directory Payment: voucher https://settle.example/.well-known/settlement Path: /articles/ Unsigned: allow Purpose: search allow use=reference Purpose: agent allow use=reference delegation=articles Purpose: train-ai charge 0.002 USD/request Purpose: archive allow use=full Purpose: research allow use=full Path: /premium/ Unsigned: challenge Purpose: search allow use=reference Purpose: agent charge 0.01 USD/request use=reference delegation=premium Purpose: train-ai deny Purpose: archive allow use=full Purpose: research allow use=full¶
Under these terms, an unsigned browser is served from /articles/ and challenged on /premium/. A search crawler is admitted everywhere at the reference level. A training crawler pays per request under /articles/ and is refused under /premium/. A user-delegated agent is admitted under /articles/ if its delegation carries the articles scope, and under /premium/ only with the premium scope and a payment voucher.¶
The Access-Intent request field declares the purpose and use level of the request. It is a Structured Field Dictionary [RFC9651] with the following members:¶
Access-Intent: purpose="agent", use="reference"¶
The field MUST be a covered component of the request signature (Section 5.4). An origin MUST refuse with status 400 a request whose Access-Intent field is present but not covered, since an intermediary could otherwise add or alter the declaration. A signed request that carries no Access-Intent field is processed under the Unsigned directive of the matching Path block, so that clients implementing Web Bot Auth without this document are neither privileged nor broken.¶
The Access-Delegation request field carries a delegation token (Section 7) asserting that the request is made on behalf of a user who holds an entitlement at the origin. The token is issued by an identity provider the origin trusts; how the origin comes to trust an identity provider is out of scope. The field MUST be a covered component of the request signature.¶
A delegation token's claims are:¶
The Access-Payment request field carries a payment credential for a charged request. Its value is a method name, a space, and a method-specific credential. This document defines the "voucher" method, whose credential is a token (Section 7) issued by a settlement service the origin accepts. The field MUST be a covered component of the request signature.¶
A voucher's claims are:¶
How the settlement service is funded, how it settles with the origin, and whether the unit of account is the request, the citation, the answer, or the transaction are out of scope. The receipt defined in Section 6.1 is designed to make any of those units measurable.¶
Requests that carry an Access-Intent field MUST be signed as specified in [I-D.ietf-webbotauth-httpsig-protocol]. This document profiles that specification as follows:¶
An origin MUST look keys up by the pair of agent identifier and key identifier, and MUST NOT accept a key found under one identifier's directory for a request that resolves to another.¶
On every response that serves a resource to a signed request, the origin MUST include an Access-Receipt field whose value is a token (Section 7) signed with a key published at the origin's Receipt-Keys directory. Its claims are:¶
The origin SHOULD append each receipt to an append-only log whose entries are hash-chained, so that the log head commits to every receipt issued. The receipt gives both parties a non-repudiable record of which representation was delivered to which agent identifier under which terms, which is the input any settlement model or dispute requires. A receipt is evidence for the one request whose Signature field it hashes and for no other; in particular, a receipt obtained from a cache is not a receipt for the request that hit the cache (Section 10).¶
A Link field with relation type "access-terms" identifies the origin's terms.txt resource. Origins SHOULD include it on 400 and 403 responses to automated clients and MAY include it on 200 responses.¶
This document uses existing HTTP status codes with their defined semantics [RFC9110] and conveys the specific reason in a Problem Details body [RFC9457], in accordance with BCP 56 [RFC9205]. It does not use 401, which requires a WWW-Authenticate field that no HTTP authentication scheme here would supply, and it does not use 402, which RFC 9110 reserves and whose semantics this document is not the place to define.¶
Every 403 response under this document MUST carry a Problem Details body of media type application/problem+json and Cache-Control: no-store. For payment, the "type" member is the "payment-required" problem type registered in Section 13.4, and the body carries these additional members: "terms_id"; "purpose"; "price", an object with "amount" (an exact decimal string), "currency", and "unit"; "payment", an array of objects each with "method" and "settlement", so that each method is paired with its settlement URI; and "terms", the URI of the terms resource. For other refusals the "type" member is the "terms-refused" problem type and the body SHOULD carry "reason", one of "unsigned", "signature-invalid", "replay", "purpose-refused", "use-exceeds-terms", or "delegation-required".¶
Deployed systems that charge crawlers have used status 402 for the payment case. This document does not depend on that usage. Should the HTTP Working Group define semantics for 402, a future version of this document can adopt them.¶
When an unsigned request arrives on a path whose Unsigned directive is "challenge", the origin responds with status 403, a Problem Details body with reason "unsigned", and an Accept-Signature field as defined in [RFC9421] listing the components and parameters the origin requires, which is the behavior [I-D.ietf-webbotauth-httpsig-protocol] recommends for requesting a signature. For example:¶
Accept-Signature: sig1=("@method" "@target-uri"
"signature-agent";key="sig1" "access-intent");created;expires;
nonce;keyid;tag="web-bot-auth"
¶
Delegation tokens, payment vouchers, and receipts are JSON Web Signatures in Compact Serialization [RFC7515] signed with Ed25519 [RFC8032]. The JOSE header MUST contain "alg" with the value "Ed25519", the fully specified identifier registered by [RFC9864], and "kid" with the thumbprint of the signing key. The deprecated polymorphic identifier "EdDSA" [RFC8037] MUST NOT be used. The payload is the JSON object of claims [RFC8259]. Verifiers MUST reject a token whose "alg" is anything else, whose signature does not verify under the key identified by "kid" at the expected issuer, or whose "exp" claim is in the past.¶
Verifiers MUST enforce audience and agent binding. A token whose "aud" is not this origin, or whose "agent" is not the agent identifier that the request's Signature-Agent resolved to, MUST be refused. These two checks are what make a stolen token useless at any other origin or under any other identifier.¶
An origin that issues receipts publishes the corresponding public keys at the directory named by Receipt-Keys, using the same directory format and the same thumbprint key identifiers as [I-D.ietf-webbotauth-httpsig-protocol]. A third party verifying a receipt fetches the directory, selects the key whose thumbprint matches the receipt's "kid", and verifies the signature. Reusing the Web Bot Auth directory format means origins and operators publish keys the same way.¶
On receiving a request for a resource governed by terms.txt, an origin proceeds in the following order. The order matters for security: inexpensive checks precede cryptography, and replay reservation precedes any asynchronous discovery.¶
A client SHOULD fetch and cache the origin's terms.txt before its first governed request, and MUST refetch it when a 403 response carries a Link with the "access-terms" relation and the client's cached copy is older than the response. A client MUST declare a purpose it can substantiate and a use level it will not exceed. A client MUST NOT retry a refused request with a different declared purpose for the same fetch in order to find one the terms admit; it MAY select a purpose from the terms before the request.¶
A client SHOULD verify the Access-Receipt it receives against the origin's published key and retain it, since the receipt is its evidence of the terms it was served under.¶
A receipt is evidence for exactly one signed request. A response stored by any cache [RFC9111], shared or private, and reused for a later request would carry a receipt that hashes a different request's signature, and the origin would have issued no receipt and logged nothing for the later one. Origins MUST therefore mark responses that carry an Access-Receipt with Cache-Control: no-store. Responses to unsigned requests are unaffected and remain cacheable as today. A future version of this document may define a cacheable variant in which the receipt is obtained separately from the representation.¶
Because the signature covers the full target URI and the request fields defined here, an intermediary in front of the origin may forward the request unchanged for the origin to verify, or may verify on the origin's behalf and convey the result by a mechanism outside this document. An intermediary that rewrites a covered component invalidates the signature, which is the intended failure.¶
The security considerations of [RFC9421] and [I-D.ietf-webbotauth-httpsig-protocol] apply. The following are specific to this document.¶
False declarations. Nothing in this document prevents an operator from declaring a purpose or use level that does not match its behavior. What the signed declaration provides is attribution: an operator that declares reference use and reproduces content in full, or declares search and never refers, leaves evidence in receipts, in its own outputs, and in traffic, and that evidence names the operator. The remedy is revocation of the operator's standing, which is outside this document.¶
Target binding. A signature that covered only the path would leave the query string unbound, so that a request for one resource could be replayed against another at the same path. Covering "@target-uri" closes this. Requests with bodies are out of scope unless the body is covered through Content-Digest, since an uncovered body is likewise alterable.¶
Credential theft. Signature validity is bounded to 300 seconds. Delegation tokens and vouchers are bound to an audience and an agent identifier, so a token stolen from one agent cannot be presented under another identifier. Key rotation is handled through the key directory.¶
Replay. The replay store is the only defense against reuse of a captured signed request within its validity window. It MUST be consulted and updated atomically, before any asynchronous operation, and in multi-instance deployments MUST be shared across instances. A first version of the reference implementation reserved the nonce after key discovery and was vulnerable to two identical requests racing a cold lookup.¶
Cost-based denial of service. Verification costs the origin CPU per request and an attacker can force it. Origins SHOULD order cheap checks before cryptography, as in Section 9.1, SHOULD rate-limit per Signature Agent URL, and can rely on the observation that refusing a request costs less than serving one. In the reference implementation on a single shared vCPU, rejecting a forged signature cost 0.21 ms and a payment refusal 0.37 ms, against 0.65 ms for a paid, receipted response.¶
Identity. A verified signature establishes that a holder of a key published under the resolved agent identifier signed the request. It does not establish who operates the agent, and an origin that needs a real-world identity behind an identifier must obtain it by other means, for example the operator registry that [I-D.ietf-webbotauth-httpsig-protocol] anticipates. This document's terms, tokens, and receipts bind to the identifier, and its guarantees are stated in those terms.¶
Directory fetching. Fetching an operator's key directory is a server-side request to a URL named by the client. Origins MUST apply the discovery protections of [I-D.ietf-webbotauth-httpsig-protocol], including bounding response size and time, refusing redirects, and refusing non-HTTPS or non-origin URLs.¶
Unauthenticated clients. This document does not defeat scraping by clients that do not sign. It makes signed access more capable than unsigned access, since only signed requests can obtain delegated entitlements, paid content, or receipts, and it lets an origin require signatures on the paths where it matters.¶
The exchange reveals the operator's identity to the origin on every request; that is its purpose. It is designed not to reveal the user's identity. The delegation token's subject is a pairwise pseudonym chosen by the identity provider, stable for one identity provider and one origin, so that an origin can recognize a returning subscriber's agent without learning who the subscriber is or correlating them across origins. Receipts carry the pseudonym and no other user identifier. Identity providers MUST NOT use a globally stable identifier as the subject.¶
The terms.txt file itself is public and reveals an origin's pricing and policy. Origins that consider that sensitive can state terms only for the purposes they wish to admit.¶
IANA is requested to register the following in the "Well-Known URIs" registry [RFC8615]:¶
On the name: [RFC8615] discourages names that are overly generic. "terms.txt" is proposed because the resource is a text file of access terms and because the name signals, to the site operators who must deploy it, continuity with robots.txt, which is the mechanism it extends. Should the designated expert prefer a more specific name, "access-terms.txt" preserves both properties.¶
IANA is requested to register the following in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" [RFC9110], each with status "permanent" and this document as reference: Access-Intent (Section 5.1), Access-Delegation (Section 5.2), Access-Payment (Section 5.3), and Access-Receipt (Section 6.1).¶
IANA is requested to register the following in the "Link Relation Types" registry [RFC8288]:¶
IANA is requested to register the following in the "HTTP Problem Types" registry [RFC9457]:¶
IANA is requested to establish a "terms.txt Purpose Names" registry with the "Specification Required" policy [RFC8126]. Each entry has a name, a description, and a reference. The initial contents are the five names defined in Section 4.5, with this document as reference. Designated experts SHOULD keep names aligned with the categories of [I-D.ietf-aipref-vocab] where the meanings coincide.¶
This section records the status of known implementations as described in [RFC7942]. It will be removed before publication as an RFC.¶
A reference implementation in dependency-free JavaScript on Node.js 22 is archived at [TERMS-TXT-IMPL] and developed at https://github.com/rch0wdhury/terms-txt under the MIT license. It implements the terms.txt parser, the origin processing rules of Section 9.1, a directory resolver, and a harness of 24 conformance and correctness checks, including verification of the Ed25519 test vector E.2.1 of [I-D.ietf-webbotauth-httpsig-protocol], sequential and concurrent replay rejection, pair-scoped key lookup, scope and agent binding of delegation tokens, single-use vouchers, per-path unsigned policy, and hash-chain verification of the receipt log. Measured on one shared vCPU over loopback, identity verification added 0.20 ms per request over a passthrough server, a receipted search request 0.34 ms, a delegated request 0.49 ms, a payment refusal 0.37 ms, and a paid receipted request 0.65 ms.¶
Release v0.1 predates this document and deviates from it in the following respects, all of which are scheduled for the next release: it covers "@path" rather than "@target-uri"; it answers unverifiable signatures with 401 and payment with 402 rather than 403 with Problem Details; its tokens use a two-part payload-and-signature form rather than JWS with "alg" "Ed25519"; it binds tokens and receipts to the raw Signature-Agent value rather than the resolved agent identifier; its receipts omit the response status, Content-Digest, and terms digest; its vouchers omit the unit and encode amounts as numbers; it marks receipted responses private rather than no-store; and its Link relation is named "terms". Its measurements are reported for that release.¶
A user-delegated agent operated by https://bot.example requests a resource under /premium/ at origin.example, whose terms are those of Section 4.7. Line breaks in field values are for presentation only.¶
GET /premium/1 HTTP/1.1
Host: origin.example
Signature-Agent: sig1="https://bot.example"
Signature-Input: sig1=("@method" "@target-uri"
"signature-agent";key="sig1" "access-intent" "access-delegation"
"access-payment");created=1789000000;expires=1789000280;
nonce="Yw3f...";keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U";
tag="web-bot-auth"
Signature: sig1=:RdNF...:
Access-Intent: purpose="agent", use="reference"
Access-Delegation: eyJhbGciOiJFZDI1NTE5Iiwia2lkIjoiLi4uIn0.eyJpc3Mi...
Access-Payment: voucher eyJhbGciOiJFZDI1NTE5Iiwia2lkIjoiLi4uIn0.ey...
¶
Had the request carried no voucher, the origin would have answered:¶
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Cache-Control: no-store
Link: </.well-known/terms.txt>; rel="access-terms"
{"type":
"https://iana.org/assignments/http-problem-types#payment-required",
"title":"Payment required by access terms","status":403,
"terms_id":"2026-09-01","purpose":"agent",
"price":{"amount":"0.01","currency":"USD","unit":"request"},
"payment":[{"method":"voucher",
"settlement":"https://settle.example/.well-known/settlement"}],
"terms":"/.well-known/terms.txt"}
¶
With a valid voucher, the origin serves the resource:¶
HTTP/1.1 200 OK Content-Type: text/html Content-Digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=: Cache-Control: no-store Link: </.well-known/terms.txt>; rel="access-terms" Access-Receipt: eyJhbGciOiJFZDI1NTE5Iiwia2lkIjoiLi4uIn0.eyJpc3MiOiJv... <html>...</html>¶
The receipt payload, decoded:¶
{"iss":"origin.example","kid":"...",
"agent":
"https://bot.example/.well-known/http-message-signatures-directory",
"sub":"3kqJ...","purpose":"agent","use":"reference",
"terms_id":"2026-09-01","terms_digest":"uU0n...",
"method":"GET","target":"https://origin.example/premium/1",
"status":200,"content_digest":"sha-256=:X48E...:",
"req":"n4bQ...","ts":1789000001,"id":"9f1c..."}
¶
This document composes work by the authors of HTTP Message Signatures, Web Bot Auth, AI Preferences, and the Content Signals convention, and draws on measurements published by Cloudflare, Imperva, the Pew Research Center, and the Data Provenance Initiative. The enforcement boundary in Section 1.1 and the replay ordering in Section 9.1 were sharpened by review of an earlier version of the reference implementation.¶