Skip to main content

AAuth Budgets
draft-hardt-aauth-budgets-00

Document Type Active Internet-Draft (individual)
Author Dick Hardt
Last updated 2026-09-28
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-hardt-aauth-budgets-00
TBD                                                             D. Hardt
Internet-Draft                                                     Hellō
Intended status: Standards Track                       28 September 2026
Expires: 1 April 2027

                             AAuth Budgets
                      draft-hardt-aauth-budgets-00

Abstract

   This document defines AAuth Budgets, an extension to the AAuth
   Protocol ([I-D.hardt-oauth-aauth-protocol]) that carries a spending
   ceiling from a person server to a resource.  A budget is a ceiling on
   what an agent may consume at one resource, denominated in a unit the
   resource declares, carried as a claim in the auth token, and enforced
   by the resource.  Budgets are structurally parallel to scope: the
   agent asks, the resource offers, the person server and access server
   may narrow, and the auth token carries what was granted.  The
   extension adds a budget claim to resource tokens and auth tokens, a
   budget_consumed claim reporting what the presented auth token
   consumed, a budget_units field and a usage_endpoint to resource
   metadata, and an AAuth-Budget response header reporting what a
   request cost and what remains.

Discussion Venues

   _Note: This section is to be removed before publishing as an RFC._

   This document is part of the AAuth specification family.  Source for
   this draft and an issue tracker can be found at
   https://github.com/dickhardt/AAuth (https://github.com/dickhardt/
   AAuth).

Status of This Memo

   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."

Hardt                     Expires 1 April 2027                  [Page 1]
Internet-Draft                AAuth-Budgets               September 2026

   This Internet-Draft will expire on 1 April 2027.

Copyright Notice

   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.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
     1.1.  Non-Goals . . . . . . . . . . . . . . . . . . . . . . . .   5
   2.  Conventions and Definitions . . . . . . . . . . . . . . . . .   6
   3.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   6
   4.  Budget Model  . . . . . . . . . . . . . . . . . . . . . . . .   6
     4.1.  A Budget Is Structurally a Scope  . . . . . . . . . . . .   6
     4.2.  The Narrowing Chain . . . . . . . . . . . . . . . . . . .   7
     4.3.  Value Representation  . . . . . . . . . . . . . . . . . .   9
     4.4.  Range Limits  . . . . . . . . . . . . . . . . . . . . . .   9
     4.5.  The Budget Object . . . . . . . . . . . . . . . . . . . .  10
   5.  Resource Metadata Extensions  . . . . . . . . . . . . . . . .  10
   6.  Authorization Endpoint Extensions . . . . . . . . . . . . . .  12
   7.  Resource Token Extensions . . . . . . . . . . . . . . . . . .  13
     7.1.  The Consumption Record  . . . . . . . . . . . . . . . . .  13
   8.  Auth Token Endpoint Extensions  . . . . . . . . . . . . . . .  15
     8.1.  What the PS Is Deciding . . . . . . . . . . . . . . . . .  15
     8.2.  What the PS Reads . . . . . . . . . . . . . . . . . . . .  16
     8.3.  How the PS Responds . . . . . . . . . . . . . . . . . . .  16
   9.  PS-to-AS Token Request Extensions . . . . . . . . . . . . . .  18
   10. Auth Token Extensions . . . . . . . . . . . . . . . . . . . .  20
   11. AAuth-Budget Response Header  . . . . . . . . . . . . . . . .  21
     11.1.  Sending Rules  . . . . . . . . . . . . . . . . . . . . .  22
     11.2.  Denomination Conflict  . . . . . . . . . . . . . . . . .  23
   12. Streaming . . . . . . . . . . . . . . . . . . . . . . . . . .  23
     12.1.  When cost Is Omitted . . . . . . . . . . . . . . . . . .  23
     12.2.  Trailer Rules  . . . . . . . . . . . . . . . . . . . . .  24
     12.3.  Ambiguous Failures . . . . . . . . . . . . . . . . . . .  25
   13. Budget Exhaustion . . . . . . . . . . . . . . . . . . . . . .  25
     13.1.  The reason Parameter . . . . . . . . . . . . . . . . . .  26
     13.2.  Refusing a Request That Does Not Fit . . . . . . . . . .  27

Hardt                     Expires 1 April 2027                  [Page 2]
Internet-Draft                AAuth-Budgets               September 2026

     13.3.  Deferred Delivery  . . . . . . . . . . . . . . . . . . .  28
     13.4.  Boundaries . . . . . . . . . . . . . . . . . . . . . . .  29
   14. Enforcement . . . . . . . . . . . . . . . . . . . . . . . . .  30
     14.1.  The Resource Enforces  . . . . . . . . . . . . . . . . .  30
     14.2.  Budgets Require Auth-Token Mode  . . . . . . . . . . . .  30
     14.3.  Token Scope  . . . . . . . . . . . . . . . . . . . . . .  30
     14.4.  Unreported Allocations . . . . . . . . . . . . . . . . .  31
       14.4.1.  Settlement . . . . . . . . . . . . . . . . . . . . .  32
     14.5.  Aggregation  . . . . . . . . . . . . . . . . . . . . . .  33
     14.6.  The Billing Account  . . . . . . . . . . . . . . . . . .  34
     14.7.  Concurrency  . . . . . . . . . . . . . . . . . . . . . .  36
     14.8.  The Budget Is a Hard Cap . . . . . . . . . . . . . . . .  36
     14.9.  Failed Calls . . . . . . . . . . . . . . . . . . . . . .  37
     14.10. Delegation . . . . . . . . . . . . . . . . . . . . . . .  37
     14.11. Mission Attribution  . . . . . . . . . . . . . . . . . .  37
   15. Usage Counters  . . . . . . . . . . . . . . . . . . . . . . .  38
     15.1.  Usage Request  . . . . . . . . . . . . . . . . . . . . .  38
     15.2.  Usage Response . . . . . . . . . . . . . . . . . . . . .  39
       15.2.1.  Calendar Counters  . . . . . . . . . . . . . . . . .  40
       15.2.2.  Per-Key Figures  . . . . . . . . . . . . . . . . . .  41
       15.2.3.  One Unit Per Response  . . . . . . . . . . . . . . .  41
       15.2.4.  The Signed Response  . . . . . . . . . . . . . . . .  42
     15.3.  Authorization and Errors . . . . . . . . . . . . . . . .  43
     15.4.  Division of Labor  . . . . . . . . . . . . . . . . . . .  43
   16. Capability Negotiation  . . . . . . . . . . . . . . . . . . .  44
   17. Errors  . . . . . . . . . . . . . . . . . . . . . . . . . . .  44
     17.1.  Declining with Guidance  . . . . . . . . . . . . . . . .  46
   18. Standing Authorization for Metered Inference  . . . . . . . .  46
   19. Security Considerations . . . . . . . . . . . . . . . . . . .  47
     19.1.  The Header Is Unsigned . . . . . . . . . . . . . . . . .  47
     19.2.  Budget Is Not a Substitute for Scope . . . . . . . . . .  48
     19.3.  Over-Issuance Through Concurrency  . . . . . . . . . . .  48
     19.4.  Consumption Reports as Attack Surface  . . . . . . . . .  48
     19.5.  Unit Substitution  . . . . . . . . . . . . . . . . . . .  49
   20. Privacy Considerations  . . . . . . . . . . . . . . . . . . .  49
   21. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  49
     21.1.  HTTP Header Field Registration . . . . . . . . . . . . .  50
     21.2.  JWT Claims Registration  . . . . . . . . . . . . . . . .  50
     21.3.  AAuth Capability Value Registry  . . . . . . . . . . . .  50
     21.4.  No Budget Unit Registry  . . . . . . . . . . . . . . . .  51
   22. Implementation Status . . . . . . . . . . . . . . . . . . . .  51
     22.1.  Implementations in Progress  . . . . . . . . . . . . . .  51
   23. Document History  . . . . . . . . . . . . . . . . . . . . . .  51
   24. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . .  52
   25. References  . . . . . . . . . . . . . . . . . . . . . . . . .  52
     25.1.  Normative References . . . . . . . . . . . . . . . . . .  52
     25.2.  Informative References . . . . . . . . . . . . . . . . .  53
   Appendix A.  Design Rationale . . . . . . . . . . . . . . . . . .  54

Hardt                     Expires 1 April 2027                  [Page 3]
Internet-Draft                AAuth-Budgets               September 2026

     A.1.  Why an Integer in a Declared Scale  . . . . . . . . . . .  54
     A.2.  Why the Scale Is Explicit . . . . . . . . . . . . . . . .  54
     A.3.  Why decimals Is in the Signed Claim . . . . . . . . . . .  55
     A.4.  Why One Record  . . . . . . . . . . . . . . . . . . . . .  55
     A.5.  Why the Agent Is Not Told Its Cumulative Consumption  . .  56
     A.6.  Why the Granted Budget Is Not the Person's Ceiling  . . .  57
     A.7.  Why a Trailer Only Adds a Member  . . . . . . . . . . . .  58
     A.8.  Why Not RateLimit . . . . . . . . . . . . . . . . . . . .  58
     A.9.  Why Budget Is Not a Mission Aggregate . . . . . . . . . .  59
     A.10. Why Units Are Not Registered  . . . . . . . . . . . . . .  59
   Appendix B.  Prior Art  . . . . . . . . . . . . . . . . . . . . .  60
     B.1.  RFC 9396, Rich Authorization Requests . . . . . . . . . .  60
     B.2.  TPX . . . . . . . . . . . . . . . . . . . . . . . . . . .  61
     B.3.  UK Open Banking Variable Recurring Payments . . . . . . .  61
     B.4.  Stripe Issuing Spending Controls  . . . . . . . . . . . .  61
     B.5.  W3C Payment Request API . . . . . . . . . . . . . . . . .  62
     B.6.  x402  . . . . . . . . . . . . . . . . . . . . . . . . . .  62
     B.7.  ODRL  . . . . . . . . . . . . . . . . . . . . . . . . . .  62
     B.8.  RateLimit Header Fields . . . . . . . . . . . . . . . . .  62
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  62

1.  Introduction

   *Status: Exploratory Draft*

   The AAuth Protocol ([I-D.hardt-oauth-aauth-protocol]) lets a person
   server (PS) decide whether an agent may access a resource, and lets
   the resource express what access it offers.  Neither party has a way
   to say _how much_.

   For a resource that meters and charges per call, that omission is the
   whole authorization decision.  An agent harness calling a model
   inference endpoint on a person's account can spend without bound: the
   scope inference.completions is either granted or not, and once
   granted it says nothing about whether the agent may consume ten cents
   or ten thousand dollars of the person's money.  The person's only
   controls are outside the protocol — a provider dashboard, a card
   limit, a bill that arrives after the fact.

   This document defines a *budget*: a ceiling on what an agent may
   consume at one resource, denominated in a unit the resource declares,
   carried as a claim in the auth token, and enforced by the resource.

Hardt                     Expires 1 April 2027                  [Page 4]
Internet-Draft                AAuth-Budgets               September 2026

   A budget is an authorization, not a hint.  The PS has authorized the
   agent to spend up to a stated amount, and the resource is the party
   that counts.  That distinction determines nearly every design choice
   in this document, in particular why the balance cannot be reported
   through RateLimit ([I-D.ietf-httpapi-ratelimit-headers]) — see
   Appendix A.8.

   The granted budget is an allocation, not the person's ceiling.  The
   ceiling is the person server's own state: no claim carries it, and it
   may not be shared with the agent.  The PS sizes each auth token
   against what the work has cost so far, and the token's expiry or its
   budget's exhaustion — whichever comes first — brings the agent back
   for the next allocation.  That return is the supervision point, and
   the PS's options there are the subject of Section 8.  Nobody knows at
   mission approval what an agent's work will cost; a figure fixed once
   up front is either too small to finish or too large to be a control
   Appendix A.6.

   Metered inference is the initiating use case, and Section 18 covers
   it as a named deployment pattern.  The mechanism is general: any
   resource that meters and charges per call uses it unchanged.

   TPX [TPX] profiles the same grant for OAuth 2.0: a person grants a
   human-driven app a metered inference budget — "a damage cap, not a
   payment" — from a provider the person chooses and pays.  This
   document is the AAuth counterpart: the same grant, carried to an
   autonomous agent through the narrowing chain, and generalized beyond
   inference to any resource that meters.  A provider implementing both
   accepts two authorization envelopes over one meter Section 18.

1.1.  Non-Goals

   *  *Not a mission aggregate.* A budget covers a single resource in a
      single unit.  It does not express a cross-resource total such as
      "$5,000 for the Japan trip."  Mission-wide totals require
      aggregation across resources that meter in different units, which
      this document does not define.
   *  *Not a rate limit.* A budget is cumulative consumption, not per-
      window throughput.  RateLimit and RateLimit-Policy
      ([I-D.ietf-httpapi-ratelimit-headers]) cover throughput.  Both MAY
      appear on the same response as AAuth-Budget, meaning different
      things.
   *  *Not pricing.* The resource prices its own service.  A budget
      bounds spend at whatever prices the resource charges; this
      document defines no way to express a price.

Hardt                     Expires 1 April 2027                  [Page 5]
Internet-Draft                AAuth-Budgets               September 2026

   *  *Not composite.* A budget is one amount in one unit.  A resource
      that meters several quantities at different rates — input tokens,
      output tokens, cache reads — collapses them to one billing unit,
      typically currency, before denominating a budget.
   *  *Not payment or settlement.* No funds move. 402 Payment Required
      and the resource's commercial arrangement with the person are
      untouched.
   *  *Not PS-enforced at request time.* The PS authorizes a number.
      The resource counts against it.  The PS is not in the request
      path.
   *  *Not an OAuth extension.* This document defines claims in AAuth
      tokens (aa-resource+jwt, aa-auth+jwt), fields in aauth-
      resource.json, a resource endpoint, an AAuth capability value, and
      an AAuth response header.  It registers nothing in an OAuth
      registry.  The documents surveyed in Appendix B are cited as prior
      art and are non-normative.

2.  Conventions and Definitions

   {::boilerplate bcp14-tagged}

3.  Terminology

   *  *Budget*: A ceiling on what an agent may consume at one resource,
      expressed as an amount in a unit the resource declares.
   *  *Unit*: A resource-declared identifier for what is being metered —
      a currency code, a token count, a call count.
   *  *Scale*: The number of decimal places implied by a budget amount,
      carried as decimals.  An amount of 5000000 with decimals of 6 is
      5.000000 of the unit.
   *  *Granted budget*: The budget claim of an auth token.  The figure
      the resource enforces against.
   *  *Consumption*: What the resource has metered against a granted
      budget, in the same unit and scale.
   *  *Consumption record*: A {jti, consumed} pair reporting what the
      resource metered against one auth token's budget, as of the
      resource token that carries it.  Carried in the budget_consumed
      claim of a resource token.
   *  *Usage counters*: Calendar-aligned consumption totals a person
      server reads at the resource's usage_endpoint.

4.  Budget Model

4.1.  A Budget Is Structurally a Scope

   The AAuth Protocol defines scope in three positions with a narrowing
   rule ([I-D.hardt-oauth-aauth-protocol], Scopes).  A budget occupies
   the same three positions, plus the PS-to-AS hop in four-party access:

Hardt                     Expires 1 April 2027                  [Page 6]
Internet-Draft                AAuth-Budgets               September 2026

       +==================+===================+===================+
       | Position         | scope             | budget            |
       +==================+===================+===================+
       | Authorization    | what the agent    | what the agent    |
       | endpoint request | asks for          | asks for          |
       +------------------+-------------------+-------------------+
       | Resource token   | what the resource | what the resource |
       |                  | will grant        | will grant        |
       +------------------+-------------------+-------------------+
       | PS-to-AS token   | (n/a)             | what the PS will  |
       | request          |                   | allow             |
       +------------------+-------------------+-------------------+
       | Auth token       | granted, MUST NOT | granted, MUST NOT |
       |                  | be broader        | exceed            |
       +------------------+-------------------+-------------------+

                                 Table 1

   The base protocol's rule that a resource token MUST only include
   resource scopes the resource has declared in its scope_descriptions
   metadata has a direct parallel here: a resource token MUST only name
   a unit the resource has declared in budget_units Section 5.

   This extension therefore introduces one new claim shape and no new
   authorization semantics.  Every party that already knows how to
   narrow a scope knows how to narrow a budget.

