<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.39 (Ruby 4.0.6) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

<!ENTITY RFC2119 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC3339 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3339.xml">
<!ENTITY RFC4648 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml">
<!ENTITY RFC8174 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY RFC8259 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml">
<!ENTITY RFC9110 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9110.xml">
<!ENTITY RFC9111 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9111.xml">
<!ENTITY RFC9457 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9457.xml">
<!ENTITY RFC8610 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml">
]>


<rfc ipr="trust200902" docName="draft-hedera-session-00" category="info" submissionType="independent">
  <front>
    <title abbrev="Hedera Session">Hedera Session Intent for HTTP Payment Authentication</title>

    <author initials="T." surname="Rowbotham" fullname="Tom Rowbotham">
      <organization></organization>
      <address>
        <email>tom@xeno.money</email>
      </address>
    </author>
    <author initials="L." surname="Walker" fullname="Lindsay Walker">
      <organization>Hedera / Hashgraph</organization>
      <address>
        <email>lindsay.w@swirldslabs.com</email>
      </address>
    </author>

    <date year="2026" month="August" day="07"/>

    
    
    

    <abstract>


<?line 75?>

<t>This document defines the "session" intent for the
"hedera" payment method in the Payment HTTP Authentication
Scheme. It specifies unidirectional streaming payment
channels for incremental, voucher-based payments suitable
for low-cost metered services on the Hedera network.</t>



    </abstract>



  </front>

  <middle>


<?line 83?>

<section anchor="introduction"><name>Introduction</name>

<t>This document is published as Informational but contains
normative requirements using BCP 14 keywords <xref target="RFC2119"/>
<xref target="RFC8174"/> to ensure interoperability between
implementations. Payment method specifications that
reference this document inherit these requirements.</t>

<t>The <spanx style="verb">session</spanx> intent establishes a unidirectional streaming
payment channel using on-chain escrow and off-chain
<xref target="EIP-712"/> vouchers. This enables high-frequency, low-cost
payments by batching many off-chain voucher signatures into
periodic on-chain settlements.</t>

<t>Unlike the <spanx style="verb">charge</spanx> intent which requires the full payment
amount upfront, the <spanx style="verb">session</spanx> intent allows clients to pay
incrementally as they consume services, paying exactly for
resources received.</t>

<t>The escrow contract (HederaStreamChannel.sol) is deployed
on Hedera's EVM layer and uses standard ERC-20 token
transfers. Hedera Token Service (HTS) tokens are exposed
as ERC-20 via <xref target="HIP-218"/>, enabling payment channels with
native HTS tokens such as Circle USDC
<xref target="CIRCLE-USDC-HEDERA"/>.</t>

<section anchor="use-case-llm-token-streaming"><name>Use Case: LLM Token Streaming</name>

<t>Consider an LLM inference API that charges per output
token:</t>

<t><list style="numbers" type="1">
  <t>Client requests a streaming completion (SSE response)</t>
  <t>Server returns 402 with a <spanx style="verb">session</spanx> challenge</t>
  <t>Client opens a payment channel on-chain, depositing
funds into the HederaStreamChannel escrow</t>
  <t>Server begins streaming response</t>
  <t>As response streams, or over incremental requests,
client signs vouchers with increasing amounts</t>
  <t>Server settles periodically or at stream completion</t>
</list></t>

<t>The client pays exactly for tokens received, with no
worst-case reservation.</t>

</section>
<section anchor="session-flow"><name>Session Flow</name>

<t>The following diagram illustrates the Hedera session flow:</t>

<figure><artwork><![CDATA[
 Client                   Server            Hedera EVM
    |                        |                    |
    |  (1) GET /resource     |                    |
    |----------------------> |                    |
    |                        |                    |
    |  (2) 402 Payment       |                    |
    |      Required          |                    |
    |      intent="session"  |                    |
    |      (includes         |                    |
    |       challengeId)     |                    |
    |<---------------------- |                    |
    |                        |                    |
    |  (3) approve() +       |                    |
    |      open() on-chain   |                    |
    |--------------------------------------->     |
    |                        |                    |
    |  (4) GET /resource     |                    |
    |      Authorization:    |                    |
    |      Payment           |                    |
    |      action="open"     |                    |
    |      (channelId,       |                    |
    |       txHash, voucher) |                    |
    |----------------------> |                    |
    |                        |                    |
    |                        |  (5) verify        |
    |                        |   on-chain state   |
    |                        |---------------->   |
    |                        |                    |
    |  (6) 200 OK + Receipt  |                    |
    |      (streaming        |                    |
    |       response)        |                    |
    |<---------------------- |                    |
    |                        |                    |
    |  (7) HEAD /resource    |                    |
    |      action="voucher"  |                    |
    |      (top-up, same     |                    |
    |       URI)             |                    |
    |----------------------> |                    |
    |                        |                    |
    |  (8) 200 OK + Receipt  |                    |
    |<---------------------- |                    |
    |                        |                    |
    |  (9) GET /resource     |                    |
    |      action="voucher"  |                    |
    |      (incremental      |                    |
    |       request)         |                    |
    |----------------------> |                    |
    |                        |                    |
    |  (10) 200 OK + Receipt |                    |
    |       (additional      |                    |
    |        response)       |                    |
    |<---------------------- |                    |
    |                        |                    |
    |  (11) GET /resource    |                    |
    |       action="close"   |                    |
    |----------------------> |                    |
    |                        |  (12) close()      |
    |                        |---------------->   |
    |                        |                    |
    |  (13) 200 OK + Receipt |                    |
    |       (includes        |                    |
    |        txHash)         |                    |
    |<---------------------- |                    |
    |                        |                    |
]]></artwork></figure>

<t>Unlike Tempo session where the client sends a signed
transaction for the server to broadcast, in the Hedera
session the client broadcasts the <spanx style="verb">open</spanx> (and <spanx style="verb">topUp</spanx>)
transactions directly via Hashio JSON-RPC and presents
the transaction hash to the server. The server verifies
the on-chain state.</t>

<t>Voucher updates and close requests are submitted to the
<strong>same resource URI</strong> that requires payment. This allows
sessions to work on any endpoint without dedicated
payment control plane routes. Servers <bcp14>SHOULD</bcp14> support
voucher updates via any HTTP method; clients <bcp14>MAY</bcp14> use
<spanx style="verb">HEAD</spanx> for pure voucher top-ups when no response body
is needed.</t>

</section>
<section anchor="concurrency"><name>Concurrency Model</name>

<t>A channel supports one active session at a time. The
cumulative voucher semantics ensure correctness -- each
voucher advances a single monotonic counter. The channel
is the unit of concurrency; no additional session locking
is required.</t>

<t>When a client sends a new streaming request on a channel
that already has an active session, servers <bcp14>SHOULD</bcp14>
terminate the previous session and start a new one.
Voucher updates <bcp14>MAY</bcp14> arrive on separate HTTP connections
(including HTTP/2 streams) and <bcp14>MUST</bcp14> be processed
atomically with respect to balance updates.</t>

<t>Servers <bcp14>MUST</bcp14> ensure that voucher acceptance and balance
deduction are serialized per channel to prevent race
conditions.</t>

</section>
</section>
<section anchor="requirements-language"><name>Requirements Language</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

</section>
<section anchor="terminology"><name>Terminology</name>

<dl>
  <dt>Streaming Payment Channel</dt>
  <dd>
    <t>A unidirectional off-chain payment mechanism where the
payer deposits funds into an escrow contract and signs
cumulative vouchers authorizing increasing payment
amounts.</t>
  </dd>
  <dt>Voucher</dt>
  <dd>
    <t>An <xref target="EIP-712"/> signed message authorizing a cumulative
payment amount for a specific channel. Vouchers are
monotonically increasing in amount.</t>
  </dd>
  <dt>Channel</dt>
  <dd>
    <t>A payment relationship between a payer and payee,
identified by a unique <spanx style="verb">channelId</spanx>. The channel holds
deposited funds and tracks cumulative settlements.</t>
  </dd>
  <dt>Settlement</dt>
  <dd>
    <t>The on-chain ERC-20 transfer that converts off-chain
voucher authorizations into actual token movement. HTS
tokens are transferred via standard ERC-20 interfaces
exposed through <xref target="HIP-218"/>.</t>
  </dd>
  <dt>Authorized Signer</dt>
  <dd>
    <t>An address delegated to sign vouchers on behalf of the
payer. Defaults to the payer if not specified.</t>
  </dd>
  <dt>Base Units</dt>
  <dd>
    <t>The smallest indivisible unit of an HTS token. For
example, Circle USDC on Hedera uses 6 decimal places;
one million base units equals 1.00 USDC.</t>
  </dd>
  <dt>Hashio JSON-RPC</dt>
  <dd>
    <t>Hedera's EVM-compatible JSON-RPC relay that enables
standard Ethereum tooling (e.g., viem, ethers.js) to
interact with smart contracts deployed on Hedera's EVM
layer.</t>
  </dd>
</dl>

</section>
<section anchor="encoding"><name>Encoding Conventions</name>

<t>This section defines normative encoding rules for
interoperability.</t>

<section anchor="hexadecimal-values"><name>Hexadecimal Values</name>

<t>All byte arrays (addresses, hashes, signatures,
channelId) use:</t>

<t><list style="symbols">
  <t>Lowercase hexadecimal encoding</t>
  <t><spanx style="verb">0x</spanx> prefix</t>
  <t>No padding or truncation</t>
</list></t>

<texttable>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Length</ttcol>
      <ttcol align='left'>Example</ttcol>
      <ttcol align='left'>&#160;</ttcol>
      <ttcol align='left'>&#160;</ttcol>
      <ttcol align='left'>&#160;</ttcol>
      <ttcol align='left'>&#160;</ttcol>
      <c>address</c>
      <c>42 chars (0x + 40 hex)</c>
      <c><spanx style="verb">0x742d...f8fe00</spanx></c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>bytes32</c>
      <c>66 chars (0x + 64 hex)</c>
      <c><spanx style="verb">0x6d0f...8e9f</spanx></c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>&#160;</c>
      <c>signature</c>
      <c>130-132 chars</c>
      <c>65-byte r</c>
      <c>&#160;</c>
      <c>s</c>
      <c>&#160;</c>
      <c>v</c>
</texttable>

<t>Implementations <bcp14>MUST</bcp14> use lowercase hex. Implementations
<bcp14>SHOULD</bcp14> accept mixed-case input but normalize to lowercase
before comparison.</t>

<t>Note: Hedera "long-zero" EVM addresses (e.g.,
<spanx style="verb">0x0000000000000000000000000000000000001549</spanx> for HTS token
0.0.5449) are valid 20-byte addresses and <bcp14>MUST</bcp14> be handled
correctly. Implementations <bcp14>MUST</bcp14> use case-insensitive
comparison for all address fields.</t>

</section>
<section anchor="numeric-values"><name>Numeric Values</name>

<t>Integer values (amounts, timestamps) are encoded as
decimal strings in JSON to avoid precision loss with
large numbers:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Encoding</ttcol>
      <ttcol align='left'>Example</ttcol>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>Decimal string</c>
      <c><spanx style="verb">"250000"</spanx></c>
      <c><spanx style="verb">requestedAt</spanx></c>
      <c>Decimal string</c>
      <c><spanx style="verb">"1736165100"</spanx></c>
      <c><spanx style="verb">chainId</spanx></c>
      <c>JSON number</c>
      <c><spanx style="verb">296</spanx></c>
</texttable>

<t>The <spanx style="verb">chainId</spanx> uses JSON number encoding as values are
small enough to avoid precision issues.</t>

</section>
<section anchor="timestamp-format"><name>Timestamp Format</name>

<t>HTTP headers and receipt fields use <xref target="RFC3339"/> formatted
timestamps: <spanx style="verb">2026-04-12T12:05:00Z</spanx>. Timestamps in
EIP-712 signed data use Unix seconds as decimal strings.</t>

</section>
</section>
<section anchor="channel-escrow-contract"><name>Channel Escrow Contract</name>

<t>Streaming payment channels require an on-chain escrow
contract that holds user deposits and enforces
voucher-based withdrawals. On Hedera, this contract is
deployed on the EVM layer and interacts with HTS tokens
via their ERC-20 interface <xref target="HIP-218"/>.</t>