4.2.  The Narrowing Chain

   Each stage MUST NOT exceed the previous stage.  There is one
   asymmetry between the amount and the denomination: the resource
   settles the denomination, and no later party may change it.

Hardt                     Expires 1 April 2027                  [Page 7]
Internet-Draft                AAuth-Budgets               September 2026

   Agent            Resource          PS               AS
     |                 |               |                |
     | budget request  |               |                |
     | (OPTIONAL)      |               |                |
     |---------------->|               |                |
     |                 | sets unit and decimals,        |
     |                 | MAY lower amount               |
     |                 |               |                |
     |  resource token (budget)        |                |
     |<----------------|               |                |
     |                 |               |                |
     |  resource token |               |                |
     |-------------------------------->|                |
     |                 |               | MAY lower      |
     |                 |               | amount         |
     |                 |               |                |
     |                 |     budget (four-party only)   |
     |                 |               |--------------->|
     |                 |               |                | MAY lower
     |                 |               |                | amount
     |                 |               |  auth token    |
     |                 |               |<---------------|
     |  auth token (granted budget)    |                |
     |<--------------------------------|                |

   {: #fig-narrowing title="Budget narrowing.  Only the resource sets
   the unit and scale."}

   1.  *The agent requests.* OPTIONAL.  A budget object in the
       authorization endpoint request Section 6.  Omitting it means the
       resource applies its own default.  Requesting more than the
       resource will allow is NOT an error; the resource narrows.

   2.  *The resource sets the unit and scale, and MAY lower the amount.*
       The resource is the enforcer and the only party that knows its
       own pricing, so it settles the denomination.  It MAY change unit
       from what the agent requested — for example converting a request
       denominated in tokens into a currency amount.  After this stage,
       unit and decimals are fixed for the life of the grant.

   3.  *The PS MAY lower the amount.* The PS MUST NOT change unit or
       decimals.  It is applying the person's policy to a figure the
       resource denominated; a PS that redenominated would be stating a
       budget in something the resource may not meter in.

   4.  *The AS MAY lower the amount* (four-party only), for its own
       credit or risk reasons.  The same prohibition on changing unit or
       decimals applies.

Hardt                     Expires 1 April 2027                  [Page 8]
Internet-Draft                AAuth-Budgets               September 2026

   Because the resource MAY change the unit, an agent MUST NOT assume
   the granted budget is directly comparable to what it requested.  The
   agent reads what it actually got from the budget claim of its auth
   token.

   The resource token carries one figure, not both the agent's request
   and the resource's own maximum.  It is the minimum of the two,
   exactly as scope is.  What the agent originally asked for has no
   bearing on the PS's decision; an agent that wants the PS to know it
   belongs in justification ([I-D.hardt-oauth-aauth-protocol], Auth
   Token Endpoint).

4.3.  Value Representation

   A budget amount is a *non-negative integer in a scale the resource
   declares*. It is not a floating-point number and not a decimal
   string.

   The value of a budget is amount divided by 10 raised to the power of
   decimals, in unit.  An amount of 5000000 with unit of USD and
   decimals of 6 is five US dollars.

   The scale is declared per unit, not globally.  A resource metering US
   dollars per inference call wants decimals of 6 to represent micro-
   dollars; a resource metering Japanese yen wants 0, matching the ISO
   4217 [ISO4217] minor unit; a resource metering tokens wants 0.

   decimals is the name x402 [x402] and ERC-20 [ERC20] use for this
   quantity.  ISO 4217 and ISO 20022 call it the minor unit.  This
   document does not introduce a third name.  See Appendix A.1 for why
   the value is an integer and Appendix A.2 for why the scale travels
   with the amount rather than being derived from the unit identifier.

4.4.  Range Limits

   Two carriers bound the representable range:

   *  A Structured Field Integer ([RFC9651], Section 3.3.1) is limited
      to 15 digits, which bounds remaining, cost, and reserved in the
      AAuth-Budget header Section 11.
   *  A JSON number is exact only to 2^53 (approximately 9.0 x 10^15),
      which bounds the amount member of the budget claim.

   US dollars at decimals of 6 therefore top out near 10^9 per budget,
   which is well beyond any plausible grant.  Implementations MUST NOT
   issue a budget whose amount exceeds 999,999,999,999,999 (15 digits),
   so that the amount and every derived figure remain representable in
   both carriers.

Hardt                     Expires 1 April 2027                  [Page 9]
Internet-Draft                AAuth-Budgets               September 2026

   If assets requiring 18 decimal places come into scope, both carriers
   break and amount would have to become a string, as it is in x402.
   This document does not define that change.

4.5.  The Budget Object

   One shape appears in every position — the authorization endpoint
   request, the resource token, the PS-to-AS token request, and the auth
   token:

   {
     "amount": 5000000,
     "unit": "USD",
     "decimals": 6
   }

   Members:

   *  *amount* (REQUIRED).  A non-negative integer, subject to
      Section 4.4.
   *  *unit* (REQUIRED).  A string identifying what is metered.  For
      currency, the value SHOULD be an ISO 4217 [ISO4217] alphabetic
      code.  Units are resource-declared; this document establishes no
      registry of unit values, for the same reason the base protocol
      establishes no registry of scope values.
   *  *decimals* (REQUIRED).  A non-negative integer giving the scale of
      amount.  When unit is an ISO 4217 code, decimals is NOT
      constrained to that currency's minor unit; see Appendix A.2.

   The object appears alongside scope wherever both are present:

   {
     "scope": "inference.completions",
     "budget": { "amount": 5000000, "unit": "USD", "decimals": 6 }
   }

5.  Resource Metadata Extensions

   This document extends the /.well-known/aauth-resource.json document
   defined in AAuth Protocol ([I-D.hardt-oauth-aauth-protocol]) with two
   fields:

Hardt                     Expires 1 April 2027                 [Page 10]
Internet-Draft                AAuth-Budgets               September 2026

   {
     "issuer": "https://inference.example",
     "jwks_uri": "https://inference.example/.well-known/jwks.json",
     "access_mode": "auth-token",
     "authorization_endpoint": "https://inference.example/authorize",
     "scope_descriptions": {
       "inference.completions": "Generate completions,
         billed to your account"
     },
     "budget_units": [
       { "unit": "USD", "decimals": 6, "max": 10000000 },
       { "unit": "tokens", "decimals": 0, "max": 5000000 }
     ],
     "usage_endpoint": "https://inference.example/usage",
     "revocation_endpoint": "https://inference.example/revoke"
   }

   *budget_units* (OPTIONAL).  An array of objects, each declaring one
   unit the resource will denominate a budget in.  Each object contains:

   *  *unit* (REQUIRED).  The unit identifier.
   *  *decimals* (REQUIRED).  The scale the resource uses for this unit.
      A resource MUST use this value in every budget it issues for this
      unit.
   *  *max* (RECOMMENDED).  A non-negative integer, in this unit's
      scale, giving the largest amount the resource will accept on a
      single auth token.  It lets an agent on the proactive path request
      something the resource will honor rather than discovering the
      ceiling by having its request narrowed.
   *  *description* (OPTIONAL).  A Markdown string describing what the
      unit meters, for display at a consent screen.  Implementations
      MUST sanitize the Markdown before rendering to users.

   A resource that declares budget_units MUST NOT issue a resource token
   whose budget.unit is absent from the array, and MUST set
   budget.decimals to the value declared for that unit.

   *usage_endpoint* (OPTIONAL).  The HTTPS URL where a person server or
   access server queries usage counters Section 15.  The URL MUST
   conform to the requirements the base protocol places on endpoint URLs
   ([I-D.hardt-oauth-aauth-protocol], Endpoint and Other URLs).

   The example also carries revocation_endpoint, which the base protocol
   recommends for a resource that accepts person tokens, as a metered
   resource does ([I-D.hardt-oauth-aauth-protocol], Resource Metadata).
   Settlement of a revoked token depends on it Section 14.4.1.

Hardt                     Expires 1 April 2027                 [Page 11]
Internet-Draft                AAuth-Budgets               September 2026

   A PS or AS that receives a resource token carrying budget already
   fetches {iss}/.well-known/aauth-resource.json to discover the
   resource's JWKS, per the dwk claim
   ([I-D.hardt-httpbis-signature-key]).  The unit declarations arrive in
   a fetch it was already making, so the cross-check in Section 17 costs
   no extra round trip.

6.  Authorization Endpoint Extensions

   An agent MAY include a budget object Section 4.5 in the authorization
   endpoint request body alongside scope:

   POST /authorize HTTP/1.1
   Host: inference.example
   Content-Type: application/json
   AAuth-Capabilities: interaction, budget
   Signature-Input: sig=("@method" "@authority"
       "@path" "signature-key");created=1754611200
   Signature: sig=:...signature bytes...:
   Signature-Key: sig=jwt;jwt="eyJhbGciOiJFZDI1NTE5IiwidHlwIjoiYWEtcGVyc29uK2p3dCIsImtpZCI6InBzLWtleS0xIn0..."

   {
     "scope": "inference.completions",
     "budget": { "amount": 10000000, "unit": "USD", "decimals": 6 }
   }

   The agent presents a person token at the authorization endpoint, as
   the base protocol requires ([I-D.hardt-oauth-aauth-protocol],
   Authorization Endpoint).

   *budget* (OPTIONAL).  The ceiling the agent is requesting.  All three
   members of the budget object are REQUIRED when budget is present.

   The resource MUST NOT reject the request because budget.amount
   exceeds what it will grant; it narrows instead Section 4.2.  The
   resource MAY reject a budget whose unit it has not declared
   Section 17.

   When the agent obtains its resource token from a 401 challenge rather
   than the authorization endpoint ([I-D.hardt-oauth-aauth-protocol],
   Auth Token Required), it has not stated a budget and the resource
   sizes the resource token on its own.  This is why max in budget_units
   matters: it is what makes the proactive path useful on a first
   attempt.

   How an agent knows an operation is metered before its first call is
   answered by R3 ([I-D.hardt-aauth-r3]): a resource MAY annotate
   individual operations in its vocabulary with a budget annotation, and

Hardt                     Expires 1 April 2027                 [Page 12]
Internet-Draft                AAuth-Budgets               September 2026

   an agent that reads one knows to include budget in this request.  The
   annotation states the fact of metering; budget_units states the units
   and ceilings.

7.  Resource Token Extensions

   This document extends the resource token (a JWT with typ: aa-
   resource+jwt) with two optional claims.

   *  *budget* (OPTIONAL): A budget object Section 4.5.  The ceiling the
      resource is willing to have granted.  Subject to the rules in
      Section 5.
   *  *budget_consumed* (OPTIONAL): A consumption record Section 7.1 for
      the auth token presented on the request this resource token
      answers — what it has consumed to date.  Not a grant.

   {
     "iss": "https://inference.example",
     "dwk": "aauth-resource.json",
     "aud": "https://ps.example",
     "jti": "rt-4c81fa",
     "ps": "https://ps.example",
     "sub": "8f14e45fceea167a5a36dedd4bea2543",
     "presented_jti": "at-71b9d0",
     "agent_jkt": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
     "tenant": "corp",
     "mission_s256": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
     "scope": "inference.completions",
     "budget": { "amount": 5000000, "unit": "USD", "decimals": 6 },
     "budget_consumed": { "jti": "at-71b9d0", "consumed": 2000000 },
     "iat": 1754612400,
     "exp": 1754612700
   }

   This example is the resource token a resource issues on a challenge
   to a request presenting the auth token of Section 10 once that
   token's grant is spent, so presented_jti and the record both name
   that token.

7.1.  The Consumption Record

   budget_consumed is a single consumption record with two members, both
   REQUIRED:

   *  *jti*: The jti claim of the auth token presented on the request
      this resource token answers.  This is the value the resource token
      carries as presented_jti ([I-D.hardt-oauth-aauth-protocol],
      Resource Token Structure).

Hardt                     Expires 1 April 2027                 [Page 13]
Internet-Draft                AAuth-Budgets               September 2026

   *  *consumed*: What the resource has metered against that token's
      budget, as of this resource token's iat: a non-negative integer in
      the unit and decimals of the budget claim in the same resource
      token.

   A resource MUST NOT include budget_consumed unless budget is present
   in the same token, and MUST omit it rather than state it in another
   scale — a record carried in a stale scale is the thousandfold error
   Section 17 in miniature.

   The record exists for one figure the issuer needs and cannot compute.
   budget-exhausted implies the whole grant was spent, but under
   insufficient-budget Section 13, and on a token that expired with
   budget left, the token's spend to date is a number only the resource
   holds — and without it the issuer accounts for the allocation as
   fully consumed Section 14.4 when most of it may remain.  A resource
   issuing a resource token on a challenge to a request that carried an
   auth token SHOULD include the record.  A resource issuing one on a
   person token, at its authorization endpoint or on the first challenge
   of a grant, has no auth token to report on and omits the claim.  In
   four-party access the resource token travels to the AS inside the
   PS's token request, so the record reaches both issuers without a
   usage query.

   The record is as of the resource token's iat.  It is a snapshot: the
   token it names is still valid, since a resource issues a resource
   token only on a request carrying a valid person token or auth token,
   and the token may spend more before it expires.  A later record for
   the same jti supersedes an earlier one.  A token's final figure is
   settled by the usage reading Section 14.4.1.

   A record is deliberately two members and no more.  The jti it names
   is a token the PS issued — or, in four-party access, relayed from the
   AS — so the issuer already holds the granted amount, the mission, the
   scope, and the issuance time, and joins them from its own ledger.
   Carrying those values again would duplicate what the issuer knows and
   put more of the person's financial detail into a token the agent also
   reads.  What the issuer cannot know, and what the record supplies, is
   what the resource actually metered.

Hardt                     Expires 1 April 2027                 [Page 14]
Internet-Draft                AAuth-Budgets               September 2026

   The record rides in the resource token because it already travels
   resource → agent → PS at exactly the moment the PS re-decides: no
   extra round trip, resource-signed, and interpretable without a
   metadata fetch.  It names the presented token and nothing else.  The
   spend under a person's other tokens is served at the usage endpoint
   Section 15, which answers that question better — per key, per
   mission, over calendar periods — on a channel the agent is not on.
   An earlier revision carried up to twenty records; Appendix A.4 says
   why one is enough.

8.  Auth Token Endpoint Extensions

   No new request parameter is defined for the agent's request to the
   PS's auth_token_endpoint.  The budget reaches the PS inside the
   resource token.

   An agent seeking a larger budget obtains a fresh resource token from
   the resource — stating the larger figure in the authorization
   endpoint request Section 6, or being handed one on a 401 Section 13 —
   and SHOULD explain the need in the justification parameter of the
   auth token request.

   When the PS issues the auth token itself (three-party), it applies
   the person's policy and issues per Section 10.  When it federates
   (four-party), it proceeds per Section 9.

8.1.  What the PS Is Deciding

   The resource token's budget states what the resource will allow.  It
   is an offer, not a request the PS is obliged to answer in full.

   Against that offer the PS holds a ceiling for the person at this
   resource — a standing limit, a mission's stated intent, an
   organizational policy, or a figure the person supplied when asked.
   The ceiling is PS state.  This document defines no wire format for
   it, no claim that carries it, and no way for the agent to read it.
   What the PS issues is an allocation drawn against it.

   Sizing the allocation is where the PS's supervision happens.  A PS
   that issues the resource's full offer every time has authorized the
   resource's maximum and learns nothing until the money is gone.  A PS
   that issues a fraction sees the agent again when that fraction is
   spent, with the token's consumption record in hand, and decides then
   whether the work is going as the person expected.

   The interval is not fixed by the clock.  An auth token expires within
   an hour, and its budget is exhausted after however much work it took
   to spend — whichever comes first returns the agent to the PS.  A

Hardt                     Expires 1 April 2027                 [Page 15]
Internet-Draft                AAuth-Budgets               September 2026

   mission running cheaply reports on the hour; one running expensively
   reports in minutes.  The PS sets that frequency by sizing the
   allocation, and no party configures it Section 14.3.

8.2.  What the PS Reads

   Four inputs are available at the moment of the decision, and a PS
   applying the person's policy SHOULD use all of them:

   *  *budget_consumed* Section 7.1 in the resource token the agent just
      presented: what the token it was presenting has cost so far,
      resource-signed, arriving at no round-trip cost.
   *  *Usage counters* Section 15 at the resource's usage_endpoint:
      totals over calendar periods, and for a mission query the
      mission's total to date — the figures that cover the stretch when
      the agent was not talking to the PS.
   *  *The mission log* ([I-D.hardt-oauth-aauth-protocol], Mission Log):
      every prior token request, justification, and clarification in
      this mission, which is what makes "faster than expected" a
      judgement the PS can actually make.
   *  *The justification* parameter of this request: why the agent says
      it needs more.

   The first two are the spend; the second two are the context.  A
   budget escalation is not interpretable without both.

8.3.  How the PS Responds

   Six responses are available.  None is new to this document; the base
   protocol defines each, and this section states which apply to a
   budget decision.

Hardt                     Expires 1 April 2027                 [Page 16]
Internet-Draft                AAuth-Budgets               September 2026

        +=================+=======================================+
        | Response        | Mechanism                             |
        +=================+=======================================+
        | Grant the offer | Issue an auth token with budget equal |
        |                 | to the resource token's Section 10    |
        +-----------------+---------------------------------------+
        | Grant less      | Issue a lower amount Section 4.2      |
        +-----------------+---------------------------------------+
        | Ask the agent   | 202 with requirement=clarification    |
        +-----------------+---------------------------------------+
        | Ask the person  | 202 with requirement=interaction      |
        +-----------------+---------------------------------------+
        | Decline with a  | Error response carrying               |
        | figure          | suggested_budget Section 17.1         |
        +-----------------+---------------------------------------+
        | End the work    | Terminate the mission                 |
        +-----------------+---------------------------------------+

                                  Table 2

   Granting less needs no signalling: the amount in the issued claim is
   the answer, and the agent reads it from the token it received
   Section 4.2.

   *Clarification is the response for an escalation the PS is not ready
   to refuse or approve.* A PS that sees consumption running ahead of
   what the mission implies MAY return 202 with
   requirement=clarification ([I-D.hardt-oauth-aauth-protocol],
   Clarification Required), putting a question to the agent before
   deciding.  This is the channel that lets the PS tell an agent it is
   overspending, which narrowing alone cannot do — a smaller amount is
   silent, and the agent cannot distinguish a PS applying pressure from
   a resource lowering its own offer.

   HTTP/1.1 202 Accepted
   Location: /pending/abc123
   Retry-After: 0
   Cache-Control: no-store
   AAuth-Requirement: requirement=clarification
   Content-Type: application/json

   {
     "status": "pending",
     "clarification": "This mission has spent $18 of an
       expected $25 and has not booked anything yet. What
       is the remaining $12 for?",
     "timeout": 120
   }

Hardt                     Expires 1 April 2027                 [Page 17]
Internet-Draft                AAuth-Budgets               September 2026

   The agent's three replies are already defined and all three are
   useful here: a clarification_response explaining the spend, an
   updated_request carrying a fresh resource token for a smaller figure
   with the presented_token it used to obtain it
   ([I-D.hardt-oauth-aauth-protocol], Updated Request), or a DELETE
   withdrawing the request.  The base protocol's limit on clarification
   rounds applies ([I-D.hardt-oauth-aauth-protocol], Clarification
   Limits).  An agent that did not declare the clarification capability
   cannot be asked, and the PS decides without it.

   Asking the person is the same mechanism one step further out, and is
   the right response when the answer is the person's rather than the
   agent's — a ceiling raise rather than an allocation.

   A PS that puts a budget to the person for consent MUST present the
   amount as a human-readable figure in its unit — "$5.00", not
   {5000000, USD, 6} — visually distinct from any resource-supplied
   description, which is Markdown and MUST be sanitized before rendering
   Section 5.  The amount is the decision the person is making.

   Ending the work is the response to an agent whose spending the PS
   cannot account for.  Terminating a mission is not a budget mechanism
   and this document defines nothing about it; it is named here because
   a budget escalation is one of the few signals that reliably surfaces
   an agent behaving unlike its mission.

9.  PS-to-AS Token Request Extensions

   This document extends the PS-to-AS token request
   ([I-D.hardt-oauth-aauth-protocol], PS-to-AS Token Request) with one
   parameter, used in four-party access only.

   *budget* (OPTIONAL): A budget object Section 4.5 carrying the ceiling
   the PS will allow.

Hardt                     Expires 1 April 2027                 [Page 18]
Internet-Draft                AAuth-Budgets               September 2026

   POST /token HTTP/1.1
   Host: as.inference.example
   Content-Type: application/json
   Content-Digest: sha-256=:...:
   Signature-Input: sig=("@method" "@authority" "@path"
       "content-type" "content-digest"
       "signature-key");created=1754611200
   Signature: sig=:...signature bytes...:
   Signature-Key: sig=jwks_uri;id="https://ps.example";
       dwk="aauth-person.json";kid="key-1"

   {
     "resource_token": "eyJhbGc...",
     "agent_token": "eyJhbGc...",
     "presented_token": "eyJhbGc...",
     "budget": { "amount": 2000000, "unit": "USD", "decimals": 6 }
   }

   The PS MUST copy unit and decimals from the resource token's budget
   claim unchanged, and MUST NOT set amount higher than the resource
   token's budget.amount.  The AS MUST NOT issue a budget claim
   exceeding this parameter, and MAY lower it further.

   When the AS returns an auth token, the PS MUST verify, along with the
   checks of the base protocol's Auth Token Delivery, that the token
   carries a budget claim when the PS sent a budget parameter, that the
   claim has the unit and decimals of that parameter and an amount no
   higher, and that the token carries no budget claim when the PS sent
   no budget parameter.  A token without a budget claim would leave the
   resource to apply its own default, which can exceed what the PS
   allowed.  A token that fails is an auth token that fails delivery
   verification, and the PS answers the agent as_unreachable
   ([I-D.hardt-oauth-aauth-protocol], Auth Token Delivery).  This is the
   budget counterpart of the base protocol's check that the AS's scope
   is no broader than the resource token's.

   When the resource token carries budget and the PS omits this
   parameter, the AS MUST NOT issue a budget claim.  A PS that grants
   the resource's full offer says so by echoing the resource token's
   budget; omission is what a PS that does not implement this extension
   sends, and it MUST NOT be read as a grant.  The auth token then
   carries no allocation, and the resource applies its own default to it
   Section 10.  Reading omission as the full offer would turn a PS's
   non-participation into the maximum grant, the opposite of what
   ignoring an unrecognized claim is meant to do.

Hardt                     Expires 1 April 2027                 [Page 19]
Internet-Draft                AAuth-Budgets               September 2026

10.  Auth Token Extensions

   This document extends the auth token (a JWT with typ: aa-auth+jwt)
   with one optional claim.

   *budget* (OPTIONAL): A budget object Section 4.5.  This is the
   granted budget and is authoritative.

   {
     "iss": "https://ps.example",
     "dwk": "aauth-person.json",
     "aud": "https://inference.example",
     "jti": "at-71b9d0",
     "ps": "https://ps.example",
     "sub": "8f14e45fceea167a5a36dedd4bea2543",
     "cnf": { "jwk": { "kty": "OKP", "crv": "Ed25519",
                       "x": "NzbLsXh8uDCcd...", "alg": "Ed25519" } },
     "tenant": "corp",
     "mission_s256": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
     "scope": "inference.completions",
     "budget": { "amount": 2000000, "unit": "USD", "decimals": 6 },
     "iat": 1754611200,
     "exp": 1754614800
   }

   Issuer rules:

   *  The issuer MUST copy unit and decimals from the resource token's
      budget claim unchanged.
   *  The issuer MUST NOT set amount higher than the resource token's
      budget.amount, or, in four-party access, higher than the budget
      parameter of the PS-to-AS token request Section 9.
   *  An issuer MUST NOT include budget in an auth token when the
      resource token carried no budget claim.  The resource, not the PS
      or AS, denominates.

   Resource rules:

   *  A resource that issued a budget in a resource token and receives
      an auth token without a budget claim MUST treat the request as
      carrying no budget authorization under this extension and apply
      its own default.
   *  A resource MUST enforce against the auth token's unit and
      decimals, not against its own current budget_units metadata.  Auth
      tokens live up to an hour and metadata can change within that
      hour; see Appendix A.3.

Hardt                     Expires 1 April 2027                 [Page 20]
Internet-Draft                AAuth-Budgets               September 2026

11.  AAuth-Budget Response Header

   AAuth-Budget is a response header carrying the remaining balance of
   the granted budget.  It is a Dictionary ([RFC9651], Section 3.2),
   matching AAuth-Requirement.

   AAuth-Budget: cost=221200, remaining=1568800,
       unit="USD", decimals=6

   Members:

   *  *remaining* (REQUIRED): A non-negative Integer, in the granted
      scale, giving what is left of the budget on this auth token, net
      of reservations for requests in flight Section 14.8.  It is a
      floor — committed consumption will not exceed the grant — though
      the figure may lag metering.  Exhaustion is signaled by the
      requirement=auth-token challenge, as a 401 or a 202 Section 13,
      for which the agent stays prepared regardless.
   *  *cost* (OPTIONAL): A non-negative Integer, in the granted scale,
      giving what *this request* cost.  A resource sends it in the
      header when it knows the figure as it writes the response, in a
      trailer when it learns the figure after Section 12, and not at all
      when it will not learn it in time to do either.  The third case is
      bounded by Section 12.1.
   *  *reserved* (OPTIONAL): A non-negative Integer, in the granted
      scale, giving what the resource has held against the grant for
      this request and not yet committed Section 14.8.  Meaningful only
      where cost is not yet known, so in practice it accompanies a
      streamed response.  It is a statement about this request, not a
      running total, and is never revised.  REQUIRED where cost is
      omitted Section 12.1.
   *  *required* (OPTIONAL): A non-negative Integer, in the granted
      scale, giving the maximum cost the resource computed for a request
      it refused under reason=insufficient-budget Section 13.1.  Sent
      only with that refusal, where it is RECOMMENDED.  It is what the
      request needed, not what the resource is asking the PS to grant
      next; see Section 13.2.
   *  *unit* (OPTIONAL): A String naming the unit. *decimals*
      (OPTIONAL): an Integer giving its scale.  Both are informational,
      and they are a pair: a sender MUST include both or neither.  They
      exist for readers that never parse a JWT — proxies, logs,
      dashboards.  Those are the same readers that would misinterpret an
      amount carrying a unit with no scale, by a factor of 10^decimals.

   Recipients MUST ignore members they do not recognize.

Hardt                     Expires 1 April 2027                 [Page 21]
Internet-Draft                AAuth-Budgets               September 2026

   The header carries no granted member, no cumulative consumption
   figure, and no token reference.  The agent holds the auth token it
   signed the request with and reads granted from there; what it needs
   per response is what this call cost and what is left, which is what
   the field carries.  Cumulative consumption is an issuer-facing
   figure, reported in the resource token Section 7.1 and at the usage
   endpoint Section 15; see Appendix A.5 for why it is not also reported
   to the agent.

   The scope of the reported figures is this auth token's budget,
   because the budget expires with the token Section 14.

11.1.  Sending Rules

   A resource that granted a budget SHOULD include AAuth-Budget on every
   response to a request bearing that auth token — success, error, and
   the challenge, 401 or 202 Section 13.3, where it reads remaining=0
   beside the AAuth-Requirement header Section 13.

   This is SHOULD rather than MUST because the failing layer may sit
   below the metering layer: a gateway timeout, a crashed worker, or a
   fault in metering itself produces a response no budget figure can
   ride on.  A resource MUST NOT omit the field for any other reason.
   An agent that misses the field learns the balance from its next
   response, and until then applies Section 12.3.

   HTTP/1.1 401 Unauthorized
   AAuth-Requirement: requirement=auth-token;
       resource-token="eyJ..."; reason=budget-exhausted
   AAuth-Budget: remaining=0, unit="USD", decimals=6

   That the field appears on every response regardless of status is the
   point of putting it in a header.  The agent reads the same field
   whether the body is JSON, a server-sent event stream, a streamed
   completion, or a problem document [RFC9457].

   Intermediaries MUST NOT add, alter, or remove AAuth-Budget.  The
   field reports the state of an authorization the resource issued; an
   intermediary rewriting it is asserting authorization state it does
   not hold.  This is the inverse of the RateLimit rule permitting
   intermediaries to tighten values
   ([I-D.ietf-httpapi-ratelimit-headers]) — see Appendix A.8.

   Recipients MUST ignore AAuth-Budget on a response served from cache
   with a positive current_age ([RFC9111], Section 4.2.3).  This is the
   one RateLimit rule that carries over unchanged.

Hardt                     Expires 1 April 2027                 [Page 22]
Internet-Draft                AAuth-Budgets               September 2026

11.2.  Denomination Conflict

   The auth token's budget claim is authoritative.  A recipient MUST NOT
   act on a header unit or decimals that disagrees with the budget claim
   in the auth token it presented, and SHOULD treat the whole field as
   unreliable for that response.

   Including the pair makes the field self-describing for proxies and
   logs that never parse a JWT, at the cost of duplicating signed
   values; the conflict rule is that cost made explicit.

12.  Streaming

   Response headers are written before the body, and a streamed
   response's actual cost is known only when the stream ends.  The
   resource therefore cannot state cost in the header.  What it can
   state is what it has held: it reserved before serving Section 14.8,
   and remaining is already net of that reservation.

   A resource serving a streamed response SHOULD send reserved in the
   header and cost in a trailer.  A resource that cannot send trailers
   sends reserved alone Section 12.1.

   HTTP/1.1 200 OK
   Content-Type: text/event-stream
   Trailer: AAuth-Budget
   AAuth-Budget: remaining=1568800, reserved=431200,
       unit="USD", decimals=6

      ...stream...

   AAuth-Budget: cost=221200

   The agent computes the balance after the request as remaining +
   reserved - cost.  Here that is 1,778,800: the 431,200 held was not
   all spent, and the unspent 210,000 returns to the grant.

12.1.  When cost Is Omitted

   Not every resource can send a trailer.  Trailers exist only on a
   chunked or HTTP/2-and-later response, and several widely deployed
   server runtimes provide no way to emit one at all.  A resource in
   that position knows the cost of a streamed response only after its
   last opportunity to report it.

   Such a resource omits cost and MUST send reserved in the header.  The
   agent recovers the figure from the following response:

Hardt                     Expires 1 April 2027                 [Page 23]
Internet-Draft                AAuth-Budgets               September 2026

   cost = previous remaining + reserved - current remaining

   The subtraction works because remaining is already net of
   reservations Section 11: the earlier figure is net of the hold, the
   later one reflects the commit and the release of the unspent
   remainder. reserved is the term that connects them, which is why it
   stops being optional here.

   It recovers one request's cost only where requests on that token are
   serial.  An agent with several requests in flight on one token
   recovers the net of everything that settled between the two
   responses, not the cost of any single one, because every concurrent
   request moves the same remaining.  An agent that wants per-request
   figures from a resource that omits cost serializes its requests on
   that token; an agent that only needs the balance does not have to.

   Until that next response arrives the agent applies Section 12.3 and
   treats the request as having cost the full reserved amount.  That is
   the conservative direction, and it is the same rule the agent already
   applies to a response it never received.

   A resource MUST NOT omit both cost and reserved.  That combination
   reports that a metered request happened and gives the agent no figure
   for it, neither exact nor conservative.

12.2.  Trailer Rules

   A resource MAY send AAuth-Budget as a trailer field, subject to three
   rules:

   1.  The response MUST list AAuth-Budget in a Trailer header field
       ([RFC9110], Section 6.6.1).
   2.  A trailer instance MUST NOT restate a member the header instance
       carried.  It carries cost and nothing else.
   3.  A recipient MUST NOT treat the trailer as necessary.  A response
       that never delivers one is complete.

   Rule 2 is what makes the field safe under either way a recipient
   handles trailers.  A recipient that discards trailers keeps the
   header's remaining, which is a floor and therefore correct if
   conservative.  A recipient that merges trailer fields into the header
   set produces a single Dictionary whose keys do not collide, because
   no key appears twice.  Restating a member is the case that would
   break: AAuth-Budget is a Dictionary, duplicate keys resolve last-wins
   ([RFC9651], Section 3.2), and which value won would then depend on
   whether the recipient merged — a difference no sender can observe or
   control.

Hardt                     Expires 1 April 2027                 [Page 24]
Internet-Draft                AAuth-Budgets               September 2026

   Rule 3 follows from trailers being droppable in transit ([RFC9110],
   Section 6.5.2) and from trailers existing only on a chunked or
   HTTP/2-and-later response.  The figure a trailer would have carried
   is also in the next response's remaining, so nothing is lost that is
   not recovered on the following call.

12.3.  Ambiguous Failures

   A request whose response never arrives — a dropped connection, an
   aborted stream — leaves the agent unable to say whether it was
   metered.  No trailer arrives on an aborted stream, and the header
   that would have carried cost is on the response that was lost.

   The agent MUST assume the request cost as much as the resource had
   held for it: reserved where it saw one, and otherwise the request's
   maximum cost as the resource would have bounded it Section 14.8.  It
   carries that assumption until a later response's remaining supersedes
   it, and it SHOULD NOT retry a chargeable request before then.

   Assuming the maximum is the conservative direction: an agent that
   under-assumes plans spending it does not have and discovers the
   shortfall as a 401 Section 13.

   Inference APIs commonly emit final usage in the stream's terminal
   event.  That is application-layer and does not provide the
   application independence this header exists for, so a resource that
   emits it and can also send a trailer SHOULD send both.  What it does
   mean is that the exact number exists when the stream ends, and a
   resource whose runtime offers no trailer has it and no protocol
   carrier for it until the next response Section 12.1.

13.  Budget Exhaustion

   *Auth token expired.* The budget expires with the token.  The base
   protocol has the agent refresh an auth token when fewer than five
   minutes remain and not present it inside that margin
   ([I-D.hardt-oauth-aauth-protocol], Expiry and the Refresh Margin).
   An expired token presented anyway is answered 401 with Signature-
   Error: error=expired_jwt, and the resource issues no resource token.
   Either way the agent re-authorizes with a person token at the
   authorization endpoint ([I-D.hardt-oauth-aauth-protocol], Re-
   authorization).  No consumption record rides on that path, and an
   allocation that expired unreported settles from the usage reading
   Section 14.4.1.

   *Budget exhausted, token still valid.* 401 with AAuth-Requirement:
   requirement=auth-token; resource-token="...".  The base protocol
   already permits a resource to return requirement=auth-token with a

Hardt                     Expires 1 April 2027                 [Page 25]
Internet-Draft                AAuth-Budgets               September 2026

   new resource token to a request that already carries an auth token,
   when the request needs more authorization than the token provides,
   and requires agents to be prepared for this step-up at any time
   ([I-D.hardt-oauth-aauth-protocol], Auth Token Required).  Budget
   exhaustion is that case, and the agent's action is the same as for
   any step-up: take the fresh resource token to its PS, with the
   exhausted auth token as presented_token.  The resource token's
   consumption record Section 7.1 is the exhausted token's spend to
   date.  The auth token issued against it expires no later than the
   exhausted one ([I-D.hardt-oauth-aauth-protocol], Auth Token
   Structure), so a step-up renews the allocation but not the token's
   lifetime.  A full-length token comes from re-authorizing with a fresh
   person token.

   *Request exceeds the remainder.* The budget has remainder, but this
   request's maximum cost exceeds it Section 14.8.  The same 401
   challenge, with reason=insufficient-budget.  The agent has a second
   move here that exhaustion does not offer: lower the request's bound
   to fit the remaining reported beside the challenge, and retry on the
   token it already holds.  The required member Section 13.2 is what
   makes that move a calculation rather than a search.

   A request refused under this section MUST NOT draw down the budget or
   appear in the record and counters.  The resource declined to serve
   it; metering the refusal would make exhaustion self-perpetuating.  A
   refusal therefore carries no cost; required Section 13.2 is the
   figure a refusal reports.

   The fresh resource token SHOULD carry the presented token's
   consumption record Section 7.1, its spend to date — the context for
   deciding whether to authorize more, and the figure that tells the
   issuer how much of the refused allocation was actually consumed.

13.1.  The reason Parameter

   A resource challenging because the budget is exhausted rather than
   because the token expired SHOULD include a reason parameter on the
   requirement member:

   HTTP/1.1 401 Unauthorized
   AAuth-Requirement: requirement=auth-token;
       resource-token="eyJ..."; reason=budget-exhausted
   AAuth-Budget: remaining=0,
       unit="USD", decimals=6

   reason is a Token.  This document defines two values:

   *  *budget-exhausted*: The granted budget is spent.

Hardt                     Expires 1 April 2027                 [Page 26]
Internet-Draft                AAuth-Budgets               September 2026

   *  *insufficient-budget*: The budget has remainder, but this
      request's maximum cost exceeds it Section 14.8.

   For either value, the enclosed resource token MAY carry a budget
   sized for what the resource would need to see granted.  The denial is
   itself the re-authorization offer.

13.2.  Refusing a Request That Does Not Fit

   A resource refusing under insufficient-budget has computed the
   request's maximum cost — Section 14.8 requires it to, before serving
   — and SHOULD report that figure as the required member of AAuth-
   Budget:

   HTTP/1.1 401 Unauthorized
   AAuth-Requirement: requirement=auth-token;
       resource-token="eyJ..."; reason=insufficient-budget
   AAuth-Budget: remaining=150000, required=400000,
       unit="USD", decimals=6

   The agent now knows both halves of the refusal: it has 0.15, and the
   request needed 0.40.  Without required it knows only the first, and
   the move Section 13 offers it — lower the request's bound and retry
   on the token it already holds — becomes a search.  It cannot compute
   the figure itself, because the bound is the resource's own
   calculation against its own pricing, and no part of this
   specification requires a resource to publish what an operation costs.

   required is not the same figure as the budget claim of the enclosed
   resource token, and the two SHOULD differ.  The resource token's
   budget is a re-authorization offer addressed to the PS, and a
   resource sizing it for exactly the refused request hands back a grant
   good for one call. required is a fact about the request that was
   refused, addressed to the agent.  The header carries it because the
   agent is the party that acts on it, and because the retry path it
   enables does not involve the person server at all.

   A resource MAY refuse without required — where the operation has no
   cost bound it is willing to state, or where stating it would disclose
   pricing the resource does not publish.  The agent then falls back to
   remaining alone.

   No new requirement value is minted.  The base protocol says an agent
   that does not recognize a requirement value MUST NOT treat the
   response as satisfiable and surfaces it as an error, while recipients
   MUST ignore unknown _parameters_ on the requirement member
   ([I-D.hardt-oauth-aauth-protocol], Requirement Responses).  A new
   value would hard-fail every budget-unaware agent on a condition that

Hardt                     Expires 1 April 2027                 [Page 27]
Internet-Draft                AAuth-Budgets               September 2026

   plain auth-token resolves correctly.  That asymmetry — unknown values
   fail, unknown parameters are ignored — is why this extension extends
   by parameter.

   An agent that understands the reason values knows what to do beyond
   re-authorizing: for budget-exhausted, request a larger budget and say
   why in the justification it sends to its PS; for insufficient-budget,
   either that, or shrink the request and retry without involving the PS
   at all.  An agent that understands neither ignores the parameter and
   re-authorizes, which is always correct.

13.3.  Deferred Delivery

   A resource MAY deliver either refusal as a 202 deferred response
   rather than a 401, holding the invocation
   ([I-D.hardt-oauth-aauth-protocol], Deferred Delivery).  The AAuth-
   Requirement header is the same, reason included, and so is the
   enclosed resource token with its consumption record Section 7.1.
   What differs is what becomes of the request.  Under the 401 the
   resource holds nothing, and the agent sends the request again.  Under
   the 202 the resource holds the invocation, and the agent does not
   send it again: it obtains an auth token and polls the pending URL,
   and the resource executes the held invocation on the first poll that
   presents a valid auth token.

   HTTP/1.1 202 Accepted
   Location: /pending/f7a3b9c
   Retry-After: 5
   Cache-Control: no-store
   AAuth-Requirement: requirement=auth-token;
       resource-token="eyJ..."; reason=budget-exhausted
   AAuth-Budget: remaining=0, unit="USD", decimals=6
   Content-Type: application/json

   {
     "status": "pending"
   }

   A resource holding an invocation under this section follows four
   rules:

   1.  *Nothing is reserved while it is held.* For the held invocation,
       the resource MUST NOT reserve against or meter to the token
       presented on the original request.  For that token the 202 is a
       refusal like the 401, and any remainder it has stays available to
       the agent's other requests.

Hardt                     Expires 1 April 2027                 [Page 28]
Internet-Draft                AAuth-Budgets               September 2026

   2.  *It meters against the completing token.* The held invocation is
       metered against the auth token presented on the poll that
       completes it.  The resource applies Section 14.8 to that token
       before executing: it reserves the invocation's maximum cost
       against that token's remainder, serves, and commits.
   3.  *A completing token that does not fit does not complete it.* If
       the invocation's maximum cost exceeds the remainder of the token
       presented on the poll, the resource does not execute it.  It
       answers the poll with another 202 carrying requirement=auth-
       token, reason=insufficient-budget, and a fresh resource token
       whose presented_jti names that token, and continues to hold the
       invocation.
   4.  *A replay is not metered again.* A resource answering a repeated
       presentation of the completing token from the stored result, as
       the base protocol requires, MUST NOT meter the invocation a
       second time.  The AAuth-Budget on the replay reports that token's
       current remaining, so that the figure is still a floor, with the
       invocation's cost where the resource has it and no reserved.

   AAuth-Budget on the 202 reports what it would report on the 401: the
   remaining of the token presented on the request, required under
   insufficient-budget Section 13.2, and unit and decimals.  It carries
   no cost and no reserved, because nothing was served or held against
   that grant.  A later 202 answering a poll that bore an auth token
   reports on that token the same way Section 11.1.  The response to the
   completing poll carries AAuth-Budget for the completing token, as any
   response to a request bearing it does.

   Under insufficient-budget, the agent's other move — lower the
   request's bound and retry on the token it already holds Section 13 —
   abandons the pending URL.  The agent sends a new request with the
   smaller bound and does not poll the pending URL again.  The held
   invocation is never executed, and since nothing was reserved for it
   (rule 1), abandoning it costs the grant nothing.  The resource
   discards it when the pending URL's lifetime ends
   ([I-D.hardt-oauth-aauth-protocol], Pending URL Security).

13.4.  Boundaries

   429 Too Many Requests is not used by this document.  The base
   protocol gives it two meanings already — slow_down on a pending URL,
   which asks a polling agent to lengthen its interval, and rate_limited
   at a revocation endpoint, which refuses work a caller has sent too
   much of ([I-D.hardt-oauth-aauth-protocol]).  Neither is a budget
   condition.  A budget refusal is about what the next request would
   cost, not about how often requests arrive, and the agent answers it
   by re-authorizing rather than by waiting.

Hardt                     Expires 1 April 2027                 [Page 29]
Internet-Draft                AAuth-Budgets               September 2026

   402 Payment Required is a different condition: the resource needs
   payment rather than re-authorization from the person.  The base
   protocol already permits AAuth-Requirement on a 402, and this
   document does not change that.

14.  Enforcement

14.1.  The Resource Enforces

   The PS authorizes a number.  The resource counts.  The PS is not in
   the request path and does not meter.

14.2.  Budgets Require Auth-Token Mode

   A budget is carried in the budget claim of an auth token, so a
   resource can enforce one only where it requires auth tokens.  A
   resource that declares access_mode: person-token and serves requests
   on the person's identity alone ([I-D.hardt-oauth-aauth-protocol],
   Person Identity Access) has no auth token to read a budget from, and
   neither does a resource operating in agent-token or session-token
   mode.

   A metered resource therefore requires an auth token on the endpoints
   it meters (access_mode: auth-token).  It MAY continue to serve
   unmetered endpoints on a person token, since a resource MAY apply
   different modes to different endpoints
   ([I-D.hardt-oauth-aauth-protocol], Resource Access Modes).  A
   resource MUST NOT rely on this extension for an endpoint it serves
   without an auth token.

   Where the resource holds the authorization state itself rather than
   reading it from a signed claim, there is nothing for the person
   server to have bounded.

14.3.  Token Scope

   A budget is scoped to the auth token that carries it and expires with
   it.  There is no persistent grant identifier and no requirement that
   the PS carry a budget across re-issuance.  This is the mechanism, not
   a gap: re-issuance is where the PS re-decides Section 8.1, and a
   budget that survived it would be a standing grant the PS no longer
   sizes.

   The budget is revoked with the token.  Revoking an auth token at its
   resource ends its budget along with the rest of its authorization.
   In three-party access the PS revokes it there; in four-party access
   the PS revokes the person token at the AS, and the AS revokes the
   auth tokens it issued against it ([I-D.hardt-oauth-aauth-protocol],

Hardt                     Expires 1 April 2027                 [Page 30]
Internet-Draft                AAuth-Budgets               September 2026

   Token Revocation).  A resource without a revocation endpoint honors a
   revoked token until its exp.  Consumption already committed is
   unaffected — a budget is a ceiling on spending, not a claim on what
   was spent — and a request already in flight completes, because
   revocation stops a token being used again rather than interrupting a
   call.  This document adds nothing to that mechanism; it is named here
   because a person hitting stop expects the money to stop, and expiry
   alone bounds that at an hour.  What a revocation means for the
   issuer's own accounting — when the allocation it reserved can be
   released — is Section 14.4.1.

   Two conditions return the agent to the PS, and either is sufficient.
   The auth token nears its exp: the base protocol caps an auth token at
   one hour and has the agent refresh it when fewer than five minutes
   remain ([I-D.hardt-oauth-aauth-protocol], Expiry and the Refresh
   Margin).  Or its budget is exhausted Section 13, which happens after
   however much work it took to spend.  Expiry is proportional to time
   and exhaustion is proportional to spend, so the supervision interval
   tracks whichever is moving faster: a mission running cheaply reports
   on the hour, one running expensively reports in minutes, and no party
   configures the difference.