<section anchor="channel-state"><name>Channel State</name>

<t>Each channel is identified by a unique <spanx style="verb">channelId</spanx> and
stores:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">payer</spanx></c>
      <c>address</c>
      <c>User who deposited funds</c>
      <c><spanx style="verb">payee</spanx></c>
      <c>address</c>
      <c>Server authorized to withdraw</c>
      <c><spanx style="verb">token</spanx></c>
      <c>address</c>
      <c>ERC-20 token address (HTS via HIP-218)</c>
      <c><spanx style="verb">authorizedSigner</spanx></c>
      <c>address</c>
      <c>Authorized signer (0 = payer)</c>
      <c><spanx style="verb">deposit</spanx></c>
      <c>uint128</c>
      <c>Total amount deposited</c>
      <c><spanx style="verb">settled</spanx></c>
      <c>uint128</c>
      <c>Cumulative amount withdrawn by payee</c>
      <c><spanx style="verb">closeRequestedAt</spanx></c>
      <c>uint64</c>
      <c>Timestamp when close was requested (0 if not)</c>
      <c><spanx style="verb">finalized</spanx></c>
      <c>bool</c>
      <c>Whether channel is closed</c>
</texttable>

<t>The <spanx style="verb">channelId</spanx> <bcp14>MUST</bcp14> be computed deterministically using
the escrow contract's <spanx style="verb">computeChannelId()</spanx> function:</t>

<figure><artwork><![CDATA[
channelId = keccak256(abi.encode(
    payer,
    payee,
    token,
    salt,
    authorizedSigner,
    address(this),
    block.chainid
))
]]></artwork></figure>

<t>Note: The <spanx style="verb">channelId</spanx> includes <spanx style="verb">address(this)</spanx> (the
escrow contract address) and <spanx style="verb">block.chainid</spanx>, explicitly
binding the channel to a specific contract deployment and
chain. Clients <bcp14>MUST</bcp14> use the contract's
<spanx style="verb">computeChannelId()</spanx> function or equivalent logic to
ensure interoperability.</t>

</section>
<section anchor="channel-lifecycle"><name>Channel Lifecycle</name>

<t>Channels have no expiry -- they remain open until
explicitly closed.</t>

<figure><artwork><![CDATA[
+-------------------------------------------------+
|               CHANNEL OPEN                      |
|  Client approves ERC-20 + calls open()          |
|  on HederaStreamChannel via Hashio JSON-RPC     |
+-------------------------------------------------+
                       |
                       v
+-------------------------------------------------+
|             SESSION PAYMENTS                    |
|  Client signs EIP-712 vouchers off-chain        |
|  Server may periodically settle() on-chain      |
+-------------------------------------------------+
                       |
           +-----------+-----------+
           v                       v
+---------------------+  +-----------------------+
|  COOPERATIVE CLOSE  |  |     FORCED CLOSE      |
|  Server calls       |  | 1. Client calls       |
|  close() with       |  |    requestClose()     |
|  final voucher      |  | 2. Wait 15 min grace  |
|                     |  | 3. Client calls       |
|                     |  |    withdraw()         |
+---------------------+  +-----------------------+
           |                       |
           +-----------+-----------+
                       v
+-------------------------------------------------+
|              CHANNEL CLOSED                     |
|  Funds distributed, channel finalized           |
+-------------------------------------------------+
]]></artwork></figure>

</section>
<section anchor="contract-functions"><name>Contract Functions</name>

<t>Compliant escrow contracts <bcp14>MUST</bcp14> implement the following
functions. The signatures shown are the reference
HederaStreamChannel.sol implementation.</t>

<section anchor="open"><name>open</name>

<t>Opens a new channel with escrowed funds.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">payee</spanx></c>
      <c>address</c>
      <c>Server's withdrawal address</c>
      <c><spanx style="verb">token</spanx></c>
      <c>address</c>
      <c>ERC-20 token contract address</c>
      <c><spanx style="verb">deposit</spanx></c>
      <c>uint128</c>
      <c>Amount to deposit in base units</c>
      <c><spanx style="verb">salt</spanx></c>
      <c>bytes32</c>
      <c>Random value for channelId</c>
      <c><spanx style="verb">authorizedSigner</spanx></c>
      <c>address</c>
      <c>Delegated signer; <spanx style="verb">0x0</spanx> = payer</c>
</texttable>

<t>Returns the computed <spanx style="verb">channelId</spanx>.</t>

<figure><sourcecode type="solidity"><![CDATA[
function open(
    address payee,
    address token,
    uint128 deposit,
    bytes32 salt,
    address authorizedSigner
) external returns (bytes32 channelId);
]]></sourcecode></figure>

<t>The client <bcp14>MUST</bcp14> approve the escrow contract to spend
<spanx style="verb">deposit</spanx> tokens before calling <spanx style="verb">open()</spanx>. On Hedera,
HTS token approvals via the ERC-20 interface require
higher gas limits (approximately 1,000,000 gas) due to
the HTS precompile overhead.</t>

</section>
<section anchor="settle"><name>settle</name>

<t>Server withdraws funds using a signed voucher without
closing the channel.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>bytes32</c>
      <c>Channel identifier</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>uint128</c>
      <c>Cumulative total authorized</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>bytes</c>
      <c>EIP-712 signature</c>
</texttable>

<t>The contract computes
<spanx style="verb">delta = cumulativeAmount - channel.settled</spanx> and
transfers <spanx style="verb">delta</spanx> tokens to the payee.</t>

<figure><sourcecode type="solidity"><![CDATA[
function settle(
    bytes32 channelId,
    uint128 cumulativeAmount,
    bytes calldata signature
) external;
]]></sourcecode></figure>

</section>
<section anchor="topup"><name>topUp</name>

<t>User adds more funds to an existing channel. If a close
request is pending (<spanx style="verb">closeRequestedAt != 0</spanx>), calling
<spanx style="verb">topUp()</spanx> <bcp14>MUST</bcp14> cancel it by resetting
<spanx style="verb">closeRequestedAt</spanx> to zero and emitting a
<spanx style="verb">CloseRequestCancelled</spanx> event.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>bytes32</c>
      <c>Existing channel identifier</c>
      <c><spanx style="verb">additionalDeposit</spanx></c>
      <c>uint256</c>
      <c>Additional amount in base units</c>
</texttable>

<figure><sourcecode type="solidity"><![CDATA[
function topUp(
    bytes32 channelId,
    uint256 additionalDeposit
) external;
]]></sourcecode></figure>

<t>Note: The <spanx style="verb">additionalDeposit</spanx> parameter is <spanx style="verb">uint256</spanx>
(not <spanx style="verb">uint128</spanx>) in HederaStreamChannel.sol; the contract
checks for overflow internally.</t>

</section>
<section anchor="close"><name>close</name>

<t>Server closes the channel, settling any outstanding
voucher and refunding the remainder to the payer. Only
callable by the payee.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>bytes32</c>
      <c>Channel to close</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>uint128</c>
      <c>Final cumulative amount</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>bytes</c>
      <c>EIP-712 signature</c>
</texttable>

<t>Transfers <spanx style="verb">cumulativeAmount - channel.settled</spanx> to payee,
refunds <spanx style="verb">channel.deposit - cumulativeAmount</spanx> to payer,
and marks channel finalized.</t>

<figure><sourcecode type="solidity"><![CDATA[
function close(
    bytes32 channelId,
    uint128 cumulativeAmount,
    bytes calldata signature
) external;
]]></sourcecode></figure>

</section>
<section anchor="requestclose"><name>requestClose</name>

<t>User requests channel closure, starting a grace period
of at least 15 minutes.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>bytes32</c>
      <c>Channel to request closure for</c>
</texttable>

<t>Sets <spanx style="verb">channel.closeRequestedAt</spanx> to current block
timestamp. The grace period allows the payee time to
submit any outstanding vouchers before forced closure.</t>

<figure><sourcecode type="solidity"><![CDATA[
function requestClose(
    bytes32 channelId
) external;
]]></sourcecode></figure>

</section>
<section anchor="withdraw"><name>withdraw</name>

<t>User withdraws remaining funds after the grace period
expires.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>bytes32</c>
      <c>Channel to withdraw from</c>
</texttable>

<t>Requires <spanx style="verb">block.timestamp &gt;= channel.closeRequestedAt +
CLOSE_GRACE_PERIOD</spanx>. Refunds all remaining deposit to
payer and marks channel finalized.</t>

<figure><sourcecode type="solidity"><![CDATA[
function withdraw(bytes32 channelId) external;
]]></sourcecode></figure>

</section>
<section anchor="associate-self"><name>associateSelf</name>

<t>Associates the escrow contract with an HTS token so it
can receive transfers. This is a Hedera-specific
function with no Tempo equivalent.</t>

<texttable>
      <ttcol align='left'>Parameter</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">token</spanx></c>
      <c>address</c>
      <c>HTS token to associate</c>
</texttable>

<figure><sourcecode type="solidity"><![CDATA[
function associateSelf(
    address token
) external returns (int256 responseCode);
]]></sourcecode></figure>

<t>This function calls the HTS precompile at address
<spanx style="verb">0x167</spanx> to perform token association. Anyone can call
it. The escrow contract <bcp14>MUST</bcp14> be associated with the
payment token before channels using that token can be
opened.</t>

</section>
</section>
<section anchor="access-control"><name>Access Control</name>

<t>The escrow contract <bcp14>MUST</bcp14> enforce the following access
control:</t>

<texttable>
      <ttcol align='left'>Function</ttcol>
      <ttcol align='left'>Caller</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">open</spanx></c>
      <c>Anyone</c>
      <c>Creates channel; caller = payer</c>
      <c><spanx style="verb">settle</spanx></c>
      <c>Payee only</c>
      <c>Withdraws with voucher</c>
      <c><spanx style="verb">topUp</spanx></c>
      <c>Payer only</c>
      <c>Adds funds</c>
      <c><spanx style="verb">close</spanx></c>
      <c>Payee only</c>
      <c>Closes with final voucher</c>
      <c><spanx style="verb">requestClose</spanx></c>
      <c>Payer only</c>
      <c>Initiates forced close</c>
      <c><spanx style="verb">withdraw</spanx></c>
      <c>Payer only</c>
      <c>Withdraws after grace</c>
      <c><spanx style="verb">associateSelf</spanx></c>
      <c>Anyone</c>
      <c>HTS token association</c>
</texttable>

</section>
<section anchor="signature-verification"><name>Signature Verification</name>

<t>The escrow contract <bcp14>MUST</bcp14> perform the following signature
verification for all functions that accept voucher
signatures (<spanx style="verb">settle</spanx>, <spanx style="verb">close</spanx>):</t>

<t><list style="numbers" type="1">
  <t><strong>Canonical signatures</strong>: The contract <bcp14>MUST</bcp14> reject
ECDSA signatures with non-canonical (high-s) values.
Signatures <bcp14>MUST</bcp14> have
<spanx style="verb">s &lt;= secp256k1_order / 2</spanx> where the half-order is
<spanx style="verb">0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E73</spanx>
<spanx style="verb">57A4501DDFE92F46681B20A0</spanx>.
See <xref target="signature-malleability"/> for rationale.</t>
  <t><strong>Authorized signer verification</strong>: The contract <bcp14>MUST</bcp14>
recover the signer address from the EIP-712 signature
and verify it matches the expected signer:
  <list style="symbols">
      <t>If <spanx style="verb">channel.authorizedSigner</spanx> is non-zero, the
recovered signer <bcp14>MUST</bcp14> equal
<spanx style="verb">channel.authorizedSigner</spanx></t>
      <t>Otherwise, the recovered signer <bcp14>MUST</bcp14> equal
<spanx style="verb">channel.payer</spanx></t>
    </list></t>
  <t><strong>Domain binding</strong>: The contract <bcp14>MUST</bcp14> use its own
address as the <spanx style="verb">verifyingContract</spanx> in the EIP-712
domain separator, ensuring vouchers cannot be
replayed across different escrow deployments.</t>
</list></t>

<t>Failure to enforce these requirements on-chain would
allow attackers to bypass server-side validation by
submitting transactions directly to the contract.</t>

</section>
</section>
<section anchor="request-schema"><name>Request Schema</name>

<t>The <spanx style="verb">request</spanx> parameter in the <spanx style="verb">WWW-Authenticate</spanx>
challenge contains a base64url-encoded JSON object.</t>

<section anchor="fields"><name>Fields</name>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">amount</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Price per unit in base units</c>
      <c><spanx style="verb">unitType</spanx></c>
      <c>string</c>
      <c><bcp14>OPTIONAL</bcp14></c>
      <c>Unit being priced (e.g., <spanx style="verb">"llm_token"</spanx>)</c>
      <c><spanx style="verb">suggestedDeposit</spanx></c>
      <c>string</c>
      <c><bcp14>OPTIONAL</bcp14></c>
      <c>Suggested deposit in base units</c>
      <c><spanx style="verb">currency</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>ERC-20 token address (HTS via HIP-218)</c>
      <c><spanx style="verb">recipient</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Payee address (server's withdrawal address)</c>
</texttable>

<t>For the <spanx style="verb">session</spanx> intent, <spanx style="verb">amount</spanx> specifies the price
per unit of service in base units (e.g., 6 decimals for
USDC), not a total charge. When <spanx style="verb">unitType</spanx> is present,
clients can use it together with <spanx style="verb">amount</spanx> to estimate
costs before streaming begins. The total cost depends on
consumption: <spanx style="verb">total = amount * units_consumed</spanx>.</t>

<t>The optional <spanx style="verb">suggestedDeposit</spanx> indicates the server's
recommended channel deposit for typical usage. Clients
<bcp14>MAY</bcp14> deposit less (if they expect limited usage) or more
(for extended sessions). The minimum viable deposit is
implementation-defined but <bcp14>SHOULD</bcp14> be at least <spanx style="verb">amount</spanx>
to cover one unit of service.</t>

<t>Challenge expiry is specified via the <spanx style="verb">expires</spanx>
auth-param in the <spanx style="verb">WWW-Authenticate</spanx> header per
<xref target="I-D.httpauth-payment"/>, using <xref target="RFC3339"/> timestamp
format. Unlike the <spanx style="verb">charge</spanx> intent, the session request
JSON does not include an <spanx style="verb">expires</spanx> field -- expiry is
conveyed solely via the HTTP header.</t>

</section>
<section anchor="method-details"><name>Method Details</name>

<t>As of version 00, session-specific request fields are
placed in <spanx style="verb">methodDetails</spanx>. A future high-level "session"
intent definition may promote common fields to the core
schema.</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">methodDetails.escrowContract</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Escrow contract address</c>
      <c><spanx style="verb">methodDetails.channelId</spanx></c>
      <c>string</c>
      <c><bcp14>OPTIONAL</bcp14></c>
      <c>Channel ID if resuming</c>
      <c><spanx style="verb">methodDetails.minVoucherDelta</spanx></c>
      <c>string</c>
      <c><bcp14>OPTIONAL</bcp14></c>
      <c>Minimum voucher increment</c>
      <c><spanx style="verb">methodDetails.chainId</spanx></c>
      <c>number</c>
      <c><bcp14>OPTIONAL</bcp14></c>
      <c>Hedera chain ID (default: 295)</c>
</texttable>

<t>Note: Unlike the Tempo session spec, there is no
<spanx style="verb">feePayer</spanx> field in this version. Hedera supports native
fee delegation via <spanx style="verb">feePayerAccountId</spanx> but this is
deferred to a future revision (see <xref target="fee-delegation"/>).</t>

<t>Channel reuse is <bcp14>OPTIONAL</bcp14>. Servers <bcp14>MAY</bcp14> include
<spanx style="verb">channelId</spanx> to suggest resuming an existing channel:</t>

<t><list style="symbols">
  <t><strong>New channel</strong> (no <spanx style="verb">channelId</spanx>): Client generates a
random salt locally, computes <spanx style="verb">channelId</spanx> using the
formula in <xref target="channel-state"/>, opens the channel
on-chain, and returns the <spanx style="verb">channelId</spanx> in the
credential.</t>
  <t><strong>Existing channel</strong> (<spanx style="verb">channelId</spanx> provided): Client
<bcp14>MUST</bcp14> verify
<spanx style="verb">channel.deposit - channel.settled &gt;= amount</spanx> before
resuming. If insufficient, client <bcp14>SHOULD</bcp14> either call
<spanx style="verb">topUp()</spanx> with the difference or open a new channel.</t>
</list></t>

<t>Servers <bcp14>MAY</bcp14> cache
<spanx style="verb">(payer address, payee address, token) -&gt; channelId</spanx>
mappings to suggest channel reuse, reducing on-chain
transactions.</t>

<t><strong>Example (new channel):</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "amount": "25",
  "unitType": "llm_token",
  "suggestedDeposit": "10000000",
  "currency": "0x000000000000000000000000000000000006f89a",
  "recipient": "0x742d35cc6634c0532925a3b844bc9e7595f8fe00",
  "methodDetails": {
    "escrowContract":
      "0x8Aaf6690C2a6397d595F97E224fC19759De6fdaE",
    "chainId": 295
  }
}
]]></sourcecode></figure>

<t>This requests a price of 0.000025 USDC per LLM token,
with a suggested deposit of 10.00 USDC (10000000 base
units). The <spanx style="verb">currency</spanx> is Circle USDC on Hedera mainnet
(HTS token 0.0.456858, exposed as ERC-20 via HIP-218).</t>

<t><strong>Example (existing channel):</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "amount": "25",
  "unitType": "llm_token",
  "currency": "0x000000000000000000000000000000000006f89a",
  "recipient": "0x742d35cc6634c0532925a3b844bc9e7595f8fe00",
  "methodDetails": {
    "escrowContract":
      "0x8Aaf6690C2a6397d595F97E224fC19759De6fdaE",
    "channelId":
      "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b"
      "1f6a9c1b3e2d4a5b6c7d8e9f",
    "chainId": 295
  }
}
]]></sourcecode></figure>

<t>For existing channels, <spanx style="verb">suggestedDeposit</spanx> is omitted
since the channel already has funds. The <spanx style="verb">channelId</spanx>
tells the client to resume this channel.</t>

</section>
</section>
<section anchor="fee-payment"><name>Fee Payment</name>

<section anchor="client-paid-fees-default"><name>Client-Paid Fees (Default)</name>

<t>In this version, the client pays all transaction fees for
channel operations (<spanx style="verb">open</spanx>, <spanx style="verb">topUp</spanx>, ERC-20 <spanx style="verb">approve</spanx>).
The client broadcasts these transactions directly via
Hashio JSON-RPC.</t>

<t>Hedera's EVM layer has predictable, low transaction fees.
However, HTS precompile interactions require higher gas
limits than standard ERC-20 operations:</t>

<texttable>
      <ttcol align='left'>Operation</ttcol>
      <ttcol align='left'>Recommended Gas Limit</ttcol>
      <c>ERC-20 <spanx style="verb">approve</spanx> (HTS)</c>
      <c>1,000,000</c>
      <c><spanx style="verb">open</spanx></c>
      <c>1,500,000</c>
      <c><spanx style="verb">topUp</spanx></c>
      <c>1,500,000</c>
      <c><spanx style="verb">settle</spanx></c>
      <c>1,500,000</c>
      <c><spanx style="verb">close</spanx></c>
      <c>1,500,000</c>
</texttable>

<t>Clients <bcp14>MUST</bcp14> set gas limits appropriate for HTS
precompile operations. The default gas estimates from
Hashio JSON-RPC may be insufficient.</t>

</section>
<section anchor="server-initiated-operations"><name>Server-Initiated Operations</name>

<t>The <spanx style="verb">settle</spanx> and <spanx style="verb">close</spanx> contract functions are
server-originated on-chain transactions. The server pays
transaction fees for these operations:</t>

<t><list style="symbols">
  <t><strong>Voucher updates</strong> (<spanx style="verb">action="voucher"</spanx>) are off-chain
and incur no transaction fees.</t>
  <t><strong>Settlement</strong> (<spanx style="verb">settle()</spanx>) and channel <strong>close</strong>
(<spanx style="verb">close()</spanx>) are initiated by the server using the
highest valid voucher. The server covers the fees.</t>
  <t>Servers <bcp14>MAY</bcp14> recover settlement costs through pricing
or other business logic.</t>
</list></t>

</section>
<section anchor="fee-delegation"><name>Fee Delegation (Future)</name>

<t>Hedera natively supports fee delegation via the
<spanx style="verb">feePayerAccountId</spanx> field on transactions. A future
revision of this specification <bcp14>MAY</bcp14> add <spanx style="verb">feePayer</spanx> support
to <spanx style="verb">methodDetails</spanx>, enabling the server to pay
transaction fees on behalf of the client. This would pair
naturally with a pull-mode open flow where the client
signs the transaction and the server broadcasts it.</t>

</section>
</section>
<section anchor="credential-schema"><name>Credential Schema</name>

<t>The credential in the <spanx style="verb">Authorization</spanx> header contains a
base64url-encoded JSON object per
<xref target="I-D.httpauth-payment"/>.</t>

<section anchor="credential-structure"><name>Credential Structure</name>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">challenge</spanx></c>
      <c>object</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Echo of the challenge parameters</c>
      <c><spanx style="verb">payload</spanx></c>
      <c>object</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Session-specific payload</c>
</texttable>

<t>Implementations <bcp14>MUST</bcp14> ignore unknown fields in credential
payloads, request objects, and receipts to allow
forward-compatible extensions.</t>

</section>
<section anchor="credential-lifecycle"><name>Credential Lifecycle</name>

<t>A streaming payment session progresses through distinct
phases, each corresponding to a payload action:</t>

<t><list style="numbers" type="1">
  <t><strong>Open</strong>: Client deposits funds on-chain (broadcasting
the transaction directly) and presents the <spanx style="verb">open</spanx>
action with the transaction hash. The server verifies
the on-chain deposit and validates the initial
voucher.</t>
  <t><strong>Streaming</strong>: Client submits <spanx style="verb">voucher</spanx> actions with
increasing cumulative amounts as service is consumed.
The server may periodically settle vouchers on-chain.</t>
  <t><strong>Close</strong>: Client sends the <spanx style="verb">close</spanx> action with the
final voucher. The server settles on-chain and
returns a receipt.</t>
</list></t>

<t>Each action carries action-specific fields directly in
the <spanx style="verb">payload</spanx> object, with the <spanx style="verb">action</spanx> field
discriminating between phases.</t>

</section>
<section anchor="payload-actions"><name>Payload Actions</name>

<t>The <spanx style="verb">payload</spanx> object uses an <spanx style="verb">action</spanx> discriminator with
action-specific fields at the same level:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">action</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>One of the actions below</c>
</texttable>

<texttable>
      <ttcol align='left'>Action</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">open</spanx></c>
      <c>Confirms channel is open on-chain</c>
      <c><spanx style="verb">topUp</spanx></c>
      <c>Adds funds to an existing channel</c>
      <c><spanx style="verb">voucher</spanx></c>
      <c>Submits updated cumulative voucher</c>
      <c><spanx style="verb">close</spanx></c>
      <c>Requests server to close channel</c>
</texttable>

<section anchor="open-payload"><name>Open Payload</name>

<t>The <spanx style="verb">open</spanx> action confirms an on-chain channel opening
and begins the streaming session. Unlike the Tempo
session where the client sends a signed transaction for
server broadcast, the Hedera client broadcasts the
<spanx style="verb">open()</spanx> transaction itself and presents the transaction
hash.</t>

<t><strong>Payload fields (in addition to <spanx style="verb">action</spanx>):</strong></t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel identifier (hex bytes32)</c>
      <c><spanx style="verb">txHash</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Transaction hash from open()</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Initial authorized amount (see below)</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>EIP-712 voucher signature</c>
</texttable>

<t>The client broadcasts the <spanx style="verb">open()</spanx> transaction via
Hashio JSON-RPC, waits for the transaction receipt, and
presents the <spanx style="verb">txHash</spanx> for server verification.</t>

<t>The server uses the <spanx style="verb">txHash</spanx> to verify the on-chain
channel state: deposit amount, payee, token, and that
the channel is not finalized.</t>