14.4.  Unreported Allocations

   An allocation can expire before its issuer sees a figure for it.  A
   consumption record comes back only on a challenge to a request that
   presented the token Section 7.1.  A token the agent retires by
   refreshing it, as the base protocol has it do inside the refresh
   margin Section 13, is never named in one, and neither is a token held
   by an agent that has crashed or been abandoned.  Until the next usage
   query, the issuer knows a grant was live and nothing about what it
   consumed — the true figure is anywhere from zero to the full amount.

   Until a figure arrives, the issuer MUST account for the allocation as
   fully consumed.  The error modes are not symmetric: an issuer that
   assumes less than was spent sizes the next allocation against
   headroom that may not exist and can overrun the ceiling it holds,
   while one that assumes the maximum is at worst temporarily
   conservative, which the next figure corrects.  This is Section 12.3
   applied to the other end of the grant — the party missing a figure
   assumes the maximum until a real one supersedes it.

Hardt                     Expires 1 April 2027                 [Page 31]
Internet-Draft                AAuth-Budgets               September 2026

   Reconciliation is idempotent where the channel names the token.  A
   consumption record is a {jti, consumed} pair whose consumed is that
   token's total as of the resource token that carried it Section 7.1,
   so a record arriving late — or arriving again — replaces the
   assumption for that token rather than adding to it.  Usage counters
   and per-key figures Section 15 name no jti; they are aggregates the
   issuer reconciles against its own ledger of what it assumed.

   The rule falls on every party that sized the allocation against a
   ceiling it holds.  In three-party access that is the PS Section 8.1.
   In four-party access it is also the AS, which issues against the
   ceiling the PS stated Section 9 and may apply credit or risk limits
   of its own Section 4.2.  Both are entitled callers of the usage
   endpoint Section 15.3.