<t>The initial voucher (<spanx style="verb">cumulativeAmount</spanx> and <spanx style="verb">signature</spanx>)
proves the client controls the signing key and
establishes the voucher chain. Implementations <bcp14>MAY</bcp14> set
<spanx style="verb">cumulativeAmount</spanx> to zero or to the first request's
cost; both are valid starting points for the
cumulative voucher sequence.</t>

<t><strong>Example:</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "open",
    "channelId":
      "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
      "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "txHash":
      "0x1a2b3c4d5e6f7890abcdef12345678"
      "90abcdef1234567890abcdef12345678",
    "cumulativeAmount": "2500",
    "signature": "0xabcdef1234567890..."
  }
}
]]></sourcecode></figure>

<t>Note: <spanx style="verb">cumulativeAmount</spanx> here is <spanx style="verb">"2500"</spanx> (the cost
of the first request at 25 base units per token for
100 tokens). Implementations <bcp14>MAY</bcp14> also send <spanx style="verb">"0"</spanx>.</t>

<t>The <spanx style="verb">challenge</spanx> object <bcp14>MUST</bcp14> echo the challenge
parameters from the server's <spanx style="verb">WWW-Authenticate</spanx> header
per <xref target="I-D.httpauth-payment"/>.</t>

</section>
<section anchor="topup-payload"><name>TopUp Payload</name>

<t>The <spanx style="verb">topUp</spanx> action adds funds to an existing channel
during a streaming session. The client broadcasts the
<spanx style="verb">topUp()</spanx> transaction itself and presents the
transaction hash.</t>

<t>Clients <bcp14>MUST</bcp14> include a <spanx style="verb">challenge</spanx> object in the Payment
credential for <spanx style="verb">topUp</spanx> actions. To obtain a challenge
for a top-up outside an active streaming response,
clients <bcp14>MAY</bcp14> send a <spanx style="verb">HEAD</spanx> request to the protected
resource; the server returns 402 with a
<spanx style="verb">WWW-Authenticate</spanx> challenge (no body). Servers <bcp14>MUST</bcp14>
reject <spanx style="verb">topUp</spanx> actions referencing an unknown or expired
challenge <spanx style="verb">id</spanx> with problem type <spanx style="verb">challenge-not-found</spanx>.</t>

<t><strong>Payload fields (in addition to <spanx style="verb">action</spanx>):</strong></t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel ID</c>
      <c><spanx style="verb">txHash</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Transaction hash from topUp()</c>
      <c><spanx style="verb">additionalDeposit</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Additional amount in base units</c>
</texttable>

<t><strong>Example:</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "topUp",
    "channelId":
      "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
      "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "txHash":
      "0x2b3c4d5e6f7890abcdef1234567890ab"
      "cdef1234567890abcdef1234567890ab",
    "additionalDeposit": "5000000"
  }
}
]]></sourcecode></figure>

<t>Upon successful verification, the server updates the
channel's available balance. The new deposit is
immediately available for voucher authorization.</t>

</section>
<section anchor="voucher-payload"><name>Voucher Payload</name>

<t>The <spanx style="verb">voucher</spanx> action submits an updated cumulative
voucher during streaming.</t>

<t><strong>Payload fields (in addition to <spanx style="verb">action</spanx>):</strong></t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel identifier</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Cumulative amount authorized</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>EIP-712 voucher signature</c>
</texttable>

<t><strong>Example:</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "voucher",
    "channelId":
      "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
      "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "cumulativeAmount": "250000",
    "signature": "0xabcdef1234567890..."
  }
}
]]></sourcecode></figure>

</section>
<section anchor="close-payload"><name>Close Payload</name>

<t>The <spanx style="verb">close</spanx> action requests the server to close the
channel and settle on-chain.</t>

<t><strong>Payload fields (in addition to <spanx style="verb">action</spanx>):</strong></t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel identifier</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Final cumulative amount</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>EIP-712 voucher signature</c>
</texttable>

<t>The server uses the voucher fields to call
<spanx style="verb">close(channelId, cumulativeAmount, signature)</spanx> on-chain
via Hashio JSON-RPC.</t>

<t><strong>Example:</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "close",
    "channelId":
      "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
      "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "cumulativeAmount": "500000",
    "signature": "0xabcdef1234567890..."
  }
}
]]></sourcecode></figure>

</section>
</section>
</section>
<section anchor="voucher-format"><name>Voucher Signing Format</name>

<t>Vouchers use typed structured data signing compatible
with <xref target="EIP-712"/>. This section normatively defines the
signing procedure; <xref target="EIP-712"/> is referenced for
background only.</t>

<section anchor="wire-format"><name>Wire Format</name>

<t>Voucher fields are placed directly in the credential
<spanx style="verb">payload</spanx> object (alongside <spanx style="verb">action</spanx>) rather than in a
nested structure:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel ID (hex bytes32)</c>
      <c><spanx style="verb">cumulativeAmount</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Cumulative amount (decimal)</c>
      <c><spanx style="verb">signature</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>EIP-712 signature (hex)</c>
</texttable>

<t>The EIP-712 domain and type definitions are fixed by
this specification. Implementations <bcp14>MUST</bcp14> reconstruct the
full typed data structure using the domain parameters
from the challenge (<spanx style="verb">chainId</spanx>, <spanx style="verb">escrowContract</spanx>) before
signature verification.</t>

</section>
<section anchor="type-definitions"><name>Type Definitions</name>

<t>The <spanx style="verb">types</spanx> object <bcp14>MUST</bcp14> contain exactly:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "Voucher": [
    { "name": "channelId", "type": "bytes32" },
    {
      "name": "cumulativeAmount",
      "type": "uint128"
    }
  ]
}
]]></sourcecode></figure>

<t>Note: The <spanx style="verb">EIP712Domain</spanx> type is implicit per EIP-712
and <bcp14>SHOULD NOT</bcp14> be included in the <spanx style="verb">types</spanx> object.</t>

</section>
<section anchor="domain-separator"><name>Domain Separator</name>

<t>The <spanx style="verb">domain</spanx> object <bcp14>MUST</bcp14> contain:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Value</ttcol>
      <c><spanx style="verb">name</spanx></c>
      <c>string</c>
      <c><spanx style="verb">"Hedera Stream Channel"</spanx></c>
      <c><spanx style="verb">version</spanx></c>
      <c>string</c>
      <c><spanx style="verb">"1"</spanx></c>
      <c><spanx style="verb">chainId</spanx></c>
      <c>number</c>
      <c>Hedera chain ID (295 or 296)</c>
      <c><spanx style="verb">verifyingContract</spanx></c>
      <c>string</c>
      <c>Escrow contract address</c>
</texttable>

</section>
<section anchor="signing-procedure"><name>Signing Procedure</name>

<t>To sign a voucher, implementations <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Construct the domain separator hash:  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
domainSeparator = keccak256(
  abi.encode(
    keccak256(
      "EIP712Domain(string name,"
      "string version,"
      "uint256 chainId,"
      "address verifyingContract)"
    ),
    keccak256(bytes(name)),
    keccak256(bytes(version)),
    chainId,
    verifyingContract
  )
)
]]></artwork></figure>
  </t>
  <t>Construct the struct hash:  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
structHash = keccak256(
  abi.encode(
    keccak256(
      "Voucher(bytes32 channelId,"
      "uint128 cumulativeAmount)"
    ),
    channelId,
    cumulativeAmount
  )
)
]]></artwork></figure>
  </t>
  <t>Compute the signing hash:  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
signingHash = keccak256(
  "\x19\x01" || domainSeparator || structHash
)
]]></artwork></figure>
  </t>
  <t>Sign with ECDSA using secp256k1 curve</t>
  <t>Encode signature as 65-byte <spanx style="verb">r || s || v</spanx> where
<spanx style="verb">v</spanx> is 27 or 28</t>
</list></t>

</section>
<section anchor="cumulative-semantics"><name>Cumulative Semantics</name>

<t>Vouchers specify cumulative totals, not incremental
deltas:</t>

<t><list style="symbols">
  <t>Voucher #1: <spanx style="verb">cumulativeAmount = 100</spanx> (100 total)</t>
  <t>Voucher #2: <spanx style="verb">cumulativeAmount = 250</spanx> (250 total)</t>
  <t>Voucher #3: <spanx style="verb">cumulativeAmount = 400</spanx> (400 total)</t>
</list></t>

<t>When settling, the contract computes:
<spanx style="verb">delta = cumulativeAmount - settled</spanx></t>

</section>
</section>
<section anchor="verification-procedure"><name>Verification Procedure</name>

<section anchor="open-verification"><name>Open Verification</name>

<t>On <spanx style="verb">action="open"</spanx>, servers <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t><strong>Transaction verification</strong>: Wait for the
transaction receipt using <spanx style="verb">txHash</spanx>. Verify the
transaction succeeded (receipt status = <spanx style="verb">success</spanx>).</t>
  <t><strong>On-chain state verification</strong>: Query the escrow
contract's <spanx style="verb">getChannel(channelId)</spanx> to verify:
  <list style="symbols">
      <t>Channel exists (deposit &gt; 0)</t>
      <t><spanx style="verb">channel.payee</spanx> matches server's address</t>
      <t><spanx style="verb">channel.token</spanx> matches <spanx style="verb">request.currency</spanx></t>
      <t><spanx style="verb">channel.deposit - channel.settled &gt;= amount</spanx></t>
      <t>Channel is not finalized</t>
      <t><spanx style="verb">channel.closeRequestedAt == 0</spanx></t>
    </list></t>
  <t><strong>Voucher verification</strong>: If <spanx style="verb">cumulativeAmount</spanx> and
<spanx style="verb">signature</spanx> are provided, verify the initial voucher:
  <list style="symbols">
      <t>Recover signer from EIP-712 signature</t>
      <t>Verify canonical low-s values</t>
      <t>Signer matches <spanx style="verb">channel.payer</spanx> or
<spanx style="verb">channel.authorizedSigner</spanx></t>
      <t><spanx style="verb">voucher.channelId</spanx> matches</t>
      <t><spanx style="verb">voucher.cumulativeAmount &gt;= channel.settled</spanx></t>
    </list></t>
  <t><strong>Initialize</strong> server-side channel state</t>
</list></t>

</section>
<section anchor="topup-verification"><name>TopUp Verification</name>

<t>On <spanx style="verb">action="topUp"</spanx>, servers <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t><strong>Transaction verification</strong>: Wait for the
transaction receipt using <spanx style="verb">txHash</spanx>. Verify the
transaction succeeded.</t>
  <t><strong>On-chain state verification</strong>: Query the escrow
contract to verify:
  <list style="symbols">
      <t><spanx style="verb">channel.deposit</spanx> increased</t>
      <t>Channel is not finalized</t>
    </list></t>
  <t><strong>Update</strong> server-side accounting: increase
available balance by <spanx style="verb">additionalDeposit</spanx>.</t>
</list></t>

</section>
<section anchor="voucher-verification"><name>Voucher Verification</name>

<t>On <spanx style="verb">action="voucher"</spanx>, servers <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Verify voucher signature using EIP-712 recovery</t>
  <t>Verify canonical low-s values (see
<xref target="signature-malleability"/>)</t>
  <t>Recover signer and <bcp14>MUST</bcp14> verify it matches expected
signer from on-chain state</t>
  <t>Verify <spanx style="verb">channel.closeRequestedAt == 0</spanx>. Servers
<bcp14>MUST</bcp14> reject vouchers on channels with a pending
forced close.</t>
  <t>Verify monotonicity:
  <list style="symbols">
      <t><spanx style="verb">cumulativeAmount &gt; highestVoucherAmount</spanx></t>
      <t><spanx style="verb">(cumulativeAmount - highestVoucherAmount) &gt;=
minVoucherDelta</spanx></t>
    </list></t>
  <t>Verify <spanx style="verb">cumulativeAmount &lt;= channel.deposit</spanx></t>
  <t>Persist voucher to durable storage before providing
service</t>
  <t>Update <spanx style="verb">highestVoucherAmount = cumulativeAmount</spanx></t>
</list></t>

<t>Servers <bcp14>MUST</bcp14> derive the expected signer from on-chain
channel state by querying the escrow contract. The
expected signer is <spanx style="verb">channel.authorizedSigner</spanx> if
non-zero, otherwise <spanx style="verb">channel.payer</spanx>. Servers <bcp14>MUST NOT</bcp14>
trust signer claims in HTTP payloads.</t>