14.4.1.  Settlement

   The issuer set every allocation's exp, so it knows when the
   assumption can be settled.

   A consumption record settles nothing.  It is a snapshot Section 7.1:
   the token stays valid, the agent may spend more on it, and under
   insufficient-budget may retry a smaller request on it Section 13.
   What the record gives the issuer is the spend so far, for the re-
   authorization decision it is making at that moment.

   A usage reading settles every allocation, in aggregate.  The issuer
   takes the person's figure from the usage endpoint Section 15,
   complete through as_of, and then holds

 free = ceiling − metered − Σ amount of every allocation not yet settled

   where metered is the person's counter — all_time for a standing
   ceiling, the matching calendar counter for a calendar one — and an
   allocation is settled by the reading once its exp is at or before
   as_of.  A settled allocation needs no figure of its own: whatever it
   consumed is inside metered, and it is no longer reserved.  The only
   over-count in free is consumption under still-live tokens, present in
   both terms; it vanishes as each expires and the next reading covers
   it.  The per-token figure in a consumption record refines the
   issuer's picture of a live allocation between readings; it does not
   settle it.

   A revoked token is not an early exp.  Revocation stops the spending;
   it does not by itself release the reservation, because the figure for
   what was spent still arrives with the next reading.  What it does is
   move the moment after which no more can be spent, and the issuer
   learns whether that moment exists from the revocation's own answer: a

Hardt                     Expires 1 April 2027                 [Page 32]
Internet-Draft                AAuth-Budgets               September 2026

   recipient answers 200 once its cascade is terminal, directly or at
   the pending URL of a 202, and an AS reports each resource's outcome
   in downstream ([I-D.hardt-oauth-aauth-protocol], Revocation
   Response).  Three outcomes, three answers:

   *  *Recorded at the resource.* Nothing further can be spent on that
      token.  The allocation is settled by the first usage reading whose
      as_of is at or after the revocation was recorded, rather than the
      first one at or after exp — the same rule as any other settlement,
      since whatever was spent is inside metered by then.
   *  *revocation_unsupported.* The resource honors the token until exp.
      The allocation stays reserved until exp and settles as it would
      have without the revocation.
   *  *revocation_unavailable.* The issuer cannot tell which of the two
      it has, so it holds the allocation reserved until exp and MAY
      revoke again later.

   An issuer that treated every revocation as an immediate settlement
   would release headroom that a resource with no revocation endpoint is
   still spending against, which is Section 14.4 in reverse and has the
   error mode that section rules out.

   An issuer whose ceiling is per calendar period SHOULD set each
   allocation's exp no later than the period boundary.  No allocation
   then straddles two periods, every allocation of a period has expired
   when the period ends, and the period settles without a query.  The
   cost is that a token issued near the boundary is short.  The calendar
   counters have no sub-day period Section 15.2.1; an issuer with an
   hourly ceiling and clipped allocations never needs one, and an issuer
   with a trailing window settles from differences of successive
   all_time readings.

14.5.  Aggregation

   Two things are counted, against different keys, and they are not the
   same requirement.

   *The cap the resource enforces is per auth token.* It is the budget
   claim of the token presented, and Section 14.8 states the invariant:
   committed consumption plus outstanding reservations against _that
   token_ MUST NOT exceed _its_ granted amount.  A resource needs no
   cross-token arithmetic to enforce a budget.

   *The ledger the resource keeps is per person.* The resource MUST
   aggregate consumption against the key (ps, sub, aud) of the auth
   token, which is what the consumption record Section 7.1 and the usage
   counters Section 15 report. (ps, sub) identifies the person: sub is
   minted by the person server named in ps, and values from different

Hardt                     Expires 1 April 2027                 [Page 33]
Internet-Draft                AAuth-Budgets               September 2026

   person servers are different people. aud is the resource itself.  In
   three-party access ps equals iss.  In four-party access iss is the
   AS, which did not mint sub, so a key on iss would let two person
   servers behind one AS collide; ps is the person server the AS
   verified sent the token request ([I-D.hardt-oauth-aauth-protocol],
   PS-to-AS Token Request).  This document introduces no new identifier.

   The ledger is not a second ceiling.  A resource MUST NOT refuse a
   request that fits its token's budget because a per-person total has
   reached some figure the resource inferred; no party told it such a
   figure, and the budgets it was handed are what it was authorized to
   honor.  Holding a person's spending across concurrent tokens within
   bounds is the PS's job Section 14.7, because the PS is the party that
   issues them and the only one that knows the ceiling Section 8.1.

   A per-agent ceiling is not a resource-side key either.  A person
   server that wants one agent capped at less than another issues it a
   smaller allocation Section 8.1; the enforcement is the token's own
   budget, and no resource-side dimension is involved.  What a resource
   cannot supply from allocations alone is how much each agent actually
   spent, since an allocation is a ceiling rather than a figure — that
   is what the per-key query at the usage endpoint serves
   Section 15.2.2.

   The ledger's key is the person, not the agent and not the mission.
   An auth token names no agent, and a person's spending at a resource
   is theirs whichever agent incurred it; a per-agent key would also
   reset every time the person changed agents. mission_s256 is optional
   — a token may carry one or not — so a mission-keyed ledger has no
   bucket for a mission-less token, and Section 18 requires mission-less
   tokens for standing inference budgets.  The person is the only key
   present on every auth token.  Missions are an attribution dimension
   over that ledger Section 14.11, not the ledger itself.

14.6.  The Billing Account

   A resource that meters usually charges someone for it, and the party
   it charges is an account in its own systems.  Nothing in a budget
   names that account.  The aggregation key above is (ps, sub, aud), and
   sub is directed per person server — it identifies a person at one PS
   and carries no meaning at the resource beyond what the resource has
   learned about it.

   For most resources that is sufficient and no mechanism is needed.
   The base protocol keys a person's relationship with a resource on the
   person server and sub precisely so it survives a change of agent, and
   a resource holding one account per person looks the account up from
   (ps, sub). tenant names the person's organization and is not part of

Hardt                     Expires 1 April 2027                 [Page 34]
Internet-Draft                AAuth-Budgets               September 2026

   the identifier ([I-D.hardt-oauth-aauth-protocol], Organization
   Identification).  Consumption then meters against the account the
   resource already had.

   Beyond that, two different questions arise, and they compose rather
   than substitute.  The first is asked once per person; the second on
   every authorization.

   *Which person is this?* The first budgeted request carrying a sub the
   resource has not seen is a question for the person, not the agent,
   and both access modes answer it with an interaction the person
   completes at the party that holds the account.

   In three-party access the resource asks.  It puts an interaction
   claim in the resource token, and the person server chains the person
   through the resource's own flow — signing in, creating an account,
   connecting a payment method — before completing its own consent
   ([I-D.hardt-oauth-aauth-protocol], Resource-Initiated Interaction).
   Because the resource issues the resource token, it decides when to
   ask again: once per person, or once per mission, since it sees
   mission_s256 at that moment.

   In four-party access the AS asks, returning 202 with
   requirement=interaction to the person server's token request
   ([I-D.hardt-oauth-aauth-protocol], PS-AS Trust Establishment).  This
   is the same one-time binding the AS already performs to establish
   trust with a person server, answering a second question at the moment
   it is already asking the person who they are.

   Because sub is directed per person server, a person reaching the same
   resource through two person servers presents two identifiers.  The
   binding interaction is what attaches both to one account, and a
   resource that skips it sees two people and bills two ledgers.

   *Which of their accounts?* Binding establishes who the person is.  It
   does not say which of several accounts an authorization is for, and a
   person who holds more than one at the resource has to say.  Account
   Binding ([I-D.hardt-oauth-aauth-protocol], Account Binding) carries
   the answer: an OPTIONAL account parameter on the authorization
   endpoint request, named from the resource's own namespace, echoed as
   the account claim of the resource token and copied into the auth
   token.

   This applies in both access modes; how account reaches the issuer,
   and what each party does with it, is specified there and not restated
   here.  In four-party access it reaches the AS in the resource token,
   so the binding tells the AS who the person is and account tells it
   which of their accounts this authorization bills.

Hardt                     Expires 1 April 2027                 [Page 35]
Internet-Draft                AAuth-Budgets               September 2026

   A metered resource should ask for account where a person may hold
   more than one, because a budget enforced against the wrong account is
   charged to the wrong payer.  A resource holding one balance per
   person needs none of it: binding is the whole mechanism, and account
   never appears in its tokens.

   None of this is specific to budgets, and this document defines no new
   mechanism for it.  It is stated here because a metered resource meets
   these cases on its first request and the rest of this document is
   silent on them.

14.7.  Concurrency

   An agent may hold several concurrent auth tokens at the same resource
   — the mission_s256 claim means concurrent missions produce concurrent
   tokens, each with its own budget, for up to an hour.  Handling this
   is mandatory, not optional:

   *  A resource MUST apply the reserve-commit-release invariant of
      Section 14.8 atomically per auth token, so that concurrent
      requests presenting the same token cannot together exceed its
      budget.
   *  A resource MUST post consumption to the (ps, sub, aud) ledger
      Section 14.5 atomically, so that concurrent requests across
      different tokens do not lose or double-count against the record
      and counters.
   *  A PS SHOULD size per-token budgets so that their sum stays within
      whatever standing ceiling it holds for the person at that
      resource.  This is the only place the cross-token total is
      enforced; Section 14.4.1 is how an issuer keeps that sum exact as
      allocations expire.

   The bound on over-issuance is the auth token lifetime multiplied by
   the number of concurrent tokens.  A PS that issues _n_ concurrent
   tokens of _X_ each has authorized up to _nX_ for as long as an hour,
   regardless of any standing figure it intended to hold.

14.8.  The Budget Is a Hard Cap

   A resource MUST NOT let metered consumption exceed the granted
   amount.  A budget is an authorization, and an authorization the
   enforcer may exceed is a hint.

   Output is metered after it is generated, so honoring the cap means
   bounding the request before serving it.  Before serving a chargeable
   request, the resource determines the request's maximum cost — from a
   bound the request declares, such as a maximum output length, or from
   a documented default — and refuses the request with

Hardt                     Expires 1 April 2027                 [Page 36]
Internet-Draft                AAuth-Budgets               September 2026

   reason=insufficient-budget Section 13.1 when that maximum exceeds the
   remainder.  An operation with no finite cost bound MUST be given one,
   be truncated when the remainder is consumed, or be refused.

   The implementation shape is reserve-commit-release: atomically
   reserve the maximum against the grant, serve, commit the actual
   charge, release the difference.  The normative requirement is the
   invariant, not the mechanism: committed consumption plus outstanding
   reservations MUST NOT exceed the granted amount at any moment,
   including under concurrent requests Section 14.7.

   The honest cost of the invariant lands near exhaustion: a request
   bounded at more than the remainder is refused even when its actual
   cost would have fit.  The mitigation is the agent's — read remaining
   from the refusal's AAuth-Budget header and retry with a bound that
   fits — and that is the correct pressure, since it rewards realistic
   bounds.

14.9.  Failed Calls

   Whether a request that fails — a 5xx after input tokens were consumed
   — draws down the budget is the resource's metering policy.  Whatever
   it meters, the record and counters MUST reflect, or the person's
   numbers will not reconcile with the bill.

14.10.  Delegation

   A budget is not delegable.  Each auth token carries its own budget,
   and consumption through a delegated token draws down that token's
   budget alone.  Both delegation paths — call chaining and sub-agent
   authorization ([I-D.hardt-oauth-aauth-protocol], Agent Delegation) —
   obtain each downstream auth token through the person server, so the
   PS sizes every grant in a chain, and Section 14.7 already governs
   their sum.  No sub-budget or draw-down-from-parent mechanism is
   defined.

14.11.  Mission Attribution

   Consumption is attributed to a mission using the mission_s256 claim
   of the auth token, beside its ps claim: a mission is identified by
   the PS that approved it together with mission_s256
   ([I-D.hardt-oauth-aauth-protocol], Mission Identifier). mission_s256
   is PS-asserted throughout: the person server validated the mission
   when it issued the person token, the resource copied it into the
   resource token, and the person server, and in four-party access the
   AS, verified that it matches the presented token's
   ([I-D.hardt-oauth-aauth-protocol], Resource Token Verification).  No
   party in the chain takes the mission on the agent's word, which is

Hardt                     Expires 1 April 2027                 [Page 37]
Internet-Draft                AAuth-Budgets               September 2026

   what makes a resource's per-mission figures worth reading.

15.  Usage Counters

   The consumption record reaches the issuer only when the agent brings
   a resource token back.  The agent is the party being budgeted and
   also the courier of the evidence: it cannot falsify the record, but
   between re-authorizations it does not appear, and the issuer is blind
   for up to an hour per token.  The usage_endpoint Section 5 removes
   the agent from that loop: the issuer — the PS, or in four-party
   access the AS — queries the resource directly, on a channel the agent
   is never on.

   The endpoint serves *usage counters*: pre-summed consumption totals
   the PS reads, acts on, and displays.  It does not compute, convert,
   or round.  The resource keeps a handful of running integers,
   incremented at metering time; serving the endpoint requires no per-
   record history.

15.1.  Usage Request

   The caller — a person server, or in four-party access an access
   server — MUST make a signed POST to the usage_endpoint, signing as a
   server in its own right: an HTTP Sig under the jwks_uri scheme, with
   id its issuer and dwk its metadata document
   ([I-D.hardt-oauth-aauth-protocol], Keying Material), and the
   signature additionally covering content-type and content-digest, as
   on a request with a body to a PS or AS
   ([I-D.hardt-oauth-aauth-protocol], Covered Components).

   The body carries at most one *scope key*, naming a claim value the
   resource has seen in auth tokens:

   *  *sub*: A directed person identifier.  Scope: the person at this
      resource, across all their agents and missions.
   *  *tenant*: A tenant identifier.  Scope: the organization, across
      its people.
   *  *mission_s256*: A mission identifier.  Scope: one mission.

   and one OPTIONAL member:

   *  *jkts*: An array of JWK Thumbprints ([RFC7638]), each naming a
      signing key the resource has seen present an auth token.  Asks for
      what each of those keys consumed Section 15.2.2.

   An access server names the person server whose values it is asking
   about:

Hardt                     Expires 1 April 2027                 [Page 38]
Internet-Draft                AAuth-Budgets               September 2026

   *  *ps*: The person server whose namespace the scope key belongs to.
      REQUIRED when the caller is an access server and the request
      carries a scope key, since the tokens an AS issues carry values
      from every person server that federates with it.  A person server
      omits it; it is the caller.

   A request MUST carry a scope key or jkts, and MAY carry both.  At
   most one scope key may appear.  A request with more than one scope
   key, or with neither a scope key nor jkts, is an error Section 15.3.

   POST /usage HTTP/1.1
   Host: inference.example
   Content-Type: application/json
   Content-Digest: sha-256=:...:
   Signature-Input: sig=("@method" "@authority" "@path"
       "content-type" "content-digest"
       "signature-key");created=1754620000
   Signature: sig=:...signature bytes...:
   Signature-Key: sig=jwks_uri;id="https://ps.example";
       dwk="aauth-person.json";kid="key-1"

   {
     "sub": "8f14e45fceea167a5a36dedd4bea2543",
     "jkts": ["NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
              "0ZcOCORZNYy-DWpqq30BbmLzO1Yw3ZQhIgnHZQKxNVE"]
   }