<t>Servers <bcp14>MUST</bcp14> persist the highest voucher to durable
storage before providing the corresponding service.
Failure to do so may result in unrecoverable fund loss
if the server crashes after service delivery.</t>

</section>
<section anchor="idempotency"><name>Idempotency</name>

<t>Servers <bcp14>MUST</bcp14> treat voucher submissions idempotently:</t>

<t><list style="symbols">
  <t>Resubmitting a voucher with the same
<spanx style="verb">cumulativeAmount</spanx> as the highest accepted <bcp14>MUST</bcp14>
return 200 OK with the current <spanx style="verb">highestAmount</spanx></t>
  <t>Submitting a voucher with lower <spanx style="verb">cumulativeAmount</spanx>
than highest accepted <bcp14>MUST</bcp14> return 200 OK with the
current <spanx style="verb">highestAmount</spanx> (not an error)</t>
  <t>Clients <bcp14>MAY</bcp14> safely retry voucher submissions after
network failures</t>
</list></t>

</section>
<section anchor="error-responses"><name>Rejection and Error Responses</name>

<t>If verification fails, servers <bcp14>MUST</bcp14> return an
appropriate HTTP status code with a Problem Details
<xref target="RFC9457"/> response body:</t>

<texttable>
      <ttcol align='left'>Status</ttcol>
      <ttcol align='left'>When</ttcol>
      <c>400 Bad Request</c>
      <c>Malformed payload or missing fields</c>
      <c>402 Payment Required</c>
      <c>Invalid signature or signer mismatch</c>
      <c>410 Gone</c>
      <c>Channel finalized or not found</c>
</texttable>

<t>Error responses use Problem Details format:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "type":
    "https://paymentauth.org/problems/"
    "session/invalid-signature",
  "title": "Invalid Signature",
  "status": 402,
  "detail": "Voucher signature could not "
    "be verified",
  "channelId": "0x6d0f4fdf..."
}
]]></sourcecode></figure>

<t>Problem type URIs:</t>

<texttable>
      <ttcol align='left'>Type URI</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">.../session/invalid-signature</spanx></c>
      <c>Voucher signature invalid</c>
      <c><spanx style="verb">.../session/signer-mismatch</spanx></c>
      <c>Signer not authorized</c>
      <c><spanx style="verb">.../session/amount-exceeds-deposit</spanx></c>
      <c>Exceeds deposit</c>
      <c><spanx style="verb">.../session/delta-too-small</spanx></c>
      <c>Below minVoucherDelta</c>
      <c><spanx style="verb">.../session/channel-not-found</spanx></c>
      <c>No such channel</c>
      <c><spanx style="verb">.../session/channel-finalized</spanx></c>
      <c>Channel closed</c>
      <c><spanx style="verb">.../session/challenge-not-found</spanx></c>
      <c>Challenge expired</c>
      <c><spanx style="verb">.../session/insufficient-balance</spanx></c>
      <c>Insufficient balance</c>
</texttable>

<t>All problem type URIs above are prefixed with
<spanx style="verb">https://paymentauth.org/problems</spanx>.</t>

<t>For errors on the Payment Auth protected resource,
servers <bcp14>MUST</bcp14> return 402 with a fresh
<spanx style="verb">WWW-Authenticate: Payment</spanx> challenge per
<xref target="I-D.httpauth-payment"/>.</t>

</section>
</section>
<section anchor="server-accounting"><name>Server-Side Accounting</name>

<t>Servers <bcp14>MUST</bcp14> maintain per-session accounting state to
track authorized funds versus consumed service.</t>

<section anchor="accounting-state"><name>Accounting State</name>

<t>For each active session identified by
<spanx style="verb">(challengeId, channelId)</spanx>, servers <bcp14>MUST</bcp14> maintain:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">acceptedCumulative</spanx></c>
      <c>uint128</c>
      <c>Highest valid voucher accepted</c>
      <c><spanx style="verb">spent</spanx></c>
      <c>uint128</c>
      <c>Cumulative amount charged</c>
      <c><spanx style="verb">settledOnChain</spanx></c>
      <c>uint128</c>
      <c>Last settled amount (informational)</c>
</texttable>

<t>The <spanx style="verb">available</spanx> balance is computed as:</t>

<figure><artwork><![CDATA[
available = acceptedCumulative - spent
]]></artwork></figure>

</section>
<section anchor="per-request-processing"><name>Per-Request Processing</name>

<t>For each request carrying a Payment credential with
<spanx style="verb">intent="session"</spanx>, servers <bcp14>MUST</bcp14> follow this procedure:</t>

<t><list style="numbers" type="1">
  <t><strong>Voucher acceptance</strong> (if provided in credential):
  <list style="symbols">
      <t>Verify signature and monotonicity per
<xref target="voucher-verification"/></t>
      <t>If valid, persist the new <spanx style="verb">acceptedCumulative</spanx></t>
      <t>If invalid, return 402 with a fresh challenge</t>
    </list></t>
  <t><strong>Balance check</strong>:
  <list style="symbols">
      <t>Compute <spanx style="verb">available = acceptedCumulative - spent</spanx></t>
      <t>Compute <spanx style="verb">cost</spanx> for this request</t>
      <t>If <spanx style="verb">available &lt; cost</spanx>: return 402 with Problem
Details including
<spanx style="verb">requiredTopUp = cost - available</spanx></t>
    </list></t>
  <t><strong>Charge and deliver</strong> (if <spanx style="verb">available &gt;= cost</spanx>):
  <list style="symbols">
      <t><strong><bcp14>MUST</bcp14> persist</strong> <spanx style="verb">spent := spent + cost</spanx> BEFORE
or atomically with delivering service</t>
      <t>Deliver the response (or next chunk for streaming)</t>
      <t>Return <spanx style="verb">Payment-Receipt</spanx> header</t>
    </list></t>
  <t><strong>Receipt generation</strong>:
  <list style="symbols">
      <t>Include balance state in receipt</t>
    </list></t>
</list></t>

</section>
<section anchor="crash-safety"><name>Crash Safety</name>

<t>To prevent fund loss from server crashes:</t>

<t><list style="symbols">
  <t>Servers <bcp14>MUST</bcp14> persist <spanx style="verb">spent</spanx> increments BEFORE
delivering corresponding service.</t>
  <t>Servers <bcp14>MUST</bcp14> persist <spanx style="verb">acceptedCumulative</spanx> BEFORE
relying on the new balance for service authorization.</t>
  <t>Implementations <bcp14>SHOULD</bcp14> use transactional storage or
write-ahead logging to ensure atomicity.</t>
</list></t>

</section>
<section anchor="request-idempotency"><name>Request Idempotency</name>

<t>To prevent double-charging on retries:</t>

<t><list style="symbols">
  <t>Clients <bcp14>SHOULD</bcp14> include an <spanx style="verb">Idempotency-Key</spanx> header</t>
  <t>Servers <bcp14>SHOULD</bcp14> track <spanx style="verb">(challengeId, idempotencyKey)</spanx>
pairs and return cached responses for duplicates</t>
  <t>Servers <bcp14>MUST NOT</bcp14> increment <spanx style="verb">spent</spanx> for duplicate
idempotent requests</t>
</list></t>

<t><strong>Example idempotent request:</strong></t>

<figure><sourcecode type="http"><![CDATA[
GET /api/chat HTTP/1.1
Host: api.example.com
Idempotency-Key: req_a1b2c3d4e5f6
Authorization: Payment eyJ...
]]></sourcecode></figure>

</section>
<section anchor="cost-calculation"><name>Cost Calculation</name>

<t>The <spanx style="verb">cost</spanx> for a request depends on the pricing model
declared in the challenge. Servers <bcp14>MUST</bcp14> support at least
one of:</t>

<t><list style="symbols">
  <t><strong>Fixed cost</strong>: A predetermined amount per request</t>
  <t><strong>Usage-based fees</strong>: Pricing proportional to resource
consumption</t>
</list></t>

<t>For streaming responses (SSE, chunked), servers <bcp14>SHOULD</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Reserve an estimated cost before starting delivery</t>
  <t>Adjust <spanx style="verb">spent</spanx> as actual consumption is measured</t>
  <t>Pause delivery if <spanx style="verb">available</spanx> is exhausted</t>
</list></t>

</section>
<section anchor="insufficient-balance-during-streaming"><name>Insufficient Balance During Streaming</name>

<t>When a streaming response exhausts <spanx style="verb">available</spanx> balance:</t>

<t><list style="numbers" type="1">
  <t>Server <bcp14>MUST</bcp14> stop delivering additional content</t>
  <t>Server <bcp14>MAY</bcp14> hold the connection open awaiting a
voucher top-up</t>
  <t>Server <bcp14>MAY</bcp14> close the response; client retries with
a higher voucher</t>
  <t>If client submits a voucher update, server <bcp14>SHOULD</bcp14>
resume delivery if the connection is still open</t>
</list></t>

<t>For SSE responses, servers <bcp14>MUST</bcp14> emit a
<spanx style="verb">payment-need-voucher</spanx> event when balance is exhausted:</t>

<figure><artwork><![CDATA[
event: payment-need-voucher
data: {"channelId":"0x6d0f4fdf...",
  "requiredCumulative":"250025",
  "acceptedCumulative":"250000",
  "deposit":"500000"}
]]></artwork></figure>

<t>The <spanx style="verb">payment-need-voucher</spanx> event data <bcp14>MUST</bcp14> be a JSON
object containing:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Required</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">acceptedCumulative</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Current highest voucher</c>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Channel identifier</c>
      <c><spanx style="verb">deposit</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Current on-chain deposit</c>
      <c><spanx style="verb">requiredCumulative</spanx></c>
      <c>string</c>
      <c><bcp14>REQUIRED</bcp14></c>
      <c>Minimum next voucher</c>
</texttable>

<t>The <spanx style="verb">deposit</spanx> field allows the client to determine the
correct recovery action. When <spanx style="verb">requiredCumulative</spanx>
exceeds <spanx style="verb">deposit</spanx>, the client <bcp14>MUST</bcp14> submit
<spanx style="verb">action="topUp"</spanx> before sending a new voucher. When
<spanx style="verb">requiredCumulative</spanx> is within <spanx style="verb">deposit</spanx>, the client
can submit <spanx style="verb">action="voucher"</spanx> directly.</t>

<t>After emitting <spanx style="verb">payment-need-voucher</spanx>, the server <bcp14>MUST</bcp14>
pause delivery until a valid voucher is accepted.
Servers <bcp14>SHOULD</bcp14> close the stream if no voucher is
received within a reasonable timeout (e.g., 60 seconds).</t>

<t>Servers <bcp14>SHOULD NOT</bcp14> deliver service beyond the authorized
balance under any circumstances. See
<xref target="dos-mitigation"/> for rate limiting requirements.</t>

</section>
</section>
<section anchor="settlement-procedure"><name>Settlement Procedure</name>

<section anchor="settlement-timing"><name>Settlement Timing</name>

<t>Servers <bcp14>MAY</bcp14> settle at any time using their own criteria:</t>

<t><list style="symbols">
  <t>Periodically (e.g., every N seconds or M base units)</t>
  <t>When <spanx style="verb">action="close"</spanx> is received</t>
  <t>When accumulated unsettled amount exceeds a threshold</t>
  <t>Based on gas cost optimization</t>
</list></t>

<t>Settlement frequency is an implementation detail left to
servers.</t>

<t>The <spanx style="verb">close()</spanx> function settles any delta between the
provided <spanx style="verb">cumulativeAmount</spanx> and <spanx style="verb">channel.settled</spanx>. If
the server has already settled the highest voucher via
<spanx style="verb">settle()</spanx>, calling <spanx style="verb">close()</spanx> with the same amount will
only refund the payer the remaining deposit.</t>

</section>
<section anchor="cooperative-close"><name>Cooperative Close</name>

<t>When the client sends <spanx style="verb">action="close"</spanx>:</t>

<t><list style="numbers" type="1">
  <t>Server receives the signed close request</t>
  <t>Server calls