15.2.  Usage Response

   {
     "as_of": 1754619970,
     "aud": "https://ps.example",
     "unit": "USD",
     "decimals": 6,
     "sub": "8f14e45fceea167a5a36dedd4bea2543",
     "usage": {
       "day": 1243180,
       "week": 3118400,
       "month": 8432650,
       "year": 39847220,
       "all_time": 61438050
     },
     "jkts": {
       "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs": 38215600,
       "0ZcOCORZNYy-DWpqq30BbmLzO1Yw3ZQhIgnHZQKxNVE": 23222450
     }
   }

Hardt                     Expires 1 April 2027                 [Page 39]
Internet-Draft                AAuth-Budgets               September 2026

   *  *as_of* (REQUIRED): The time through which the figures are
      complete, in seconds since the Unix epoch.  Metering aggregation
      MAY lag serving; as_of is what keeps a lagging figure honest.
   *  *aud* (REQUIRED): The caller the response was produced for — a
      person server, identified as in the ps claim of a resource token,
      or an access server, identified as in the iss claim of an auth
      token.  It is what stops a signed response being presented to a
      third party as a statement about them Section 15.2.4.
   *  *unit* (REQUIRED) and *decimals* (REQUIRED): The unit every figure
      in the response is denominated in, and its scale, as in the budget
      object Section 4.5.
   *  The *scope key* from the request, echoed unchanged — sub, tenant,
      or mission_s256 — present only when the request carried one.
   *  *usage* (REQUIRED when the request carried a scope key): Calendar
      counters for that scope.
   *  *jkts* (REQUIRED when the request carried jkts): An object mapping
      each thumbprint to what that key consumed Section 15.2.2.

15.2.1.  Calendar Counters

   The members of usage are day, week, month, year, and all_time,
   following the interval enumeration of Stripe Issuing [Stripe.Issuing]
   Appendix B.4.  Each is a non-negative integer giving consumption
   within the current period:

   *  *day*: since 00:00 UTC today.
   *  *week*: since Monday 00:00 UTC of the current ISO 8601 week.
   *  *month*, *year*: since the start of the current UTC calendar month
      or year.
   *  *all_time* (REQUIRED): everything the resource has metered against
      budgets under this key.

   All period boundaries are UTC.  This is a definition, not a
   deployment choice: no timezone appears in metadata or in the
   response, and every party computes the same figure.  The cost is that
   "today" resets mid-afternoon in Auckland, which Stripe Issuing
   accepts for the same reason this document does — the counter is
   decision context, not a bill.

   The calendar counters other than all_time are OPTIONAL; a resource
   omits periods it does not track.  For a mission_s256 query, all_time
   is the mission total — the figure a PS wants when deciding whether to
   fund a mission's continuation — and a resource MAY serve it alone.

   Counters are subject to the 15-digit bound of Section 4.4.  A
   resource whose cumulative figure would exceed it omits that counter
   rather than reporting an inexact number.

Hardt                     Expires 1 April 2027                 [Page 40]
Internet-Draft                AAuth-Budgets               September 2026

   all_time reaches as far back as the resource retains.  This document
   sets no retention requirement for scope keys; the person's bill is
   the durable record.

15.2.2.  Per-Key Figures

   Each member of jkts is a thumbprint mapped to a single non-negative
   integer: everything the resource has metered against budgets on auth
   tokens presented by that key.

   There are no calendar periods here.  A key's consumption is already
   bounded by the tokens issued to it, and an auth token lives at most
   an hour; a key that has stopped presenting tokens has a figure that
   no longer moves.  Periods answer "how much this month", which is a
   question about a person, not about a key.

   A resource SHOULD retain a key's figure for at least 24 hours after
   that key's last metered request, and MAY retain it longer.  The bound
   is idle time rather than age, so a key in continuous use is never
   pruned.  Beyond that window the PS is the party that accumulates: it
   polls, it knows which keys belonged to which agent across rotations,
   and it holds the history.  The resource keeps a short tail.

   A resource MUST omit a thumbprint from jkts rather than report zero
   for it when it holds no figure — because the key is unrecognized, or
   because its figure has been pruned.  Absence means the resource
   cannot answer; a present zero means the key consumed nothing.  This
   differs from the treatment of an unrecognized scope key Section 15.3,
   and the reason is that there is nothing to conceal: the PS issued or
   relayed every auth token, so it already knows the key exists, and a
   zero that means "pruned" would be a wrong answer to an allocation
   decision rather than a withheld one.

15.2.3.  One Unit Per Response

   Every figure in a response is in one unit, named once at the top
   level, and it is the unit the resource meters in.  There is no
   request parameter selecting it.

   The alternative is a per-unit array at every level, which costs every
   response the shape needed by deployments that meter in one unit —
   which is nearly all of them, since a resource that meters several
   quantities collapses them to one billing unit before denominating a
   budget Section 1.1.  A resource may still declare several units in
   budget_units Section 5, because that is what an agent may ask a
   budget to be denominated in; what this endpoint reports is what the
   resource actually metered, and the response says which unit that was.

Hardt                     Expires 1 April 2027                 [Page 41]
Internet-Draft                AAuth-Budgets               September 2026

15.2.4.  The Signed Response

   Signing the usage response is RECOMMENDED.  A resource that signs
   uses an HTTP Sig with a key from the jwks_uri in its resource
   metadata Section 5 — the same key material the PS already fetched to
   verify resource tokens.  The signature MUST cover @status, content-
   type, and content-digest, and MUST be bound to the request by
   covering the request's @authority and @path with the req parameter
   ([RFC9421]).

   HTTP/1.1 200 OK
   Content-Type: application/json
   Content-Digest: sha-256=:...:
   Signature-Input: sig=("@status" "content-type"
       "content-digest" "@authority";req "@path";req);
       created=1754620001
   Signature: sig=:...signature bytes...:
   Signature-Key: sig=jwks_uri;id="https://inference.example";
       dwk="aauth-resource.json";kid="r1"

   The endpoint reports what a person owes for, so an unsigned figure is
   one the party that produced it can later disown.  Signing makes the
   resource committed to what it reported: it cannot tell the person
   server one number and the biller another.  It does not make the meter
   honest — the resource is the counterparty as well as the signer — and
   Section 19.4 covers what remains.

   It also closes an asymmetry.  The consumption record Section 7.1 is
   already resource-signed, because it rides inside a resource token.
   The usage endpoint is the only issuer-facing consumption channel that
   is not.

   It is RECOMMENDED rather than REQUIRED because the figures are
   decision context rather than authorization, and because this would be
   the first response-side signature in the AAuth family — the signature
   profile is request-side throughout Section 19.1.  A person server
   receiving an unsigned response is not in a position to do anything
   but read it: refusing it leaves the PS with no figures rather than
   unattributable ones, which is the worse of the two.  What signing
   changes is whether the resource can later disown what it said, and
   that is worth having wherever both ends will implement it.

   aud is what keeps the signed response non-transferable.  Without it a
   resource-signed statement of consumption could be handed to a third
   party as though it described them, and the figures carry no other
   indication of who asked.

Hardt                     Expires 1 April 2027                 [Page 42]
Internet-Draft                AAuth-Budgets               September 2026

15.3.  Authorization and Errors

   The id parameter of the Signature-Key header is the caller's server
   identifier, and its dwk names the metadata document that says which
   role is calling — aauth-person.json for a person server, aauth-
   access.json for an access server ([I-D.hardt-oauth-aauth-protocol],
   Keying Material).  That identifier is what the response carries as
   aud Section 15.2.  A caller is a person server or an access server.
   The resource MUST only answer for values that have appeared in auth
   tokens it accepted whose iss or ps claim names the caller: for a PS,
   the tokens it issued in three-party access and the tokens carrying it
   as ps in four-party access; for an AS, the tokens it issued, and for
   a scope key only those whose ps is the request's ps.  This applies to
   thumbprints in jkts as much as to scope keys. sub is directed per PS,
   so one person server cannot even name another's subjects; tenant,
   mission_s256, and thumbprints are not directed, and this check is
   what stops a third party from querying them.

   An AS is entitled because it sizes allocations against a ceiling of
   its own Section 4.2 and is bound by Section 14.4 for them.  An AS
   operated by the resource may take the same figures from the resource
   directly; the endpoint is for the AS that is not.

   A query for a scope key the resource does not recognize returns 200
   with usage omitted; "never seen" and "nothing consumed" are
   deliberately indistinguishable, so that a query cannot be used to
   discover whether a person holds an account.  Unrecognized thumbprints
   are handled differently and for a stated reason Section 15.2.2.

   invalid_request, using the error response format of
   ([I-D.hardt-oauth-aauth-protocol]), is returned for a body carrying
   more than one scope key, carrying neither a scope key nor jkts,
   carrying a scope key from an access server without ps, or carrying a
   malformed value.

   A resource MAY rate-limit the endpoint, using the RateLimit fields
   ([I-D.ietf-httpapi-ratelimit-headers]) as on any endpoint.  A PS
   SHOULD poll no faster than its decisions require.

15.4.  Division of Labor

   The two issuer-facing channels answer different questions at
   different moments.  The consumption record Section 7.1 serves the re-
   authorization decision: it arrives in-band, resource-signed, at no
   round-trip cost, exactly when the issuer is deciding.  The usage
   counters serve everything else: supervision between re-
   authorizations, settlement of allocations that expired unreported
   Section 14.4.1, mission totals, tenant-level exposure, how a person's

Hardt                     Expires 1 April 2027                 [Page 43]
Internet-Draft                AAuth-Budgets               September 2026

   spending divides among their agents Section 15.2.2, and the person's
   dashboard.  A metered resource SHOULD implement both; the narrowing
   chain Section 4.2 functions with the record alone.  The agent's own
   view is neither of these: it is the AAuth-Budget header Section 11,
   scoped to the token it holds and to the request it just made.

16.  Capability Negotiation

   This document adds budget to the AAuth Capability Value Registry.  An
   agent that understands budget semantics — the budget claim, the
   AAuth-Budget header, and the reason values Section 13.1 — SHOULD
   include budget in its AAuth-Capabilities request header, and in the
   capabilities parameter of its person token and auth token requests
   ([I-D.hardt-oauth-aauth-protocol], AAuth-Capabilities Request
   Header).  The person token request is where a budget-aware agent
   first reaches its PS about a resource, so it is where the declaration
   first matters:

   AAuth-Capabilities: interaction, clarification, budget

   This tells the resource up front whether the agent will read what it
   sends, rather than leaving it to rely on ignore-unknown-parameter
   behavior.  It is the same negotiation interaction performs for
   requirement=interaction.  Recipients MUST ignore unrecognized
   capability values.

   A resource MUST NOT withhold AAuth-Budget from an agent that did not
   declare the capability.  The header is safe to ignore.

17.  Errors

   Narrowing is never an error.  A resource that will grant less than
   the agent asked for issues a smaller budget; a PS or AS that will
   allow less issues a smaller amount.  No error is returned in either
   case.

   Errors are reserved for statements that cannot be reconciled:

Hardt                     Expires 1 April 2027                 [Page 44]
Internet-Draft                AAuth-Budgets               September 2026

   +=================+========+===============+========================+
   | Error           | Status | Endpoint      | Meaning                |
   +=================+========+===============+========================+
   | invalid_budget  | 400    | Authorization | The budget object is   |
   |                 |        | endpoint      | malformed, or names    |
   |                 |        |               | a unit the resource    |
   |                 |        |               | has not declared in    |
   |                 |        |               | budget_units           |
   +-----------------+--------+---------------+------------------------+
   | invalid_budget  | 400    | PS and AS     | The resource token's   |
   |                 |        | auth token    | budget.decimals        |
   |                 |        | endpoints     | disagrees with the     |
   |                 |        |               | value declared for     |
   |                 |        |               | that unit in the       |
   |                 |        |               | resource's             |
   |                 |        |               | budget_units           |
   |                 |        |               | metadata, or the       |
   |                 |        |               | object is otherwise    |
   |                 |        |               | malformed              |
   +-----------------+--------+---------------+------------------------+
   | invalid_request | 400    | Usage         | More than one scope    |
   |                 |        | endpoint      | key, neither a scope   |
   |                 |        |               | key nor jkts, or a     |
   |                 |        |               | malformed value        |
   |                 |        |               | Section 15.3           |
   +-----------------+--------+---------------+------------------------+

                                  Table 3

   Error responses use the error response format defined in AAuth
   Protocol ([I-D.hardt-oauth-aauth-protocol]).

   invalid_budget at the authorization endpoint parallels invalid_scope:
   the agent named something the resource does not recognize.

   A decimals mismatch at the PS or AS MUST be a hard reject rather than
   a narrowing.  A mismatch means one of the two figures is stale, and
   guessing which one is worse than failing — the error modes are a
   budget interpreted a thousandfold too large or too small.

   A PS or AS that has no cached budget_units for the resource and
   cannot fetch the metadata MAY proceed on the resource token's
   decimals, which is signed by the resource.  The cross-check is a
   defense against staleness, not against the resource.

Hardt                     Expires 1 April 2027                 [Page 45]
Internet-Draft                AAuth-Budgets               September 2026

17.1.  Declining with Guidance

   A PS granting less than the resource offered needs no mechanism: the
   amount in the issued claim says it.  A PS or AS that declines a token
   request outright on budget grounds MAY include *suggested_budget* in
   its error response body: a budget object Section 4.5 whose unit and
   decimals are copied from the resource token, and whose amount is what
   the issuer would currently accept.  It is guidance, not a grant — the
   agent's move is a fresh resource token at that figure Section 6 and a
   new token request, with the usual consent and policy evaluation.

   In four-party access an AS's suggested_budget reaches the PS, not the
   agent.  The PS relays it in the problem+json body with which it
   relays the AS's error to the agent ([I-D.hardt-oauth-aauth-protocol],
   Auth Token Delivery), with unit and decimals unchanged and amount
   lowered to what the PS would itself currently accept for the person
   where that is lower.  That figure never exceeds the ceiling the PS
   holds Section 8.1, and the PS states it as an amount it would accept,
   not as the ceiling, which the agent does not learn Appendix A.6.

18.  Standing Authorization for Metered Inference

   Metered inference is the initiating use case for this extension and
   has a property that distinguishes it from most resource access: the
   agent needs it before it can do anything else, including decide what
   else it needs.

   *Inference authorization is agent-scoped and standing.* It is
   established at first PS contact, not per mission.  The reason is a
   termination argument rather than a preference: a per-mission
   inference budget requires the agent to run inference in order to
   evaluate whether it needs more inference budget, and that evaluation
   itself consumes inference.  A standing allocation terminates; a per-
   mission one does not.

   *Mission-less auth tokens are already legal.* mission_s256 is
   optional in a person token and therefore in everything derived from
   it, and the PS permission and interaction endpoints work with or
   without a mission.  No new token type is needed for this pattern.

   *Do not model the harness as a mission.* A mission description is
   defined as human intent expressed in Markdown.  Synthesizing an
   "operating mission" or "harness mission" to hold the inference budget
   would put a fabricated description into the content-addressed blob
   that every token carrying mission_s256 is bound to, and mission
   revocation — a kill switch for one piece of work — would then also be
   the kill switch for the agent's ability to think.  Those are two
   distinct controls and conflating them is a mistake.

Hardt                     Expires 1 April 2027                 [Page 46]
Internet-Draft                AAuth-Budgets               September 2026

   *Pre-mission inference runs on a mission-less auth token* and lands
   in the person's usage with no mission attribution.  Mission
   boundaries become natural auth token re-issuance points, which costs
   nothing: the agent is already talking to its PS to create the
   mission.

   *AP-bundled inference is out of scope.* Where the agent provider pays
   for the agent's inference, the agent token is the credential, the
   person server never appears, and nothing in this document applies.
   This is the common deployment today, and readers will otherwise
   assume the extension covers it.  The case that does engage this
   extension is a harness written by the agent provider spending against
   the _person's_ inference account — which is where a ceiling matters
   most, because the agent provider's software is deciding how much of
   the person's money to consume.

   *A TPX provider adds agent support without touching its meter.* A TPX
   [TPX] provider already prices per token, reports cost in each
   response's usage, and enforces a person-granted budget as a hard cap
   — for human-driven apps holding OAuth grants.  Serving agents means
   accepting AAuth auth tokens carrying budget beside those grants: two
   authorization envelopes over one metering core.  Deployed this way,
   this extension is the AAuth binding of TPX.

   Neither envelope displaces the other.  A person driving an app and an
   agent acting for that person are different situations, and a provider
   serving both has one meter under two front doors Section 22.

19.  Security Considerations

19.1.  The Header Is Unsigned

   AAuth-Budget is not signed, so an intermediary can lie about the
   balance.  The failure modes are bounded.  Understating remaining
   makes the agent re-authorize earlier than it needed to.  Overstating
   it makes the agent hit an unexpected 401.  Neither causes overspend,
   because enforcement is the resource checking metered consumption
   against the signed budget claim of the auth token — the header is a
   pacing signal, not the authorization.

   An implementation that needs the balance to be trustworthy rather
   than merely harmless can cover AAuth-Budget with an HTTP Message
   Signature on the response ([RFC9421]), as the usage endpoint
   recommends for its own responses Section 15.2.4.  It is not required
   here, and the difference is what each response is for.  A usage
   response is a statement of what a person owes for, read by a party
   that may later have to hold the resource to it.  A balance on a
   request response is a pacing signal the agent acts on immediately and

Hardt                     Expires 1 April 2027                 [Page 47]
Internet-Draft                AAuth-Budgets               September 2026

   re-reads on the next call, and signing every metered response to
   protect a figure that is superseded seconds later buys little for
   what it costs at inference volumes.

19.2.  Budget Is Not a Substitute for Scope

   A budget bounds how much an agent may consume, not what it may do.
   An agent with a small budget at a resource that performs irreversible
   actions can still perform them.  Resources MUST continue to enforce
   scope, and SHOULD NOT treat the presence of a budget as evidence that
   the person reviewed anything beyond the amount.

19.3.  Over-Issuance Through Concurrency

   A PS that issues concurrent auth tokens without tracking their sum
   has authorized their sum, not any single one of them Section 14.7.  A
   resource that aggregates non-atomically across concurrent requests
   can be driven past the ceiling by parallel calls.  Both are
   implementation errors that produce real overspend, and both are easy
   to make.

19.4.  Consumption Reports as Attack Surface

   The budget_consumed record is resource-signed and usage counters are
   served from the resource's authenticated endpoint, signed where the
   resource follows Section 15.2.4; both are the resource's own account
   of what it metered.  A resource that inflates them can induce a PS to
   authorize more than the person intended, or to refuse further
   authorization.  An issuer SHOULD reconcile them against the person's
   billing relationship with the resource where one exists, and SHOULD
   NOT treat them as authoritative for anything other than its own next
   decision.

   Signing the usage response Section 15.2.4 does not change this.  It
   makes the resource committed to a figure rather than able to disown
   it, which is what stops it reporting one number to the person server
   and another to the biller.  It does not make the meter honest,
   because the resource meters, reports, and signs.  The person's bill
   is the record a dispute settles against, and a signed report is
   evidence of what the resource said, not of what it consumed.

Hardt                     Expires 1 April 2027                 [Page 48]
Internet-Draft                AAuth-Budgets               September 2026

19.5.  Unit Substitution

   Because a resource may change the unit between what the agent
   requested and what it offers Section 4.2, a PS reading a budget claim
   must read unit and decimals rather than assuming the denomination the
   agent described in justification.  The cross-check against
   budget_units in Section 17 is the defense against a stale scale;
   there is no defense against a resource that misdenominates
   deliberately, and none is needed — that resource is equally free to
   ignore the budget it was granted.

20.  Privacy Considerations

   A budget amount is financial information about the person.  It
   travels from the resource to the PS in the resource token and back in
   the auth token, and appears in plaintext in the AAuth-Budget response
   header on every response.

   The consumption record and usage counters are more revealing than the
   budget itself: counters describe the person's spending at that
   resource over time and by mission, and the record itemizes one grant.
   All of it is visible to the person's PS by design — the PS is
   deciding on the person's behalf.

   The two channels differ in who else can read them.  Usage counters
   travel only between resource and issuer, so tenant-scope and long-
   horizon figures exist nowhere the agent can see.  The consumption
   record rides in the resource token, which the agent relays and can
   read.  It names only the token the agent itself presented, and only
   as a jti and an amount — an agent learns nothing about the person's
   other tokens or other agents from it — and a resource that considers
   even that too revealing omits budget_consumed and serves the usage
   endpoint alone.

   Because AAuth-Budget is unsigned and unencrypted above TLS, every
   intermediary on the path sees the person's remaining balance at that
   resource, and the price of the request that produced the response.
   Carrying no cumulative figure bounds this: an intermediary sees what
   one call cost and what is left of one hour's grant, not the person's
   spending history at that resource.  Deployments that consider even
   the per-call figure sensitive may omit the OPTIONAL cost member from
   the header, at the price of leaving the agent to derive it from
   successive remaining values.

21.  IANA Considerations

Hardt                     Expires 1 April 2027                 [Page 49]
Internet-Draft                AAuth-Budgets               September 2026

21.1.  HTTP Header Field Registration

   This specification registers the following HTTP header field in the
   "Hypertext Transfer Protocol (HTTP) Field Name Registry" established
   by [RFC9110]:

   *  Header Field Name: AAuth-Budget
   *  Status: permanent
   *  Structured Type: Dictionary
   *  Reference: This document, Section 11

21.2.  JWT Claims Registration

   This document requests registration of the following claims in the
   IANA "JSON Web Token Claims" registry established by [RFC7519]:

    +=================+====================+============+=============+
    | Claim Name      | Claim Description  | Change     | Reference   |
    |                 |                    | Controller |             |
    +=================+====================+============+=============+
    | budget          | Authorized         | IETF       | This        |
    |                 | spending ceiling   |            | document,   |
    |                 | at a resource      |            | Section 4.5 |
    +-----------------+--------------------+------------+-------------+
    | budget_consumed | What the presented | IETF       | This        |
    |                 | auth token         |            | document,   |
    |                 | consumed, reported |            | Section 7.1 |
    |                 | by a resource      |            |             |
    +-----------------+--------------------+------------+-------------+

                                  Table 4

21.3.  AAuth Capability Value Registry

   This document requests registration of the following value in the
   AAuth Capability Value Registry established by AAuth Protocol
   ([I-D.hardt-oauth-aauth-protocol]).  The registry policy is
   Specification Required ([RFC8126], Section 4.6).

                  +========+===========================+
                  | Value  | Reference                 |
                  +========+===========================+
                  | budget | This document, Section 16 |
                  +--------+---------------------------+

                                 Table 5

Hardt                     Expires 1 April 2027                 [Page 50]
Internet-Draft                AAuth-Budgets               September 2026

21.4.  No Budget Unit Registry

   This document deliberately establishes no registry of unit values.
   Units are declared by each resource in its budget_units metadata,
   exactly as scope values are declared in scope_descriptions.  See
   Appendix A.10.

22.  Implementation Status

   _Note: This section is to be removed before publishing as an RFC._

   This section records the status of known implementations of the
   protocol defined by this specification at the time of posting of this
   Internet-Draft, and is based on a proposal described in [RFC7942].
   The description of implementations in this section is intended to
   assist the IETF in its decision processes in progressing drafts to
   RFCs.

22.1.  Implementations in Progress

   *tokenpony* (Infinite Logic PBC) meters LLM inference and implements
   TPX [TPX], an OAuth 2.0 profile carrying the same grant for human-
   driven apps.  That deployment is live, and this extension is being
   added over the same metering core, with AuthGravity as the person
   server and Harness News as the agent, in four-party access.  TPX is a
   complete deployment on its own: it needs no person server and nothing
   from this document, and the two specifications share no wire surface
   — one meter, two independent authorization envelopes.

   *Regent Protocol* is in production at get4agent.com (marketplace
   resource and provisioning server): allocations, refusals with
   required, the streaming cost-omitted mode, the usage endpoint, and
   sub-agent delegation.  Its open-source resource/PS middleware regent-
   httpsig (Python, Apache-2.0) publishes test vectors.

   *The editor* is implementing this extension in several services.

   Implementation reports and test vectors are expected from these
   efforts and will be recorded here.

23.  Document History

   _Note: This section is to be removed before publishing as an RFC._

   *  draft-hardt-aauth-budgets-00
      -  Initial submission, written against draft-hardt-oauth-aauth-
         protocol-11.

Hardt                     Expires 1 April 2027                 [Page 51]
Internet-Draft                AAuth-Budgets               September 2026

24.  Acknowledgments

   The author thanks Abay Aubakirov, Alex Polvi, and Karl McGuinness for
   feedback on early drafts.

25.  References