<spanx style="verb">close(channelId, cumulativeAmount, signature)</spanx>
on-chain via Hashio JSON-RPC</t>
  <t>Contract settles any delta and refunds remainder</t>
  <t>Server returns receipt with transaction hash</t>
</list></t>

<t>Servers <bcp14>SHOULD</bcp14> close promptly when clients request --
the economic incentive is to claim earned funds
immediately.</t>

<t>The server <bcp14>MUST</bcp14> set a gas limit of at least 1,500,000
for the <spanx style="verb">close()</spanx> call due to HTS precompile overhead.</t>

</section>
<section anchor="forced-close"><name>Forced Close</name>

<t>If the server does not respond to close requests:</t>

<t><list style="numbers" type="1">
  <t>Client calls <spanx style="verb">requestClose(channelId)</spanx> on-chain</t>
  <t>15-minute grace period begins</t>
  <t>Server can still <spanx style="verb">settle()</spanx> or <spanx style="verb">close()</spanx> during
the grace period</t>
  <t>After grace period, client calls
<spanx style="verb">withdraw(channelId)</spanx></t>
  <t>Client receives all remaining (unsettled) funds</t>
</list></t>

<t>Clients <bcp14>SHOULD</bcp14> wait at least 16 minutes after
<spanx style="verb">requestClose()</spanx> before calling <spanx style="verb">withdraw()</spanx> to account
for block time variance.</t>

</section>
<section anchor="sequential-sessions"><name>Sequential Sessions</name>

<t>A single channel supports sequential sessions. Each
session uses the same cumulative voucher counter. When a
new session begins on a channel, the previous session's
spending state is irrelevant -- the channel's
<spanx style="verb">highestVoucherAmount</spanx> is the source of truth for the
next voucher's minimum value.</t>

</section>
<section anchor="voucher-submission-transport"><name>Voucher Submission Transport</name>

<t>Vouchers are submitted via HTTP requests to the <strong>same
resource URI</strong> that requires payment. There is no
separate session endpoint. Clients <bcp14>SHOULD</bcp14> use HTTP/2
multiplexing or maintain separate connections for voucher
updates and content streaming when topping up during a
long-lived response.</t>

<t>For voucher-only updates (no response body needed),
clients <bcp14>MAY</bcp14> use <spanx style="verb">HEAD</spanx> requests. Servers <bcp14>SHOULD</bcp14> support
voucher credentials on <spanx style="verb">HEAD</spanx> requests for resources
that require session payment.</t>

</section>
<section anchor="receipt-generation"><name>Receipt Generation</name>

<t>Servers <bcp14>MUST</bcp14> return a <spanx style="verb">Payment-Receipt</spanx> header on
<strong>every successful paid request</strong>. For streaming
responses (SSE, chunked transfer), servers <bcp14>MUST</bcp14> include
the receipt in the initial response headers AND in the
final message of the stream.</t>

<t>For SSE responses, the final receipt <bcp14>SHOULD</bcp14> be delivered
as an event:</t>

<figure><artwork><![CDATA[
event: payment-receipt
data: {"method":"hedera","intent":"session",
  "status":"success",...}
]]></artwork></figure>

<t>The session intent extends the receipt with balance
tracking:</t>

<texttable>
      <ttcol align='left'>Field</ttcol>
      <ttcol align='left'>Type</ttcol>
      <ttcol align='left'>Description</ttcol>
      <c><spanx style="verb">method</spanx></c>
      <c>string</c>
      <c><spanx style="verb">"hedera"</spanx></c>
      <c><spanx style="verb">intent</spanx></c>
      <c>string</c>
      <c><spanx style="verb">"session"</spanx></c>
      <c><spanx style="verb">status</spanx></c>
      <c>string</c>
      <c><spanx style="verb">"success"</spanx></c>
      <c><spanx style="verb">timestamp</spanx></c>
      <c>string</c>
      <c><xref target="RFC3339"/> response time</c>
      <c><spanx style="verb">challengeId</spanx></c>
      <c>string</c>
      <c>Challenge identifier</c>
      <c><spanx style="verb">channelId</spanx></c>
      <c>string</c>
      <c>Channel identifier</c>
      <c><spanx style="verb">acceptedCumulative</spanx></c>
      <c>string</c>
      <c>Highest voucher accepted</c>
      <c><spanx style="verb">spent</spanx></c>
      <c>string</c>
      <c>Total charged so far</c>
      <c><spanx style="verb">reference</spanx></c>
      <c>string</c>
      <c>Transaction or channel ref</c>
      <c><spanx style="verb">units</spanx></c>
      <c>number</c>
      <c><bcp14>OPTIONAL</bcp14>: Units consumed</c>
      <c><spanx style="verb">txHash</spanx></c>
      <c>string</c>
      <c><bcp14>OPTIONAL</bcp14>: Transaction hash</c>
</texttable>

<t>The <spanx style="verb">reference</spanx> field satisfies the core MPP receipt
<spanx style="verb">reference</spanx> requirement. It is set to <spanx style="verb">txHash</spanx> when a
transaction was broadcast (open, close), otherwise
set to <spanx style="verb">channelId</spanx> (voucher).</t>

<t>The <spanx style="verb">txHash</spanx> field is <bcp14>OPTIONAL</bcp14> because not every
response involves an on-chain settlement -- voucher
updates are off-chain.</t>

<t><strong>Example receipt (per-request with metering):</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "method": "hedera",
  "intent": "session",
  "status": "success",
  "timestamp": "2026-04-12T12:08:30Z",
  "challengeId": "c_8d0e3b5a9f2c1d4e",
  "channelId":
    "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
    "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
  "reference":
    "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
    "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
  "acceptedCumulative": "250000",
  "spent": "237500",
  "units": 500
}
]]></sourcecode></figure>

<t><strong>Example receipt (on close with settlement):</strong></t>

<figure><sourcecode type="json"><![CDATA[
{
  "method": "hedera",
  "intent": "session",
  "status": "success",
  "timestamp": "2026-04-12T12:10:00Z",
  "challengeId": "c_8d0e3b5a9f2c1d4e",
  "channelId":
    "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c"
    "0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
  "reference":
    "0x1a2b3c4d5e6f7890abcdef12345678"
    "90abcdef1234567890abcdef12345678",
  "acceptedCumulative": "250000",
  "spent": "250000",
  "txHash":
    "0x1a2b3c4d5e6f7890abcdef12345678"
    "90abcdef1234567890abcdef12345678"
}
]]></sourcecode></figure>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<section anchor="replay-prevention"><name>Replay Prevention</name>

<t>Vouchers are bound to a specific channel and contract
via:</t>

<t><list style="symbols">
  <t><spanx style="verb">channelId</spanx> in the voucher message</t>
  <t><spanx style="verb">verifyingContract</spanx> in EIP-712 domain</t>
  <t><spanx style="verb">chainId</spanx> in EIP-712 domain</t>
  <t>Cumulative amount semantics (can only increase)</t>
</list></t>

<t>The escrow contract enforces:</t>

<t><list style="symbols">
  <t><spanx style="verb">cumulativeAmount &gt; channel.settled</spanx> (monotonicity)</t>
  <t><spanx style="verb">cumulativeAmount &lt;= channel.deposit</spanx> (cap)</t>
</list></t>

</section>
<section anchor="no-voucher-expiry"><name>No Voucher Expiry</name>

<t>Vouchers have no <spanx style="verb">validUntil</spanx> field. This simplifies
the protocol:</t>

<t><list style="symbols">
  <t>Channels have no expiry -- closed explicitly</t>
  <t>Vouchers remain valid until the channel closes</t>
  <t>The close grace period protects against clients
disappearing</t>
</list></t>

<t><strong>Operational guidance:</strong> Servers <bcp14>SHOULD</bcp14> settle and close
channels inactive for extended periods (e.g., 30+ days).</t>

</section>
<section anchor="dos-mitigation"><name>Denial of Service</name>

<t>To mitigate voucher flooding, servers <bcp14>MUST</bcp14> implement
rate limiting:</t>

<t><list style="symbols">
  <t>Servers <bcp14>SHOULD</bcp14> limit voucher submissions to 10 per
second per session</t>
  <t>Servers <bcp14>MAY</bcp14> implement additional IP-based rate
limiting</t>
  <t>Servers <bcp14>MUST</bcp14> enforce <spanx style="verb">minVoucherDelta</spanx> when present</t>
  <t>Servers <bcp14>SHOULD</bcp14> skip expensive signature verification
for vouchers that do not advance state (return 200 OK
with current <spanx style="verb">highestAmount</spanx> per <xref target="idempotency"/>)</t>
</list></t>

<t>Servers <bcp14>SHOULD</bcp14> perform format validation before
expensive ECDSA signature recovery.</t>

<t>To mitigate channel griefing via dust deposits:</t>

<t><list style="symbols">
  <t>Servers <bcp14>SHOULD</bcp14> enforce a minimum deposit (e.g.,
1 USDC equivalent)</t>
  <t>Servers <bcp14>MAY</bcp14> reject channels below this threshold</t>
</list></t>

</section>
<section anchor="front-running-protection"><name>Front-Running Protection</name>

<t>Cumulative voucher semantics prevent front-running
attacks. If a client submits a higher voucher while a
server's <spanx style="verb">settle()</spanx> transaction is pending, the
settlement will still succeed -- it merely leaves
additional unsettled funds.</t>

</section>
<section anchor="cross-contract-replay-prevention"><name>Cross-Contract Replay Prevention</name>

<t>The EIP-712 domain includes <spanx style="verb">verifyingContract</spanx>, binding
vouchers to a specific escrow contract address.</t>

</section>
<section anchor="escrow-guarantees"><name>Escrow Guarantees</name>

<t>The escrow contract provides:</t>

<t><list style="symbols">
  <t><strong>Payer protection</strong>: Funds only withdrawn with valid
voucher signature</t>
  <t><strong>Payee protection</strong>: Deposited funds guaranteed</t>
  <t><strong>Forced close</strong>: 15-minute grace period protects
both parties</t>
</list></t>

</section>
<section anchor="authorized-signer"><name>Authorized Signer</name>

<t>The <spanx style="verb">authorizedSigner</spanx> field allows delegation of
signing authority to a hot wallet while the main wallet
only deposits funds.</t>

<t><strong>Security considerations for delegated signing:</strong></t>

<t><list style="symbols">
  <t>Clients using <spanx style="verb">authorizedSigner</spanx> delegation <bcp14>SHOULD</bcp14>
limit channel deposits to acceptable loss amounts</t>
  <t>Clients <bcp14>SHOULD</bcp14> rotate authorized signers periodically</t>
  <t>Clients <bcp14>SHOULD NOT</bcp14> reuse signers across multiple
high-value channels</t>
  <t>If the authorized signer key is compromised, an
attacker can drain the entire channel deposit</t>
</list></t>

</section>
<section anchor="signature-malleability"><name>Signature Malleability</name>

<t>ECDSA signatures are malleable: for any valid signature
<spanx style="verb">(r, s)</spanx>, the signature <spanx style="verb">(r, -s mod n)</spanx> is also valid.
To prevent signature substitution attacks,
implementations <bcp14>MUST</bcp14> enforce canonical signatures:</t>

<t><list style="symbols">
  <t>Signatures <bcp14>MUST</bcp14> use "low-s" values with
<spanx style="verb">s &lt;= secp256k1_order / 2</spanx></t>
  <t>The secp256k1 half-order is:
<spanx style="verb">0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E73</spanx>
<spanx style="verb">57A4501DDFE92F46681B20A0</spanx></t>
  <t>Servers <bcp14>MUST</bcp14> reject signatures with <spanx style="verb">s</spanx> values
exceeding this threshold</t>
</list></t>

<t>Accepted signature formats:</t>

<t><list style="symbols">
  <t>65-byte <spanx style="verb">(r, s, v)</spanx> format where <spanx style="verb">v</spanx> is 27 or 28</t>
  <t>64-byte EIP-2098 compact format</t>
</list></t>

<t>The HederaStreamChannel.sol contract uses Solady's
<spanx style="verb">SignatureCheckerLib</spanx> which enforces these requirements.</t>

</section>
<section anchor="voucher-context-and-user-experience"><name>Voucher Context and User Experience</name>

<t>The voucher message contains only <spanx style="verb">channelId</spanx> and
<spanx style="verb">cumulativeAmount</spanx>. Wallet implementations are
encouraged to:</t>

<t><list style="symbols">
  <t>Decode <spanx style="verb">channelId</spanx> components when the derivation
formula is known</t>
  <t>Display the payee address and token in human-readable
form</t>
  <t>Show cumulative vs. incremental amounts clearly</t>
</list></t>

</section>
<section anchor="session-attribution"><name>Session Attribution</name>

<t>Vouchers are bound to channels but not to specific HTTP
sessions or API requests. The <spanx style="verb">challengeId</spanx> provides
correlation across requests. Servers <bcp14>MUST</bcp14> implement
challenge-to-voucher mapping for:</t>

<t><list style="symbols">
  <t>Dispute resolution</t>
  <t>Usage accounting</t>
  <t>Audit trails</t>
</list></t>

</section>
<section anchor="session-binding"><name>Cross-Session Replay Prevention</name>

<t>Vouchers use cumulative amount semantics: each voucher
authorizes a total payment up to <spanx style="verb">cumulativeAmount</spanx>, and
the on-chain contract enforces strict monotonicity
(<spanx style="verb">cumulativeAmount &gt; channel.settled</spanx>). A voucher can
only ever advance the channel state forward.</t>

<t>A separate <spanx style="verb">sessionHash</spanx> binding is unnecessary:</t>

<t><list style="symbols">
  <t><strong>Cross-session replay is harmless</strong>: If a voucher
from session A is presented in session B, it can only
authorize funds up to the amount already committed.</t>
  <t><strong>Cross-resource replay</strong>: Vouchers authorize
cumulative payment on a channel, not access to
specific resources. Resource authorization is handled
at the application layer via <spanx style="verb">challengeId</spanx>.</t>
</list></t>

</section>
<section anchor="chain-finality"><name>Chain Finality</name>

<t>Hedera achieves asynchronous Byzantine Fault Tolerant
(aBFT) consensus with deterministic finality in
approximately 3-5 seconds <xref target="HEDERA-DOCS"/>. Once a
transaction reaches consensus, it cannot be reversed.</t>

<t>For high-value channels, servers <bcp14>SHOULD</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Re-verify channel state periodically during
long-lived sessions</t>
  <t>Monitor for <spanx style="verb">ChannelClosed</spanx> or <spanx style="verb">CloseRequested</spanx>
events</t>
  <t>Cease service delivery if the channel becomes
invalid</t>
</list></t>

</section>
<section anchor="hts-token-association"><name>HTS Token Association</name>

<t>Before an escrow contract can receive HTS tokens, it
<bcp14>MUST</bcp14> be associated with the token via the
<spanx style="verb">associateSelf()</spanx> function (see <xref target="associate-self"/>).
This is a one-time operation per token. If the escrow
contract is not associated with the payment token,
<spanx style="verb">open()</spanx> will fail with a transfer error.</t>

<t>Servers deploying escrow contracts <bcp14>MUST</bcp14> ensure the
contract is associated with all supported payment tokens
before advertising session challenges.</t>

</section>
<section anchor="gas-limit-considerations"><name>Gas Limit Considerations</name>

<t>Hedera's EVM layer routes HTS token operations through
the HTS precompile at address <spanx style="verb">0x167</spanx>. This precompile
has higher gas requirements than standard ERC-20
operations. Implementations <bcp14>MUST</bcp14> set appropriate gas
limits (see <xref target="fee-payment"/>) to avoid transaction
failures.</t>

<t>The default gas estimates from Hashio JSON-RPC
(<spanx style="verb">eth_estimateGas</spanx>) may underestimate gas for HTS
precompile calls. Implementations <bcp14>SHOULD</bcp14> use hardcoded
minimum gas limits for escrow operations.</t>

</section>
<section anchor="grace-period-rationale"><name>Grace Period Rationale</name>

<t>The 15-minute forced close grace period balances
competing concerns:</t>

<t><list style="symbols">
  <t><strong>Payer protection</strong>: Ensures timely fund recovery</t>
  <t><strong>Payee protection</strong>: Provides time to detect close
requests and submit final settlements</t>
  <t><strong>Block time variance</strong>: Allows margin for timestamp
variations</t>
</list></t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<section anchor="payment-intent-registration"><name>Payment Intent Registration</name>

<t>This document registers the following payment intent in
the "HTTP Payment Intents" registry established by
<xref target="I-D.httpauth-payment"/>:</t>

<texttable>
      <ttcol align='left'>Intent</ttcol>
      <ttcol align='left'>Methods</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Reference</ttcol>
      <c><spanx style="verb">session</spanx></c>
      <c><spanx style="verb">hedera</spanx></c>
      <c>Streaming payment channel</c>
      <c>This document</c>
</texttable>

<t>Contact: Tom Rowbotham (<eref target="mailto:tom@xeno.money">tom@xeno.money</eref>)</t>

</section>
<section anchor="problem-type-registration"><name>Problem Type Registration</name>

<t>This document registers the following problem types in
the "HTTP Problem Types" registry established by
<xref target="RFC9457"/>:</t>

<texttable>
      <ttcol align='left'>Type URI</ttcol>
      <ttcol align='left'>Title</ttcol>
      <ttcol align='left'>Status</ttcol>
      <ttcol align='left'>Ref</ttcol>
      <c><spanx style="verb">.../session/invalid-signature</spanx></c>
      <c>Invalid Signature</c>
      <c>402</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/signer-mismatch</spanx></c>
      <c>Signer Mismatch</c>
      <c>402</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/amount-exceeds-deposit</spanx></c>
      <c>Amount Exceeds Deposit</c>
      <c>402</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/delta-too-small</spanx></c>
      <c>Delta Too Small</c>
      <c>402</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/channel-not-found</spanx></c>
      <c>Channel Not Found</c>
      <c>410</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/channel-finalized</spanx></c>
      <c>Channel Finalized</c>
      <c>410</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/challenge-not-found</spanx></c>
      <c>Challenge Not Found</c>
      <c>402</c>
      <c>This document</c>
      <c><spanx style="verb">.../session/insufficient-balance</spanx></c>
      <c>Insufficient Balance</c>
      <c>402</c>
      <c>This document</c>
</texttable>

<t>All type URIs above are prefixed with
<spanx style="verb">https://paymentauth.org/problems</spanx>.</t>

<t>Each problem type is defined in <xref target="error-responses"/>.</t>

</section>
</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

    <references title='Normative References' anchor="sec-normative-references">

&RFC2119;
&RFC3339;
&RFC4648;
&RFC8174;
&RFC8259;
&RFC9110;
&RFC9111;
&RFC9457;
<reference anchor="I-D.httpauth-payment" target="https://datatracker.ietf.org/doc/draft-ietf-httpauth-payment/
">
  <front>
    <title>The 'Payment' HTTP Authentication Scheme</title>
    <author initials="J." surname="Moxey" fullname="Jake Moxey">
      <organization></organization>
    </author>
    <date year="2026" month="January"/>
  </front>
</reference>


    </references>

    <references title='Informative References' anchor="sec-informative-references">

&RFC8610;
<reference anchor="EIP-712" target="https://eips.ethereum.org/EIPS/eip-712">
  <front>
    <title>Typed structured data hashing and signing</title>
    <author initials="R." surname="Bloemen" fullname="Remco Bloemen">
      <organization></organization>
    </author>
    <date year="2017" month="September"/>
  </front>
</reference>
<reference anchor="SSE" target="https://html.spec.whatwg.org/multipage/server-sent-events.html
">
  <front>
    <title>Server-Sent Events</title>
    <author >
      <organization>WHATWG</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="HEDERA-DOCS" target="https://docs.hedera.com">
  <front>
    <title>Hedera Documentation</title>
    <author >
      <organization>Hedera</organization>
    </author>
    <date year="2026"/>
  </front>
</reference>
<reference anchor="HIP-218" target="https://hips.hedera.com/hip/hip-218
">
  <front>
    <title>HIP-218: Smart Contract Verification</title>
    <author >
      <organization>Hedera</organization>
    </author>
    <date year="2022"/>
  </front>
</reference>
<reference anchor="CIRCLE-USDC-HEDERA" target="https://www.circle.com/multi-chain-usdc/hedera
">
  <front>
    <title>Circle USDC on Hedera</title>
    <author >
      <organization>Circle</organization>
    </author>
    <date year="2026"/>
  </front>
</reference>


    </references>

</references>


<?line 1874?>

<section anchor="example"><name>Example</name>

<t>Note: In examples throughout this appendix, hex values
shown with <spanx style="verb">...</spanx> (e.g., <spanx style="verb">"0x6d0f4fdf..."</spanx>) are
abbreviated. Actual values <bcp14>MUST</bcp14> be full-length as
specified in <xref target="encoding"/>.</t>

<section anchor="challenge"><name>Challenge</name>

<figure><sourcecode type="http"><![CDATA[
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment
  id="kM9xPqWvT2nJrHsY4aDfEb",
  realm="api.llm-service.com",
  method="hedera",
  intent="session",
  expires="2026-04-12T12:05:00Z",
  request="<base64url-encoded JSON below>"
]]></sourcecode></figure>

<t>The <spanx style="verb">request</spanx> decodes to:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "amount": "25",
  "unitType": "llm_token",
  "suggestedDeposit": "10000000",
  "currency":
    "0x000000000000000000000000000000000006f89a",
  "recipient":
    "0x742d35cc6634c0532925a3b844bc9e7595f8fe00",
  "methodDetails": {
    "escrowContract":
      "0x8Aaf6690C2a6397d595F97E224fC19759De6fdaE",
    "chainId": 295
  }
}
]]></sourcecode></figure>

<t>Note: Challenge expiry is in the header <spanx style="verb">expires</spanx>
auth-param, not in the request JSON. The client
generates a random salt locally for new channels.</t>

<t>This requests 0.000025 USDC per LLM token, with a
suggested deposit of 10.00 USDC (10000000 base units).</t>

</section>
<section anchor="open-credential"><name>Open Credential</name>

<t>The client first broadcasts <spanx style="verb">approve()</spanx> and <spanx style="verb">open()</spanx> to
Hedera EVM via Hashio JSON-RPC, then retries the <strong>same
resource URI</strong> with the open credential:</t>

<figure><sourcecode type="http"><![CDATA[
GET /api/chat HTTP/1.1
Host: api.llm-service.com
Authorization: Payment <base64url credential>
]]></sourcecode></figure>

<t>The credential payload for an open action:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "open",
    "channelId": "0x6d0f4fdf...",
    "txHash": "0x1a2b3c4d...",
    "cumulativeAmount": "2500",
    "signature": "0xabcdef1234567890..."
  }
}
]]></sourcecode></figure>

</section>
<section anchor="voucher-top-up-same-resource-uri"><name>Voucher Top-Up (Same Resource URI)</name>

<t>During streaming, clients submit updated vouchers to
the <strong>same resource URI</strong>. <spanx style="verb">HEAD</spanx> is recommended for
pure top-ups when no response body is needed:</t>

<figure><sourcecode type="http"><![CDATA[
HEAD /api/chat HTTP/1.1
Host: api.llm-service.com
Authorization: Payment <base64url credential
  with action="voucher">
]]></sourcecode></figure>

<t>Or with a regular request:</t>

<figure><sourcecode type="http"><![CDATA[
GET /api/chat HTTP/1.1
Host: api.llm-service.com
Authorization: Payment <base64url credential
  with action="voucher">
]]></sourcecode></figure>

<t>The credential payload for a voucher update:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "voucher",
    "channelId": "0x6d0f4fdf...",
    "cumulativeAmount": "250000",
    "signature": "0x1234567890abcdef..."
  }
}
]]></sourcecode></figure>

</section>
<section anchor="close-request-same-resource-uri"><name>Close Request (Same Resource URI)</name>

<figure><sourcecode type="http"><![CDATA[
GET /api/chat HTTP/1.1
Host: api.llm-service.com
Authorization: Payment <base64url credential
  with action="close">
]]></sourcecode></figure>

<t>The credential payload for a close request:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "hedera",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-12T12:05:00Z"
  },
  "payload": {
    "action": "close",
    "channelId": "0x6d0f4fdf...",
    "cumulativeAmount": "500000",
    "signature": "0xabcdef1234567890..."
  }
}
]]></sourcecode></figure>