25.1.  Normative References

   [I-D.hardt-httpbis-signature-key]
              Hardt, D. and T. Meunier, "HTTP Signature Keys", 2026,
              <https://datatracker.ietf.org/doc/draft-hardt-httpbis-
              signature-key>.

   [I-D.hardt-oauth-aauth-protocol]
              Hardt, D., "AAuth Protocol", 2026,
              <https://datatracker.ietf.org/doc/draft-hardt-oauth-aauth-
              protocol>.

   [RFC7519]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
              (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
              <https://www.rfc-editor.org/info/rfc7519>.

   [RFC7638]  Jones, M. and N. Sakimura, "JSON Web Key (JWK)
              Thumbprint", RFC 7638, DOI 10.17487/RFC7638, September
              2015, <https://www.rfc-editor.org/info/rfc7638>.

   [RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
              Writing an IANA Considerations Section in RFCs", BCP 26,
              RFC 8126, DOI 10.17487/RFC8126, June 2017,
              <https://www.rfc-editor.org/info/rfc8126>.

   [RFC9110]  Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
              Ed., "HTTP Semantics", STD 97, RFC 9110,
              DOI 10.17487/RFC9110, June 2022,
              <https://www.rfc-editor.org/info/rfc9110>.

   [RFC9111]  Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
              Ed., "HTTP Caching", STD 98, RFC 9111,
              DOI 10.17487/RFC9111, June 2022,
              <https://www.rfc-editor.org/info/rfc9111>.

   [RFC9421]  Backman, A., Ed., Richer, J., Ed., and M. Sporny, "HTTP
              Message Signatures", RFC 9421, DOI 10.17487/RFC9421,
              February 2024, <https://www.rfc-editor.org/info/rfc9421>.

Hardt                     Expires 1 April 2027                 [Page 52]
Internet-Draft                AAuth-Budgets               September 2026

   [RFC9651]  Nottingham, M. and P. Kamp, "Structured Field Values for
              HTTP", RFC 9651, DOI 10.17487/RFC9651, September 2024,
              <https://www.rfc-editor.org/info/rfc9651>.

25.2.  Informative References

   [AP2]      Google, "Agent Payments Protocol (AP2)", 2025,
              <https://ap2-protocol.org/>.

   [ERC20]    Vogelsteller, F. and V. Buterin, "EIP-20: Token Standard",
              2015, <https://eips.ethereum.org/EIPS/eip-20>.

   [I-D.hardt-aauth-r3]
              Hardt, D., "AAuth Rich Resource Requests (R3)", 2026,
              <https://datatracker.ietf.org/doc/draft-hardt-aauth-r3>.

   [I-D.ietf-httpapi-ratelimit-headers]
              Polli, R., Ruiz, A. M., and D. Miller, "RateLimit header
              fields for HTTP", Work in Progress, Internet-Draft, draft-
              ietf-httpapi-ratelimit-headers-11, 23 May 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-
              ratelimit-headers-11>.

   [ISO4217]  International Organization for Standardization, "ISO
              4217:2015 Codes for the representation of currencies",
              2015, <https://www.iso.org/iso-4217-currency-codes.html>.

   [OBIE.VRP] Open Banking Implementation Entity, "Variable Recurring
              Payments Profile, Read/Write Data API", 2024,
              <https://openbankinguk.github.io/read-write-api-
              site3/v4.0/profiles/vrp-profile.html>.

   [ODRL]     W3C, "ODRL Vocabulary and Expression 2.2", 2018,
              <https://www.w3.org/TR/odrl-vocab/>.

   [RFC7942]  Sheffer, Y. and A. Farrel, "Improving Awareness of Running
              Code: The Implementation Status Section", BCP 205,
              RFC 7942, DOI 10.17487/RFC7942, July 2016,
              <https://www.rfc-editor.org/info/rfc7942>.

   [RFC9396]  Lodderstedt, T., Richer, J., and B. Campbell, "OAuth 2.0
              Rich Authorization Requests", RFC 9396,
              DOI 10.17487/RFC9396, May 2023,
              <https://www.rfc-editor.org/info/rfc9396>.

   [RFC9457]  Nottingham, M., Wilde, E., and S. Dalal, "Problem Details
              for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, July 2023,
              <https://www.rfc-editor.org/info/rfc9457>.

Hardt                     Expires 1 April 2027                 [Page 53]
Internet-Draft                AAuth-Budgets               September 2026

   [Stripe.Issuing]
              Stripe, "Stripe Issuing: Card spending controls", 2026,
              <https://docs.stripe.com/api/cards/object#card_object-
              spending_controls>.

   [TPX]      Infinite Logic PBC, "TPX: Token Pony Express — An OAuth
              2.0 Profile for Metered LLM Inference Grants", 2026,
              <https://tokenpony.dev/spec/>.

   [W3C.PaymentRequest]
              W3C, "Payment Request API", 2025,
              <https://www.w3.org/TR/payment-request/>.

   [x402]     x402 Foundation, "x402: HTTP 402 Payment Protocol", 2025,
              <https://docs.x402.org>.

Appendix A.  Design Rationale

A.1.  Why an Integer in a Declared Scale

   *Why not a Structured Field Decimal.* [RFC9651], Section 3.3.2 caps a
   Decimal at 12 integer digits and 3 fractional digits, with round-
   half-to-even serialization.  Inference is priced per million tokens,
   so a single call can cost on the order of $0.000015, which serializes
   to 0.000.  The header would report zero consumption on every request
   while the person receives a bill.

   *Why not a binary float.* IEEE 754 cannot represent 0.1 exactly, and
   a budget is a running sum, so the error accumulates rather than
   cancelling.  No monetary prior art surveyed in Appendix B uses a
   float.

   *Why not a decimal string,* which is what most monetary prior art
   does use ([W3C.PaymentRequest], [x402]).  An integer in a declared
   scale is the only representation under which the Structured Field
   header value and the JWT claim value are the same number.  A decimal
   string in the claim beside a Structured Field Decimal in the header
   would disagree at the third decimal place, and every implementation
   would have to define its own rounding to reconcile them.

A.2.  Why the Scale Is Explicit

   x402 [x402] omits a scale because the asset contract address _is_ the
   unit and the scale comes from the contract, immutably.  USD does not
   work that way.  ISO 4217 [ISO4217] fixes the minor unit for USD at 2,
   and 2 decimal places cannot express a fifteen-microdollar call.  The
   resource is therefore choosing a scale that the unit identifier does
   not determine, and a scale that is chosen has to travel with the

Hardt                     Expires 1 April 2027                 [Page 54]
Internet-Draft                AAuth-Budgets               September 2026

   amount.

A.3.  Why decimals Is in the Signed Claim

   decimals is declared in budget_units metadata and also carried in the
   budget claim.  The duplication is deliberate, and the reason is not
   primarily an attack argument — the resource is the enforcer, and a
   resource willing to reinterpret the scale is equally willing to
   ignore the budget outright.

   The reasons are versioning and self-description:

   *  *Versioning.* Auth tokens live up to an hour.  A resource changing
      its declared precision as an ordinary product decision — cents to
      micro-dollars — would silently reinterpret every token in flight
      by a factor of ten thousand.
   *  *Self-description.* The resource is not the only reader.  The PS
      ledgers against the number, the person's dashboard displays it, a
      proxy logs it, a dispute cites it.  Each would otherwise have to
      resolve the number against mutable metadata fetched at some
      unspecified later time.

A.4.  Why One Record

   An earlier revision carried up to twenty consumption records in the
   resource token, one per recent grant, so that a PS re-deciding saw
   the person's recent spend at the resource without a round trip.
   Working through the issuer's ledger, the presented token's figure is
   the only one that is news.  Every prior token either came back
   through the same path when it was retired, in which case its record
   already arrived, or expired unreported, in which case the
   conservative rule Section 14.4 holds until a usage reading settles it
   Section 14.4.1 — and a reading settles every expired allocation at
   once, without naming any of them.  The prior records cost roughly a
   kilobyte in the 401 header and let an agent read what was spent under
   tokens it never held, including the person's other agents'.  The one
   thing the list uniquely offered — sibling-token spend at a checkpoint
   — is what the per-key query at the usage endpoint answers, per agent
   rather than per token, on a channel the agent is not on.

   The jti stays.  Concurrent tokens are the normal case for an agent
   running several missions, and an issuer holding several live
   allocations for one agent cannot tell from an amount alone which of
   them a figure belongs to.  The alternative — attributing by agent key
   and falling back to the conservative rule when ambiguous — makes the
   fallback the normal case for exactly the agents doing concurrent
   work.  One short claim keeps the figure attributable and idempotent
   per token.

Hardt                     Expires 1 April 2027                 [Page 55]
Internet-Draft                AAuth-Budgets               September 2026

A.5.  Why the Agent Is Not Told Its Cumulative Consumption

   An earlier revision of this document carried a consumed member in the
   header, giving what had been consumed against the auth token to date,
   and a balance_endpoint where the agent could read the same figure on
   demand.  Both are gone.  The agent is told what a request cost and
   what is left; cumulative consumption is reported to the person server
   and not to the agent.

   Four reasons.

   The figure is redundant. granted is in the auth token the agent
   signed the request with, and remaining is in the response, so
   cumulative consumption is granted - remaining whenever nothing is
   reserved.  Carrying a member the recipient can already compute is
   weight without information.

   The word is already spoken for.  A consumption record is a {jti,
   consumed} pair Section 7.1 where consumed means the total metered
   against one token's whole budget.  A person server reads those
   records and this header's semantics against each other.  Having
   consumed mean a per-request figure in one place and a per-token total
   in the other is the kind of collision that survives review and then
   costs an implementer a day.

   Cumulative spend is the more revealing figure.  It describes a
   pattern rather than a transaction, and AAuth-Budget travels unsigned
   past every intermediary on the path Section 20.  What the agent
   genuinely needs per response is the price of the call it just made
   and whether it can afford another.  Both are per-request facts, and
   that is what the field now carries.

   There is a fourth reason that applies across tokens rather than
   within one.  An agent holding its cumulative consumption over a
   series of allocations can watch the series and infer the ceiling
   behind it — how much the PS is willing to release, and how fast.  The
   ceiling is deliberately not disclosed Appendix A.6, and a per-token
   figure that reconstructs it by subtraction discloses it anyway.

   The balance_endpoint went with it.  It was OPTIONAL, existed for one
   case — an ambiguous failure, where the agent cannot say whether a
   request was metered — and cost a resource an endpoint to implement
   and this document a section to specify.  That case is now answered by
   a rule the agent applies locally Section 12.3: assume the maximum
   until a later remaining says otherwise.  A conservative default that
   every agent applies is better than an optional round trip that some
   resources offer.

Hardt                     Expires 1 April 2027                 [Page 56]
Internet-Draft                AAuth-Budgets               September 2026

A.6.  Why the Granted Budget Is Not the Person's Ceiling

   A person server could authorize the whole of a person's intended
   spend at a resource in one auth token and let the agent draw it down.
   TPX [TPX] does the OAuth equivalent: the budget sits on a durable
   grant, the app spends against it unsupervised, and the person hears
   about it when the grant runs dry.  This document does not, and the
   difference is not a missing feature.

   *The figure is not knowable when it would have to be fixed.* A
   mission is approved before the work is done, and the work is what
   determines the cost.  A person asked at approval for a number is
   guessing.  Too low and the agent stops mid-task and the person is
   interrupted anyway.  Too high and the number is not a control,
   because the agent will never reach it and nothing is checked before
   it does.  An allocation sized against what the work has actually cost
   so far does not require the guess to be right.

   *A ceiling the agent can read is a ceiling the agent plans against.*
   An agent that knows it has been authorized for a pool treats the pool
   as available.  An agent that knows only its current allocation asks
   when the allocation runs out, and asking is what puts the PS back in
   the decision.  The justification accompanying that request, and the
   consumption records arriving with it, are the person server's
   evidence — and neither exists if the agent never has to come back.

   *The check-in is the point, not a cost of it.* Re-authorization is
   where the PS reads what the last allocation bought Section 8.2,
   compares it against the mission, and chooses among its six responses
   Section 8.3 — including the two that are not a number at all: asking
   the agent to account for the spend, and ending the work.  A single
   up-front grant has no such moment.  It has one, at approval, when the
   least is known.

   This is why the ceiling appears nowhere on the wire.  There is no
   claim for it, it may not be shared with the agent, and cumulative
   consumption that would reveal it by subtraction is withheld as well
   Appendix A.5.  What the resource enforces is the allocation in the
   token in front of it.  What the person authorized is a matter between
   the person and their PS.

Hardt                     Expires 1 April 2027                 [Page 57]
Internet-Draft                AAuth-Budgets               September 2026

A.7.  Why a Trailer Only Adds a Member

   AAuth-Budget may be sent as a trailer, carrying cost for a response
   whose cost was unknown when the header was written Section 12.  This
   document rejected trailers in an earlier revision, on the reasoning
   of the RateLimit work ([I-D.ietf-httpapi-ratelimit-headers]):
   intermediaries drop them, and combining a header value with a trailer
   value complicates clients.

   The first objection carries less weight here.  It is largely a
   browser property — fetch does not surface trailers — and the traffic
   this document governs is an agent calling a resource, which is
   server-to-server and commonly HTTP/2.  Where a trailer is dropped
   anyway, rule 3 of Section 12.2 makes that harmless.

   The second objection is the real one, and Section 12.2 answers it
   structurally rather than by mandating client behavior.  A recipient
   may discard trailer fields or merge them into the header set, and a
   sender can neither observe nor control which.  Restating a member
   across the two would therefore produce a value that depends on the
   recipient's choice: AAuth-Budget is a Dictionary, duplicate keys
   resolve last-wins ([RFC9651], Section 3.2), so merging yields the
   trailer's value and discarding yields the header's.  Adding a member
   that the header did not carry has no such fork.  Merge yields a
   complete picture, discard yields a conservative one, and neither is
   wrong.

   This is why reserved is a statement about a request rather than a
   running balance.  A running figure would go stale the moment the
   reservation was released, and a stale member surviving a merge is
   exactly the failure the rule exists to prevent.  What was held for a
   request does not change after the fact.

A.8.  Why Not RateLimit

   RateLimit and RateLimit-Policy ([I-D.ietf-httpapi-ratelimit-headers])
   already report a server-side quota and its remaining balance.
   Reusing them would avoid a new header.  Four things prevent it, all
   following from a budget being an authorization rather than a capacity
   hint:

   1.  *Stated non-goal.* The RateLimit specification excludes
       authorization from its scope.  Reporting the balance of a PS-
       issued grant through a field whose own specification says it is
       not for access control is a misuse a reviewer will name.

Hardt                     Expires 1 April 2027                 [Page 58]
Internet-Draft                AAuth-Budgets               September 2026

   2.  *No unit carrier.* q and r MUST be non-negative Integers, and the
       quota units registry covers request, content-bytes, and
       concurrent-requests.  There is no currency carrier, so the
       denomination would be invisible in the field reporting the
       number.
   3.  *Opposite reliability contracts.* RateLimit says servers need not
       send the fields on every response, clients must not assume future
       responses will carry them, and a positive r is not a guarantee of
       anything.  Those are correct properties for a capacity hint and
       wrong ones for the remaining portion of an authorization, which
       is why Section 11.1 requires the field on every response the
       metering layer answers rather than leaving it optional.
   4.  *Intermediary rewriting.* Intermediaries MAY tighten RateLimit
       values.  An intermediary tightening a budget balance is forging
       authorization state.

   The two fields are complementary and MAY appear on the same response.
   A resource limiting an agent to 100 requests per minute _and_ to five
   dollars of spend is stating two different things, and collapsing them
   loses one.

A.9.  Why Budget Is Not a Mission Aggregate

   A mission description may well say "budget around $5,000," and the
   obvious next step is to make that a protocol object the PS enforces
   across every resource the mission touches.  This document does not,
   for two reasons.

   The resources in a mission meter in units that do not add up.  An
   airline meters in USD, an inference endpoint in micro-dollars or
   tokens, a storage service in gigabyte-months.  Aggregating requires
   conversion rates and a common denomination, neither of which the
   protocol has, and both of which change.

   More fundamentally, the enforcement point is wrong.  The party that
   can enforce a per-resource ceiling is the resource, because it
   meters.  No party meters the mission.  A mission-level total is a PS
   policy input — the PS decides how much of the person's $5,000 to
   authorize at each resource as it goes — which is exactly what the
   narrowing chain in Section 4.2 gives it.  The mission description
   already carries the person's intent, and the PS already reads it.

A.10.  Why Units Are Not Registered

   RateLimit establishes an IANA registry of quota units because its
   units — request, content-bytes, concurrent-requests — are protocol-
   generic and every server means the same thing by them.

Hardt                     Expires 1 April 2027                 [Page 59]
Internet-Draft                AAuth-Budgets               September 2026

   Budget units are not generic.  A unit is meaningful only against a
   resource's own pricing, and the parties that need to interpret it are
   the resource that declared it and the PS that fetched the resource's
   metadata.  This is the same situation as scope values, which the base
   protocol leaves to each resource's scope_descriptions rather than
   registering.  Registering USD would add nothing that ISO 4217 does
   not already provide, and registering tokens would suggest an
   interoperable meaning that does not exist.

   No registry does not mean no constraint.  A monetary unit SHOULD be
   an ISO 4217 alphabetic code Section 4.5, which is what keeps a
   consent screen able to render "$5.00" rather than a resource-invented
   string the person has to interpret.  What is left unregistered is the
   non-monetary case, where no external register exists to point at.

Appendix B.  Prior Art

   This section is non-normative.  It records where the field shapes and
   value encodings in this document come from, and what gap remains.

B.1.  RFC 9396, Rich Authorization Requests

   [RFC9396] (OAuth WG, May 2023), Section 2.2 defines the complete set
   of common data fields for an authorization detail: type, locations,
   actions, datatypes, identifier, privileges.  There is no amount or
   quantity field among them. instructedAmount appears only in the
   document's examples and belongs to the payment_initiation
   authorization details type, which comes from Berlin Group NextGenPSD2
   and carries ISO 20022 ActiveCurrencyAndAmount semantics; it is not
   defined by RFC 9396.

   Section 10 states that registration of authorization details types
   with the AS is outside the specification's scope, and Section 14
   registers the request parameter, the claim, the metadata fields, and
   the invalid_authorization_details error — but establishes no registry
   of types.

   Section 6.1 is the load-bearing citation: there is no standardized
   mechanism for comparing two arbitrary authorization detail requests,
   and an AS should not rely on simple object comparison.  AAuth Budgets
   closes that gap for one narrow case.  Because the unit is resource-
   declared and the value is an integer in a declared scale, "is this
   grant less than the prior one" is a numeric comparison rather than a
   structural one.

   R3 ([I-D.hardt-aauth-r3]) covers why AAuth does not profile RAR
   generally.

Hardt                     Expires 1 April 2027                 [Page 60]
Internet-Draft                AAuth-Budgets               September 2026

B.2.  TPX

   TPX [TPX] is an OAuth 2.0 profile for metered LLM inference grants:
   apps ship without provider keys, and the person grants each app a
   metered budget from a provider the person chooses and pays.  The
   budget rides RFC 9396 authorization_details as {type: "llm-
   inference", budget, models}; the user or provider MAY grant less than
   requested and the client MUST read the granted figure from the token
   response — the requested/granted split of the narrowing chain
   Section 4.2, in OAuth form.

   Three of its mechanisms have direct counterparts here.  Its GET
   /credits spend summary and budget_used introspection member report
   cumulative spend on a grant, which this document reports to the
   person server Section 15 rather than to the agent Appendix A.5.  Its
   separation of budget_exhausted from balance_exhausted is the same
   boundary Section 13.4 draws between re-authorization and payment.
   And its budget is "a damage cap, not a payment" — the hard-cap
   property Section 14.8 states, which TPX asserts as a property of the
   grant and this document additionally realizes with reservations,
   since an agent's operations are unbounded before generation.

   TPX denominates in USD as decimal JSON numbers with at most six
   fractional digits, where this document uses an integer in a declared
   scale Appendix A.1.  TPX serves human-driven apps over OAuth;
   Section 18 describes the deployment where one provider's meter serves
   both envelopes.

B.3.  UK Open Banking Variable Recurring Payments

   [OBIE.VRP] ControlParameters is the most complete standing-budget
   model in production: MaximumIndividualAmount,
   MaximumCumulativeAmount, MaximumCumulativeNumberOfPayments, and
   PeriodicLimits[] carrying PeriodType and PeriodAlignment.
   PeriodAlignment — Consent versus Calendar — names the choice the
   usage counters Section 15 make: calendar alignment, with the timezone
   question answered by fixing UTC.

B.4.  Stripe Issuing Spending Controls

   [Stripe.Issuing] spending_controls.spending_limits[] is {amount,
   interval, categories}, with amount an integer in the currency's
   smallest unit. interval spans per_authorization through all_time,
   which is the precedent for expressing a per-transaction cap and a
   periodic cap in a single enumeration rather than two fields; the
   usage counters Section 15 adopt the date-based portion of that
   enumeration directly.  Stripe computes all date-based intervals from
   midnight UTC — the precedent for fixing UTC by definition — and

Hardt                     Expires 1 April 2027                 [Page 61]
Internet-Draft                AAuth-Budgets               September 2026

   documents spending aggregation as best-effort with up to 30 seconds
   of delay, the precedent for as_of.

B.5.  W3C Payment Request API

   [W3C.PaymentRequest] PaymentCurrencyAmount is {currency, value} with
   value a decimal string.  It is reused by Google's Agent Payments
   Protocol [AP2] in CartMandate.  AP2's IntentMandate carries a maximum
   price, an expiry, and a merchant allowlist as user-signed
   constraints, which is the closest prior art to a user-authorized
   agent ceiling.

B.6.  x402

   [x402] carries maxAmountRequired as a string in the asset's atomic
   units, alongside asset (a contract address) and network; v2 renames
   the field to amount and moves network to CAIP-2 form.  There is no
   currency field: the asset identifier is the unit, and the exponent
   comes from the contract.  This is the precedent for using a unit
   identifier rather than a currency field, and for decimals as the name
   of the scale.

B.7.  ODRL

   [ODRL] payAmount with unit is the precedent for a field literally
   named unit holding a currency code.

B.8.  RateLimit Header Fields

   [I-D.ietf-httpapi-ratelimit-headers] (HTTPAPI WG, Standards Track,
   not yet an RFC) defines RateLimit-Policy with q, qu, w, and pk, and
   RateLimit with r, t, and pk, both as RFC 9651 Lists.  It establishes
   an IANA RateLimit Quota Units registry (Specification Required) with
   initial entries request, content-bytes, and concurrent-requests, and
   three RFC 9457 problem types: quota-exceeded (429), temporary-
   reduced-capacity (503), and abnormal-usage-detected (429).

   It is cited here for why AAuth-Budget exists separately Appendix A.8,
   for the trailer rules Section 12.2, and for pk as the precedent for a
   documented, client-predictable partition key.

Author's Address

   Dick Hardt
   Hellō
   Email: dick.hardt@gmail.com

Hardt                     Expires 1 April 2027                 [Page 62]