<t>The voucher fields contain the final cumulative amount
for on-chain settlement.</t>

</section>
</section>
<section anchor="reference-implementation"><name>Reference Implementation</name>

<t>This appendix provides reference implementation details.
These are informative and not normative.</t>

<section anchor="solidity-interface"><name>Solidity Interface</name>

<figure><sourcecode type="solidity"><![CDATA[
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IHederaStreamChannel {
    struct Channel {
        bool finalized;
        uint64 closeRequestedAt;
        address payer;
        address payee;
        address token;
        address authorizedSigner;
        uint128 deposit;
        uint128 settled;
    }

    function CLOSE_GRACE_PERIOD()
        external view returns (uint64);
    function VOUCHER_TYPEHASH()
        external view returns (bytes32);

    function open(
        address payee,
        address token,
        uint128 deposit,
        bytes32 salt,
        address authorizedSigner
    ) external returns (bytes32 channelId);

    function settle(
        bytes32 channelId,
        uint128 cumulativeAmount,
        bytes calldata signature
    ) external;

    function topUp(
        bytes32 channelId,
        uint256 additionalDeposit
    ) external;

    function close(
        bytes32 channelId,
        uint128 cumulativeAmount,
        bytes calldata signature
    ) external;

    function requestClose(
        bytes32 channelId
    ) external;

    function withdraw(
        bytes32 channelId
    ) external;

    function getChannel(
        bytes32 channelId
    ) external view returns (Channel memory);

    function getChannelsBatch(
        bytes32[] calldata channelIds
    ) external view returns (Channel[] memory);

    function computeChannelId(
        address payer,
        address payee,
        address token,
        bytes32 salt,
        address authorizedSigner
    ) external view returns (bytes32);

    function getVoucherDigest(
        bytes32 channelId,
        uint128 cumulativeAmount
    ) external view returns (bytes32);

    function domainSeparator()
        external view returns (bytes32);

    function associateSelf(
        address token
    ) external returns (int256 responseCode);

    event ChannelOpened(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee,
        address token,
        address authorizedSigner,
        bytes32 salt,
        uint256 deposit
    );

    event Settled(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee,
        uint256 cumulativeAmount,
        uint256 deltaPaid,
        uint256 newSettled
    );

    event CloseRequested(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee,
        uint256 closeGraceEnd
    );

    event CloseRequestCancelled(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee
    );

    event TopUp(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee,
        uint256 additionalDeposit,
        uint256 newDeposit
    );

    event ChannelClosed(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee,
        uint256 settledToPayee,
        uint256 refundedToPayer
    );

    event ChannelExpired(
        bytes32 indexed channelId,
        address indexed payer,
        address indexed payee
    );

    error ChannelAlreadyExists();
    error ChannelNotFound();
    error ChannelFinalized();
    error InvalidSignature();
    error InvalidToken();
    error InvalidPayee();
    error AmountExceedsDeposit();
    error AmountNotIncreasing();
    error DepositOverflow();
    error ZeroDeposit();
    error NotPayer();
    error NotPayee();
    error TransferFailed();
    error CloseNotReady();
}
]]></sourcecode></figure>

</section>
<section anchor="deployed-contracts"><name>Deployed Contracts</name>

<texttable>
      <ttcol align='left'>Network</ttcol>
      <ttcol align='left'>Chain ID</ttcol>
      <ttcol align='left'>Contract Address</ttcol>
      <c>Hedera Testnet</c>
      <c>296</c>
      <c><spanx style="verb">0x8Aaf6690C2a6397d595F97E224fC19759De6fdaE</spanx></c>
      <c>Hedera Mainnet</c>
      <c>295</c>
      <c><spanx style="verb">0x8Aaf6690C2a6397d595F97E224fC19759De6fdaE</spanx></c>
</texttable>

<t>Both deployments are fully verified on Sourcify.</t>

</section>
<section anchor="supported-tokens"><name>Supported Tokens</name>

<texttable>
      <ttcol align='left'>Token</ttcol>
      <ttcol align='left'>Network</ttcol>
      <ttcol align='left'>HTS Token ID</ttcol>
      <ttcol align='left'>EVM Address</ttcol>
      <c>USDC</c>
      <c>Testnet</c>
      <c>0.0.5449</c>
      <c><spanx style="verb">0x00...1549</spanx></c>
      <c>USDC</c>
      <c>Mainnet</c>
      <c>0.0.456858</c>
      <c><spanx style="verb">0x00...06f89a</spanx></c>
</texttable>

<t>HTS tokens are exposed as ERC-20 via <xref target="HIP-218"/>.</t>

</section>
<section anchor="contract-source"><name>Contract Source</name>

<t>The reference implementation is available at:
<spanx style="verb">contracts/src/HederaStreamChannel.sol</spanx> in the
mppx-hedera repository.</t>

</section>
<section anchor="typescript-client-library"><name>TypeScript Client Library</name>

<t>The <spanx style="verb">mppx-hedera</spanx> npm package provides client and server
implementations:</t>

<t><list style="symbols">
  <t><spanx style="verb">mppx-hedera/client</spanx> -- <spanx style="verb">hederaSession()</spanx> client</t>
  <t><spanx style="verb">mppx-hedera/server</spanx> -- <spanx style="verb">hedera.session()</spanx> server</t>
  <t><spanx style="verb">mppx-hedera/server/sse</spanx> -- SSE transport for
metered streaming</t>
</list></t>

</section>
</section>
<section anchor="schema-definitions-json-schema"><name>Schema Definitions (JSON Schema)</name>

<section anchor="session-request-schema"><name>Session Request Schema</name>

<figure><sourcecode type="json"><![CDATA[
{
  "$schema":
    "https://json-schema.org/draft/2020-12/schema",
  "$id":
    "https://paymentauth.org/schemas/"
    "hedera-session-request.json",
  "title": "Hedera Session Request",
  "type": "object",
  "required": [
    "amount", "currency",
    "recipient", "methodDetails"
  ],
  "properties": {
    "amount": {
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "unitType": {
      "type": "string"
    },
    "suggestedDeposit": {
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "currency": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{40}$"
    },
    "recipient": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{40}$"
    },
    "methodDetails": {
      "$ref": "#/$defs/methodDetails"
    }
  },
  "$defs": {
    "methodDetails": {
      "type": "object",
      "required": ["escrowContract"],
      "properties": {
        "escrowContract": {
          "type": "string",
          "pattern": "^0x[0-9a-fA-F]{40}$"
        },
        "channelId": {
          "type": "string",
          "pattern": "^0x[0-9a-fA-F]{64}$"
        },
        "minVoucherDelta": {
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "chainId": {
          "type": "integer",
          "enum": [295, 296]
        }
      }
    }
  }
}
]]></sourcecode></figure>

</section>
<section anchor="session-payload-schema"><name>Session Payload Schema</name>

<figure><sourcecode type="json"><![CDATA[
{
  "$schema":
    "https://json-schema.org/draft/2020-12/schema",
  "$id":
    "https://paymentauth.org/schemas/"
    "hedera-session-payload.json",
  "title": "Hedera Session Payload",
  "type": "object",
  "required": ["action"],
  "properties": {
    "action": {
      "enum": [
        "open", "topUp", "voucher", "close"
      ]
    },
    "txHash": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{64}$"
    },
    "channelId": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{64}$"
    },
    "cumulativeAmount": {
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "signature": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{128,130}$"
    },
    "additionalDeposit": {
      "type": "string",
      "pattern": "^[0-9]+$",
      "description":
        "Additional deposit amount in base units "
        "(topUp action only)"
    }
  }
}
]]></sourcecode></figure>

</section>
<section anchor="session-receipt-schema"><name>Session Receipt Schema</name>

<t>Servers <bcp14>MUST</bcp14> include <spanx style="verb">Payment-Receipt</spanx> only on
successful processing of a session action (2xx).</t>

<figure><sourcecode type="json"><![CDATA[
{
  "$schema":
    "https://json-schema.org/draft/2020-12/schema",
  "$id":
    "https://paymentauth.org/schemas/"
    "hedera-session-receipt.json",
  "title": "Hedera Session Receipt",
  "type": "object",
  "required": [
    "method", "intent", "status",
    "timestamp", "challengeId",
    "channelId", "reference",
    "acceptedCumulative", "spent"
  ],
  "properties": {
    "method": { "const": "hedera" },
    "intent": { "const": "session" },
    "status": { "const": "success" },
    "timestamp": {
      "type": "string",
      "format": "date-time"
    },
    "challengeId": { "type": "string" },
    "channelId": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{64}$"
    },
    "reference": {
      "type": "string",
      "description":
        "txHash when a tx was broadcast "
        "(open, close); channelId otherwise"
    },
    "acceptedCumulative": {
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "spent": {
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "units": {
      "type": "integer"
    },
    "txHash": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{64}$"
    }
  }
}
]]></sourcecode></figure>

</section>
</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>The author thanks the Tempo team for the MPP session
payment channel design and the mppx ecosystem
architecture that this specification builds upon.
HederaStreamChannel.sol is a port of Tempo's
TempoStreamChannel.sol adapted for Hedera's EVM layer
and HTS token ecosystem.</t>

</section>


  </back>

<!-- ##markdown-source:
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
db4BBVrgxQTqWyyRqKxTWSAns97XnDLuKAZ2PUFwOmIujKR0Nd1uSwdk1VVr
1hHsJ6JLKYyAorEGHI8p/YG6fwCSKQm/JANO4mugRJtXJ5AEaLTzZPJlUAcI
PumCvIBTFHH5RfbOQjgr3VGd3+zKKMyiw5e5kxxWMNt6zJap6bBgg6nj/mqN
OTlC/B10syQGU9MVfC4hRkfs66nv8LUeQlGebHKFFcNTELLFH3t9CZ6dhRQY
YSPi8JZ909/bIt7PtnyP1Iux20hKRO2ICUPCDgbjOD5lCChTswYDCiXaHHI2
ypZzvQXQTkNysGekc9sXqN7IMHAiyFIWbIAJolgChQgXJ9SJ4aU0NrjXUPaH
Ptqu348fmy4sC56lmyK3a+Iil5GByhkNfEsbunaZd7vNrPFtUXDH+vobh0VY
XzeNWepb7Zr7Co25jEGE5lBvEEYz9s+jAxujd9GN0bJOxILZT80WKMIiW1pO
Qlzv+/siKhgYGmeP8zwegfEyx7Fvwznti/BGeQGQGTmjwkmH5lb2VeEE/Ybo
ugaBNrLThD5IwGcJPjC19v6ilwDNknpt8yUdGLvu5D+Ea3o5BmaWEN8VB73c
OXHCcFa0GRnjfIVqFLJSPkgm6D6aUyCehx/xQ36BHkYhnLhg0BC7JnOFlpir
7Z8kozVN+ztntRwE03A+p6gHj35GPhW24D/RcuSn1izkIsDY1XUNdGh4Y2zu
r6+Tfe8vOYgl9zDRNV6xtX2z1t9aQ8fFmopM+JmTZOmrsiSCj/QkQIWfUNkU
v3lUYMv2eHcv5LZWFuXGGEW0sTUabW9vbI66Wxv9vf5WuDHc3dwcjvbina29
LQ4w4sYFXgYd3JNquVZk4muaTRe63z0Ix9vbe93Dfri9sbcTQX8v9naO+/3N
8WFvD7o/irfHUXi8xt6cNWGPa8Tv4KOPwUfPkunldiSJFu/Tbgcn2N/iaDwU
cTF7pGBSJI9jXhH4oWGvq4F3mEOGf0gWDkhUFAnL0wOSfEXgH2q2s3gRNJyp
CoOGNre2d7d2WzYmsph8UzWEIhmVudYvpaX/rymFj7LfCYa2bY6jcW/cH2+H
vfH2qDfsjofRdggdjvqjbrgbbUQ7wzVtAo+Ee/DQRtyPNsOt4fZoJ8LAuE/S
4wuSyoubBaymTo0AsY+zggRwOYgVWjmNn7eBwXBlNHuwiNVqL7yU3H+UqJbj
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

-->

</rfc>

