<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-hopley-x402-refund-receipt-01" submissionType="IETF" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true">

<front>
<title abbrev="x402-refund-receipt">Categorical Refund Receipt Format for Agentic-Payment Flows</title><seriesInfo value="draft-hopley-x402-refund-receipt-01" stream="IETF" status="informational" name="Internet-Draft"></seriesInfo>
<author initials="C." surname="Hopley" fullname="Christopher Hopley"><organization>AlgoVoi</organization><address><postal><street></street>
</postal><email>chopmob@gmail.com</email>
</address></author><date year="2026" month="May" day="30"></date>
<area>Independent Submission</area>
<workgroup>Independent Submission</workgroup>
<keyword>x402</keyword>
<keyword>agentic payments</keyword>
<keyword>refund</keyword>
<keyword>compliance</keyword>
<keyword>JCS</keyword>
<keyword>RFC 8785</keyword>
<keyword>audit chain</keyword>
<keyword>categorical receipt</keyword>
<keyword>PSD2</keyword>

<abstract>
<t>This document specifies a categorical refund receipt format for
agentic-payment flows. The format is the post-settlement counterpart
to the admission-time compliance receipt format specified in
draft-hopley-x402-compliance-receipt: where the compliance receipt
records an admission decision under regulatory screening obligations,
the refund receipt records a reversal-of-funds event with the same
canonicalisation discipline and the same audit-chain semantics.</t>
<t>The receipt format uses a closed enumeration of categorical outcomes
(FULL, PARTIAL, REJECTED) rather than a continuous percentage or
amount-only representation. The categorical outcome is load-bearing
for downstream regulatory obligations: under PSD2 (Directive
2015/2366) Article 89 a REJECTED outcome carries dispute-evidence
obligations that a PARTIAL refund does not, and the categorical
distinction must be preserved at the canonical-bytes level rather
than collapsed to a percentage projection of the original amount.</t>
<t>Receipts are canonicalised under RFC 8785 (JSON Canonicalization
Scheme) with an in-band canonicalisation rule pin (canon_version).
The pin enables year-N re-verification from retained bytes alone,
without dependence on an out-of-band rule registry that the operator
must continue to publish.</t>
<t>The refund receipt format composes with the compliance receipt
format via the <tt>original_payment_ref</tt> field, a content-addressed
reference to the original payment record. A verifier walking the
audit chain can confirm the full payment lifecycle from
admission-time screening through settlement to refund event under one
byte-deterministic canonicalisation pin.</t>
<t>This document is complementary to
draft-vauban-x402-stark-receipts (which covers cryptographic
settlement-time payment-condition proofs) and to
draft-hopley-x402-compliance-receipt (which covers admission-time
compliance screening receipts). The three documents pin the same
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt> canonicalisation
discipline.</t>
</abstract>

</front>
<middle>
<section anchor="sect-1-introduction"><name>Introduction</name>

<section anchor="sect-1-1-motivation"><name>Motivation</name>
<t>Agentic-payment flows generate two classes of receipt over the
lifecycle of a transaction: admission-time receipts (compliance
screening, payment authorisation, mandate verification) and
post-settlement receipts (settlement confirmation, refund, dispute
resolution).</t>
<t>A refund is a state transition that creates a new record on the
post-settlement chain: funds previously transferred to a payee are
returned in full, in part, or the return request is denied. The
operational and regulatory significance of this state transition is
load-bearing:</t>

<ul spacing="compact">
<li>Under UK Consumer Rights Act 2015 and EU Consumer Rights
Directive 2011/83/EU Article 9, a FULL refund within the statutory
window closes the consumer's right to further remedy.</li>
<li>Under PSD2 (Directive 2015/2366) Article 89, an unauthorised
payment must be refunded immediately or rejected with documented
reasons. A REJECTED outcome creates dispute-evidence obligations
distinct from a FULL or PARTIAL outcome.</li>
<li>Under UK POCA 2002 and EU AML Directives 5/6, a refund triggered
by post-settlement sanctions screening or fraud detection requires
audit-chain linkage to the original compliance receipt for
retention-period audit by competent authorities.</li>
</ul>
<t>A receipt format that collapses these distinctions to a continuous
amount-only representation loses the load-bearing operational
distinction.</t>
<t>This document specifies a refund receipt format that preserves the
categorical outcome at the canonical-bytes level. The same
canonicalisation discipline and audit-chain semantics as
draft-hopley-x402-compliance-receipt apply, so a verifier can use
one implementation to walk the entire payment lifecycle.</t>
</section>

<section anchor="sect-1-2-scope"><name>Scope</name>
<t>This document specifies:</t>

<ul spacing="compact">
<li>The canonical JSON shape of the refund receipt (Section 3)</li>
<li>The canonicalisation rule applicable to the receipt (Section 4)</li>
<li>The audit chain composition under which refund receipts compose
with compliance receipts and settlement records (Section 5)</li>
<li>The year-N auditability properties the format pins (Section 6)</li>
<li>Worked examples covering FULL, PARTIAL, and REJECTED outcomes
(Appendix A)</li>
<li>Reference implementations and conformance vectors (Appendix B)</li>
</ul>
<t>The document does NOT specify:</t>

<ul spacing="compact">
<li>The refund orchestration protocol (operator-layer concern; out of
scope)</li>
<li>Dispute-resolution state machines (a refund receipt records one
state transition; multi-party dispute orchestration is a separate
problem class)</li>
<li>Cross-chain settlement mechanisms (an asset substitution between
original payment and refund is permitted in the receipt format but
the bridge mechanism is out of scope)</li>
<li>Card-network chargeback or interchange formats (ISO 8583 / ISO
20022 message families serve that purpose)</li>
</ul>
</section>

<section anchor="sect-1-3-relationship-to-other-internet-drafts"><name>Relationship to other Internet-Drafts</name>
<t>This document is one of a coordinated suite of five AlgoVoi-authored
receipt and response format Internet-Drafts, all anchoring to the
canonicalisation discipline specified in
draft-hopley-x402-canonicalisation-jcs:</t>

<ul spacing="compact">
<li>draft-hopley-x402-canonicalisation-jcs -- the JCS canonicalisation
discipline pinned by Section 4 of this document.</li>
<li>draft-hopley-x402-compliance-receipt -- admission-time compliance
screening receipt. A refund receipt's <tt>original_payment_ref</tt> MAY
equal the <tt>content_hash</tt> of the compliance receipt that admitted
the original payment.</li>
<li>draft-hopley-x402-settlement-attestation -- per-settlement
categorical attestation. A refund receipt's <tt>original_payment_ref</tt>
MAY equal the <tt>content_hash</tt> of a settlement attestation when the
refund reverses a previously-SETTLED payment.</li>
<li>draft-hopley-x402-cancellation-receipt -- the mandate cancellation
receipt format. A USER_REQUESTED cancellation under PSD2 Article
64 MAY chain forward to a refund receipt on the audit chain when
Article 64 refund obligations attach to a recently-settled debit.</li>
<li>draft-hopley-x402-composite-trust-query -- verifier-side
composite-trust-query response format. A verifier walking an audit
chain containing a refund receipt emits a single composite-trust
response over the chain.</li>
</ul>
<t>The five formats share the same canonicalisation pin, audit chain
row shape, integer-millisecond timestamp encoding (Substrate Rule 2),
jurisdiction_flags ordering convention, and closed-enumeration
discipline. A verifier walking the full payment lifecycle requires
only one implementation of the canonicalisation discipline.</t>
</section>

<section anchor="sect-1-4-relationship-to-draft-vauban-x402-stark-receipts"><name>Relationship to draft-vauban-x402-stark-receipts</name>
<t>draft-vauban-x402-stark-receipts covers cryptographic settlement-time
payment-condition proofs (STARK receipts). The refund receipt
specified in this document MAY reference a STARK receipt as its
<tt>original_payment_ref</tt> value: when a payment that was settled with a
STARK proof is subsequently refunded, the refund receipt links back
to the STARK-receipt content_hash and the verifier walks the chain
across both formats under one canonicalisation pin.</t>
</section>
</section>

<section anchor="sect-2-conventions-and-definitions"><name>Conventions and Definitions</name>

<section anchor="sect-2-1-notation"><name>Notation</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;,
&quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and
&quot;OPTIONAL&quot; in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.</t>
</section>

<section anchor="sect-2-2-definitions"><name>Definitions</name>
<t><strong>refund receipt</strong>: a JSON object of the shape specified in Section
3, canonicalised under the discipline specified in Section 4.</t>
<t><strong>content_hash</strong>: SHA-256, lowercase hex, of the JCS-canonical bytes
of the receipt object.</t>
<t><strong>original_payment_ref</strong>: a string of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>
identifying the original payment record by content hash. The
original record MAY be a compliance receipt, a settlement
attestation, or an operator-specific payment record.</t>
<t><strong>refund_amount</strong>: a two-field object <tt>{amount_minor, asset_id}</tt>
representing the refunded value. <tt>amount_minor</tt> is a decimal-digit
string in the asset's minor unit; <tt>asset_id</tt> identifies the asset and
its decimal precision.</t>
<t><strong>canon_version</strong>: an in-band string identifying the canonicalisation
discipline. Fixed value <tt>jcs-rfc8785-v1</tt> for this version.</t>
<t><strong>audit chain row</strong>: a four-field object linking receipts via
SHA-256 hash chain, shape specified in Section 5.1.</t>
</section>
</section>

<section anchor="sect-3-receipt-format-specification"><name>Receipt Format Specification</name>
<t>A refund receipt is a JSON object with the following seven fields.
All fields are REQUIRED. The receipt is canonicalised under RFC 8785
(JCS) per Section 4. Field names are sorted lexicographically by JCS
during canonicalisation; the receipt object itself uses arbitrary
authoring order.</t>

<section anchor="sect-3-1-refund-result"><name>refund_result</name>
<t>A string-valued field. The value MUST be one of:</t>

<ul spacing="compact">
<li><tt>FULL</tt> -- the entire original payment amount has been returned to
the payer.</li>
<li><tt>PARTIAL</tt> -- less than the original payment amount has been
returned. The <tt>refund_amount</tt> field carries the actual refunded
value; the verifier compares against the original via
<tt>original_payment_ref</tt> linkage.</li>
<li><tt>REJECTED</tt> -- a refund request was processed and denied. No funds
moved. The receipt records the denial event so downstream
dispute / chargeback chains can reference it.</li>
</ul>
<t>The three-element enumeration is closed. Implementations MUST reject
any other value at validation time before canonicalisation. Score,
percentage, or amount-only projections are not acceptable
substitutes for the categorical outcome.</t>
<t>The regulatory distinction is load-bearing. Under PSD2 (Directive
2015/2366) Article 89, a payer denied a refund (REJECTED) must
receive a documented denial; this is operationally distinct from a
PARTIAL refund where some-but-not-all of the original amount has
been returned. Under UK Consumer Rights Act 2015 and EU Consumer
Rights Directive 2011/83/EU Article 9, only a FULL refund within the
statutory window closes the consumer's right to further remedy. A
percentage or amount-only representation cannot preserve these
distinctions.</t>
</section>

<section anchor="sect-3-2-jurisdiction-flags"><name>jurisdiction_flags</name>
<t>An ordered array of string-valued ISO-3166-1 alpha-2 country codes
or alpha-3 region codes identifying the applicable regulatory
frameworks for the refund event.</t>
<t>Authoring convention: primary jurisdiction first (where the
operating entity is licensed), secondary jurisdictions in order of
regulatory precedence.</t>
<t>Array element ORDER is SIGNIFICANT and load-bearing. RFC 8785 does
not normalise array order during canonicalisation. The array
<tt>[&quot;UK&quot;, &quot;EU&quot;]</tt> and the array <tt>[&quot;EU&quot;, &quot;UK&quot;]</tt> produce byte-distinct
canonical representations and distinct <tt>content_hash</tt> values.</t>
</section>

<section anchor="sect-3-3-original-payment-ref"><name>original_payment_ref</name>
<t>A string-valued field of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>. The
hex digest is SHA-256 of the JCS-canonical bytes of the original
payment record being refunded.</t>
<t>When refunding a payment that was admitted under a compliance
receipt (per draft-hopley-x402-compliance-receipt), the
<tt>original_payment_ref</tt> MAY equal the <tt>content_hash</tt> of the
compliance receipt itself. This is the conventional choice and
enables the audit-chain composition described in Section 5.</t>
<t>When refunding a payment that was settled with a STARK proof (per
draft-vauban-x402-stark-receipts), the <tt>original_payment_ref</tt> MAY
equal the <tt>content_hash</tt> of the STARK receipt.</t>
<t>Implementations MUST NOT strip the <tt>sha256:</tt> prefix during
canonicalisation or verification. The prefix is part of the canonical
bytes.</t>
</section>

<section anchor="sect-3-4-refund-amount"><name>refund_amount</name>
<t>A sub-object with exactly two fields:</t>

<ul spacing="compact">
<li><tt>amount_minor</tt> -- a string of decimal digits representing the
refunded value in the asset's minor unit. String typing avoids
float-precision loss and JavaScript-integer-overflow concerns for
large values, and is representable losslessly under JCS.</li>
<li><tt>asset_id</tt> -- a string identifying the asset and its decimal
precision. Convention: <tt>&lt;symbol&gt;.&lt;decimals&gt;</tt> for chain-native
assets (e.g. <tt>USDC.6</tt>, <tt>ALGO.6</tt>, <tt>ETH.18</tt>); <tt>&lt;chain&gt;:&lt;asset_id&gt;.&lt;decimals&gt;</tt>
for ASA-style assets (e.g. <tt>algo:31566704.6</tt>).</li>
</ul>
<t>The sub-object's keys are sorted lexicographically by RFC 8785
during canonicalisation: <tt>amount_minor</tt> then <tt>asset_id</tt>. Verifiers
MUST treat <tt>{&quot;amount_minor&quot;:&quot;100000&quot;,&quot;asset_id&quot;:&quot;USDC.6&quot;}</tt> as
equivalent to the same content produced by an authoring layer that
emitted fields in <tt>asset_id</tt>-first order; JCS canonicalisation
removes the distinction.</t>
<t>For a PARTIAL refund, <tt>refund_amount</tt> carries the actual refunded
value. For a FULL refund, <tt>refund_amount</tt> carries the entire
original payment amount. For a REJECTED refund, <tt>refund_amount</tt>
carries the amount that WOULD have been refunded had the request
been accepted (the requested-but-denied amount), enabling the
denial-evidence chain to capture the operational claim.</t>
<t>Cross-asset refunds (where the refund asset differs from the
original payment asset, e.g. paid in USDC on Base, refunded in USDC
on Solana) are permitted: <tt>refund_amount.asset_id</tt> MAY differ from
the asset of the original payment. The cross-chain mechanism by
which the substitution is achieved is out of scope of this document.</t>
</section>

<section anchor="sect-3-5-refund-provider-did"><name>refund_provider_did</name>
<t>A string-valued DID URI identifying the entity issuing the refund.
For Verifiable-Credentials-class identities this is the issuer DID;
for centralised gateway-class identities this is <tt>did:web:&lt;host&gt;</tt>.</t>
</section>

<section anchor="sect-3-6-refund-timestamp-ms"><name>refund_timestamp_ms</name>
<t>An integer-valued field carrying the epoch-millisecond timestamp of
the refund event in UTC.</t>
<t>This field MUST be an integer in the canonical receipt. RFC 3339
string forms (e.g. <tt>&quot;2026-05-28T12:00:00Z&quot;</tt>) MUST be rejected at
the validation layer before canonicalisation; silent type-coercion
breaks year-N auditability and cross-implementation byte-determinism.</t>
<t>The integer-only restriction is required because RFC 8785 canonicalises
the integer <tt>1716494400000</tt> and the string <tt>&quot;1716494400000&quot;</tt> to
distinct canonical-bytes representations. A receipt format that
accepted both forms could produce two byte-distinct receipts for
the same logical refund event, breaking the dedup and audit-chain
linkage properties.</t>
<t>This rule is formalised in x402-foundation/x402 pull request #2436
(canonicalisation discipline), normatively specified in
draft-hopley-x402-canonicalisation-jcs Section 4.1, and is referred
to in the AlgoVoi substrate as Substrate Rule 2.</t>
</section>

<section anchor="sect-3-7-canon-version"><name>canon_version</name>
<t>A string-valued in-band canonicalisation rule pin. For this version
of the receipt format the value MUST be <tt>jcs-rfc8785-v1</tt>.</t>
<t>The pin enables year-N re-verification from retained bytes alone.
A future revision of the canonicalisation discipline MAY introduce
a successor pin (e.g. <tt>jcs-rfc8785-v2</tt>); a verifier reading a receipt
with the successor pin applies the corresponding rule. The pin is
itself canonicalised and signed-over so it cannot be silently
re-narrated post-emission.</t>
</section>
</section>

<section anchor="sect-4-canonicalisation"><name>Canonicalisation</name>
<t>The refund receipt MUST be canonicalised under JSON Canonicalization
Scheme (JCS) as specified in [RFC8785]. The canonicalisation
discipline pinned by this document is:</t>

<artwork><![CDATA[urn:x402:canonicalisation:jcs-rfc8785-v1
]]></artwork>
<t>This discipline mandates:</t>

<ul spacing="compact">
<li>RFC 8785 canonical JSON for the receipt object.</li>
<li>UTF-8 encoding with no byte-order mark.</li>
<li>Object keys sorted lexicographically by code point at every level
(per RFC 8785 Section 3.2.3).</li>
<li>Array element order preserved (per RFC 8785 Section 3.2.3).</li>
<li>Numeric values canonicalised per RFC 8785 Section 3.2.2.3.</li>
<li>Integer-only encoding for <tt>refund_timestamp_ms</tt> (Substrate Rule
2), applied at the validation layer before canonicalisation.</li>
</ul>
<t>The discipline pinned here is identical to that pinned by
draft-hopley-x402-compliance-receipt Section 4, normatively
specified in draft-hopley-x402-canonicalisation-jcs, and to the
canonicalisation specification at x402-foundation/x402
specs/canonicalisation.md (PR #2436).</t>
<t>The discipline is byte-for-byte cross-validated across eight
independent JCS implementations in eight programming languages per
the AlgoVoi conformance attestation dated 2026-05-24:
[AlgoVoi-JCS-8-impl].</t>
</section>

<section anchor="sect-5-audit-chain-composition"><name>Audit Chain Composition</name>
<t>A refund receipt MAY participate in an audit chain alongside
compliance receipts and other receipt classes that pin the same
canonicalisation discipline.</t>

<section anchor="sect-5-1-chain-row-shape"><name>Chain Row Shape</name>
<t>An audit chain row is a JSON object with four fields:</t>

<sourcecode type="json"><![CDATA[{
  "row_number": 1,
  "content_hash": "<hex64>",
  "prev_hash": "<hex64>",
  "row_content_hash": "<hex64>"
}
]]></sourcecode>

<ul spacing="compact">
<li><tt>row_number</tt>: integer, 1-indexed.</li>
<li><tt>content_hash</tt>: SHA-256, lowercase hex, of the JCS-canonical bytes
of the receipt object anchored by this row.</li>
<li><tt>prev_hash</tt>: SHA-256, lowercase hex, of the previous row's
<tt>row_content_hash</tt>. For row 1, <tt>prev_hash</tt> MUST be 64 zero hex
characters (<tt>0000...0000</tt>).</li>
<li><tt>row_content_hash</tt>: SHA-256, lowercase hex, of the JCS-canonical
bytes of this row object (with <tt>row_content_hash</tt> itself excluded
from the JCS computation; the row's first three fields
<tt>{row_number, content_hash, prev_hash}</tt> are canonicalised and
hashed to produce <tt>row_content_hash</tt>).</li>
</ul>
<t>This row shape is identical to the audit-chain row shape specified
in draft-hopley-x402-compliance-receipt Section 5.1. The two
documents pin the same chain composition so receipts of either class
can be linked into one verifiable chain.</t>
</section>

<section anchor="sect-5-2-linkage-verification"><name>Linkage Verification</name>
<t>A verifier reading a chain segment performs these checks:</t>

<ul spacing="compact">
<li>For each row, recompute the row's <tt>row_content_hash</tt> from its
first three fields under JCS and compare against the stored value.
Mismatch indicates row tampering.</li>
<li>For each row N &gt; 1, check that row N's <tt>prev_hash</tt> equals row
N-1's <tt>row_content_hash</tt>. Mismatch indicates chain truncation,
reordering, or row deletion.</li>
<li>For row 1, check that <tt>prev_hash</tt> is 64 zero hex characters
(the chain genesis anchor).</li>
<li>For each row, optionally fetch the receipt body whose
<tt>content_hash</tt> is referenced and verify the body re-canonicalises
to the same hash. This step is required for receipt-level audit
but optional for row-level chain integrity.</li>
</ul>
<t>A chain that passes all of the above is byte-deterministically
verifiable from retained bytes alone, with no dependence on the
originating gateway's continued operation.</t>
</section>

<section anchor="sect-5-3-composition-with-compliance-receipts"><name>Composition with Compliance Receipts</name>
<t>When a refund receipt references a compliance receipt via
<tt>original_payment_ref</tt>, the audit-chain composition is:</t>

<artwork><![CDATA[chain row N      chain row N+1
+------------+   +------------+
| compliance |-->| refund     |
| receipt    |   | receipt    |
| (content_  |   | (content_  |
|  hash)     |   |  hash)     |
+------------+   +------------+
]]></artwork>
<t>Row N anchors the compliance receipt (admission decision). Row N+1
anchors the refund receipt; the refund receipt's
<tt>original_payment_ref</tt> equals the <tt>content_hash</tt> of the compliance
receipt anchored by row N. The chain row N+1's <tt>prev_hash</tt> equals
row N's <tt>row_content_hash</tt>. A verifier walking this segment confirms:</t>

<ol spacing="compact">
<li>The compliance receipt admitted the original payment.</li>
<li>The refund receipt links to that admission via
<tt>original_payment_ref</tt>.</li>
<li>The chain rows preserve hash-linkage with no truncation or
reordering.</li>
</ol>
<t>The same composition extends to longer chains: multi-leg PARTIAL
refunds, refund reversals (refund-of-refund), and disputed REJECTED
refunds with subsequent re-evaluation each contribute one or more
rows to the chain.</t>
</section>

<section anchor="sect-5-4-retention-storage"><name>Retention Storage</name>
<t>Retention storage of refund receipts and their audit chains is
out of scope of this document. Operators MUST retain receipts for
the period required by applicable regulatory frameworks (UK
Consumer Rights Act 2015 disclosure period; PSD2 Article 89
dispute window; MiCA Article 80 records retention; AMLR Article 56
records retention).</t>
<t>Object Lock COMPLIANCE-mode retention on object stores supporting
WORM retention (Amazon S3, Backblaze B2, Cloudflare R2) is a
practical implementation; refund receipts and their audit-chain
rows MUST NOT be modifiable during the retention period.</t>
</section>
</section>

<section anchor="sect-6-year-n-auditability-properties"><name>Year-N Auditability Properties</name>
<t>This receipt format preserves the following properties so that
retained bytes are independently verifiable years after emission,
without dependence on the originating gateway's continued operation.</t>

<ol>
<li><t><strong>Self-describing canonicalisation pin.</strong> The <tt>canon_version</tt>
field is an in-band identifier (<tt>jcs-rfc8785-v1</tt>) so a verifier
reading retained bytes can determine which canonicalisation rule
to apply.</t>
</li>
<li><t><strong>No external rule registry required.</strong> The canonical bytes
produced under <tt>jcs-rfc8785-v1</tt> are RFC 8785 plus the
integer-millisecond timestamp encoding rule (Substrate Rule 2).
Both rules are specified in this document and in
draft-hopley-x402-compliance-receipt; neither requires the
operator to continue to publish a canonicalisation rule
registry.</t>
</li>
<li><t><strong>Cross-implementation verifiability.</strong> The JCS RFC 8785
canonicalisation discipline has been byte-for-byte cross-validated
across eight independent reference implementations in eight
programming languages: Python (rfc8785), TypeScript
(canonicalize), Go (gowebpki/jcs), Rust (serde_jcs), Java
(cyberphone/json-canonicalization, authored by Anders Rundgren,
RFC 8785 editor), PHP (root23/php-json-canonicalization), C#/.NET
(Baqhub.Packages.JsonCanonicalization), and Ruby
(json-canonicalization). 192/192 byte-for-byte agreements across
24 vectors in 3 anchor sets. The attestation record is published
at [AlgoVoi-JCS-8-impl]. A verifier built with any of these eight
implementations produces identical canonical bytes for any refund
receipt under this format.</t>
</li>
<li><t><strong>Tamper detection.</strong> Per-row <tt>content_hash</tt> and chain <tt>prev_hash</tt>
linkage (Section 5) detect single-row tampering and chain
truncation / reordering respectively.</t>
</li>
<li><t><strong>Regulatory distinction preserved.</strong> The closed enumeration on
<tt>refund_result</tt> (Section 3.1) preserves the load-bearing
distinction between FULL, PARTIAL, and REJECTED for the full
retention period.</t>
</li>
<li><t><strong>Compositional verifiability.</strong> A refund receipt's
<tt>original_payment_ref</tt> MAY reference any other receipt class that
pins the same canonicalisation discipline (compliance receipt,
STARK receipt, settlement attestation). The verifier needs only
one canonicalisation implementation to walk the full payment
lifecycle.</t>
</li>
</ol>
</section>

<section anchor="sect-7-composition-with-other-x402-substrate"><name>Composition with Other x402 Substrate</name>
<t>This receipt format composes with other elements of the x402 substrate:</t>

<section anchor="sect-7-1-compliance-receipt-linkage"><name>Compliance Receipt Linkage</name>
<t>The conventional <tt>original_payment_ref</tt> target for an
admission-then-refund flow is the <tt>content_hash</tt> of the compliance
receipt that admitted the original payment under
draft-hopley-x402-compliance-receipt. The two receipts compose into
one audit-chain segment that records the full admission-through-
refund lifecycle. See Section 5.3.</t>
</section>

<section anchor="sect-7-2-stark-receipt-linkage"><name>STARK Receipt Linkage</name>
<t>When a payment was settled with a STARK proof per
draft-vauban-x402-stark-receipts, the refund receipt's
<tt>original_payment_ref</tt> MAY equal the <tt>content_hash</tt> of the STARK
receipt. The verifier confirms the STARK-proven settlement and the
subsequent refund event under one canonicalisation pin.</t>
</section>

<section anchor="sect-7-3-composite-trust-query"><name>Composite Trust-Query</name>
<t>Multiple emitters' attestations may participate in a composite
trust-query per x402-foundation/x402 pull request #2440. A refund
provider's attestation row in a composite-trust-query MAY reference
a refund receipt's <tt>content_hash</tt> as the underlying evidence.</t>
</section>
</section>

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

<section anchor="sect-8-1-urn-namespace-registration"><name>URN Namespace Registration</name>
<t>This document references the URN
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt> registered by
draft-hopley-x402-canonicalisation-jcs Section 10.1. No additional
URN namespace registration is required by this document.</t>
</section>

<section anchor="sect-8-2-receipt-format-identifier"><name>Receipt Format Identifier</name>
<t>This document defines the receipt format identifier:</t>

<artwork><![CDATA[urn:x402:receipt:refund-v1
]]></artwork>
<t>This identifier MAY be used by composite-trust-query implementations
(per x402-foundation/x402 PR #2440) to refer to refund receipts as
a class. Registration with IANA is requested under the
x402-foundation/x402 receipt-format identifier namespace.</t>
</section>
</section>

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

<section anchor="sect-9-1-receipt-tampering"><name>Receipt Tampering</name>
<t>A refund receipt's <tt>content_hash</tt> is the SHA-256 of its JCS-canonical
bytes. Tampering with any field of the receipt produces a different
<tt>content_hash</tt>; the tampered receipt fails verification against any
audit-chain row that references the original <tt>content_hash</tt>.</t>
</section>

<section anchor="sect-9-2-chain-truncation-and-reordering"><name>Chain Truncation and Reordering</name>
<t>The audit chain <tt>prev_hash</tt> linkage (Section 5.2) detects
truncation, reordering, or row deletion. A verifier walking the
chain confirms that every row's <tt>prev_hash</tt> equals the previous
row's <tt>row_content_hash</tt>; any deviation indicates chain integrity
loss.</t>
</section>

<section anchor="sect-9-3-double-refund-attacks"><name>Double-Refund Attacks</name>
<t>A malicious operator might attempt to issue two refund receipts
for the same original payment, each linking to the same
<tt>original_payment_ref</tt>. Detection requires the verifier to walk
the chain forward from the compliance receipt and observe both
refund rows; the chain itself does not prevent the double-issuance
but makes it byte-detectable.</t>
<t>Operators SHOULD enforce single-refund-per-payment at the
operator-layer orchestration before emitting receipts. For PARTIAL
refunds that genuinely require multiple legs (e.g. a customer
returning two items from a single order), each leg's refund receipt
MUST link to the original payment ref AND to the prior refund row
to make the leg-sequence verifiable; the chain order encodes the
cumulative refunded amount.</t>
</section>

<section anchor="sect-9-4-cross-asset-refund-substitution"><name>Cross-Asset Refund Substitution</name>
<t>A refund receipt MAY refund in a different asset than the original
payment. A verifier cannot determine equivalence-of-value between
the original asset and the refund asset from the receipt alone;
asset-substitution claims of equivalence require additional external
evidence (price oracle attestations, settlement proofs) and are out
of scope of this document.</t>
<t>Operators substituting assets MUST disclose the substitution
clearly to the payer at the time of the refund and MUST retain
evidence of the equivalence claim under the same retention period
as the receipt itself.</t>
</section>

<section anchor="sect-9-5-operator-continuity-loss"><name>Operator Continuity Loss</name>
<t>If the original refund-issuing operator becomes unavailable, the
audit chain and its receipts MUST remain independently verifiable
from retained bytes plus the eight reference implementations cited
in Section 6. This document specifies year-N auditability
properties so that operator continuity loss does not break
verifiability.</t>
</section>

<section anchor="sect-9-6-did-resolution-compromise"><name>DID Resolution Compromise</name>
<t><tt>refund_provider_did</tt> is a DID URI. If the DID resolution
infrastructure is compromised at verification time, the verifier
MAY be unable to resolve the DID to an authoritative key. The
receipt format MAY be combined with offline DID document snapshots
(captured at the time of receipt emission and retained alongside the
receipt) to make verification independent of live DID resolution.</t>
</section>

<section anchor="sect-9-7-privacy"><name>Privacy</name>
<t>The <tt>original_payment_ref</tt> field is content-addressed, not cleartext.
A receipt does not leak payer identity, payee identity, or original
payment amount on its face. The <tt>refund_amount</tt> field carries the
refunded value but the original payment amount is not in the
receipt; cross-receipt linkage (via <tt>original_payment_ref</tt> to a
compliance receipt) is required to recover the original amount, and
the linkage is itself content-addressed.</t>
</section>
</section>

</middle>
<back>
<section anchor="sect-10-references"><name>References</name>

<section anchor="sect-10-1-normative-references"><name>Normative References</name>

<ul spacing="compact">
<li>[RFC2119] Bradner, S., &quot;Key words for use in RFCs to Indicate
Requirement Levels&quot;, BCP 14, RFC 2119, DOI 10.17487/RFC2119, March
1997.</li>
<li>[RFC8174] Leiba, B., &quot;Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words&quot;, BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017.</li>
<li>[RFC8259] Bray, T., Ed., &quot;The JavaScript Object Notation (JSON) Data
Interchange Format&quot;, STD 90, RFC 8259, DOI 10.17487/RFC8259, December
2017.</li>
<li>[RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, &quot;JSON
Canonicalization Scheme (JCS)&quot;, RFC 8785, DOI 10.17487/RFC8785, June
2020.</li>
<li>[RFC8141] Saint-Andre, P. and J. Klensin, &quot;Uniform Resource Names
(URNs)&quot;, RFC 8141, DOI 10.17487/RFC8141, April 2017.</li>
</ul>
</section>

<section anchor="sect-10-2-informative-references"><name>Informative References</name>

<ul spacing="compact">
<li>draft-hopley-x402-canonicalisation-jcs
Hopley, C., &quot;JCS Canonicalisation Discipline for Agentic-Payment
Receipts&quot;, draft-hopley-x402-canonicalisation-jcs-v1, May 2026.</li>
<li>draft-hopley-x402-compliance-receipt
Hopley, C., &quot;Categorical Compliance Screening Receipt Format for
Agentic-Payment Flows&quot;, draft-hopley-x402-compliance-receipt-01,
May 2026.</li>
<li>draft-hopley-x402-settlement-attestation
Hopley, C., &quot;Categorical Settlement Attestation Format for
Agentic-Payment Flows&quot;, draft-hopley-x402-settlement-attestation-00,
May 2026.</li>
<li>draft-hopley-x402-cancellation-receipt
Hopley, C., &quot;Categorical Mandate Cancellation Receipt Format for
Agentic-Payment Flows&quot;, draft-hopley-x402-cancellation-receipt-00,
May 2026.</li>
<li>draft-hopley-x402-composite-trust-query
Hopley, C., &quot;Composite Trust Query Response Format for
Agentic-Payment Audit Chains&quot;,
draft-hopley-x402-composite-trust-query-00, May 2026.</li>
<li>draft-vauban-x402-stark-receipts (companion document on STARK
receipt format).</li>
<li>AlgoVoi, &quot;Substrate Adopters Registry&quot;,
<eref target="https://docs.algovoi.co.uk/adopters"> target="https://docs.algovoi.co.uk/adopters"</eref></li>
<li>x402-foundation/x402 pull request #2436 -- canonicalisation
discipline (AlgoVoi-authored normative section with subsequent
review co-signatures from Vauban Pay and Arian Gogani).</li>
<li>x402-foundation/x402 pull request #2440 -- composite trust-query
algorithm.</li>
<li>[AlgoVoi-JCS-8-impl]
AlgoVoi, &quot;Eight-implementation cross-validation attestation for
JCS RFC 8785&quot;, 2026-05-24,
<eref target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/blob/main/_attestations/2026-05-24-8-impl-cross-validation.md"> target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/blob/main/_attestations/2026-05-24-8-impl-cross-validation.md"</eref></li>
<li>[AlgoVoi-Substrate-Authorship]
AlgoVoi, &quot;Substrate Authorship and Provenance&quot;,
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance"> target="https://docs.algovoi.co.uk/substrate-authorship-provenance"</eref></li>
<li>UK Consumer Rights Act 2015.</li>
<li>EU Consumer Rights Directive 2011/83/EU, Article 9.</li>
<li>EU Payment Services Directive 2 (PSD2, Directive 2015/2366),
Article 89 (unauthorised payment refunds).</li>
<li>UK Money Laundering Regulations 2017.</li>
<li>UK Proceeds of Crime Act 2002, Section 330.</li>
<li>EU Anti-Money Laundering Directive 5 (Directive (EU) 2018/843).</li>
<li>EU Anti-Money Laundering Directive 6 (Directive (EU) 2018/1673).</li>
<li>EU Markets in Crypto-Assets Regulation (MiCA, Regulation (EU)
2023/1114), Article 80.</li>
<li>EU Anti-Money Laundering Regulation (AMLR, Regulation (EU) 2024/1624),
Article 56.</li>
</ul>
</section>
</section>

<section anchor="appendix-a-examples-informative"><name>Appendix A. Examples (Informative)</name>
<t>The following example refund receipts illustrate the format. All
three are canonicalised under <tt>jcs-rfc8785-v1</tt> and produce the
content_hashes pinned in the AlgoVoi <tt>refund_receipt_v1</tt>
conformance vector set.</t>

<section anchor="a-1-full-refund-under-uk-eu-joint-jurisdiction"><name>A.1. FULL refund under UK + EU joint jurisdiction</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "jcs-rfc8785-v1",
  "jurisdiction_flags": ["UK", "EU"],
  "original_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
  "refund_amount": {"amount_minor": "100000", "asset_id": "USDC.6"},
  "refund_provider_did": "did:example:refund-provider-1",
  "refund_result": "FULL",
  "refund_timestamp_ms": 1716494400000
}
]]></sourcecode>
<t>Refunds 0.1 USDC (100000 minor units, 6 decimals) under joint UK +
EU jurisdiction. The <tt>original_payment_ref</tt> references a payment
record whose content_hash is the listed value (e.g. a compliance
receipt from draft-hopley-x402-compliance-receipt). FULL closes the
consumer's right to further remedy under UK Consumer Rights Act
2015 and EU Consumer Rights Directive 2011/83/EU Article 9.</t>
</section>

<section anchor="a-2-partial-refund"><name>A.2. PARTIAL refund</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "jcs-rfc8785-v1",
  "jurisdiction_flags": ["UK", "EU"],
  "original_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
  "refund_amount": {"amount_minor": "100000", "asset_id": "USDC.6"},
  "refund_provider_did": "did:example:refund-provider-1",
  "refund_result": "PARTIAL",
  "refund_timestamp_ms": 1716494400000
}
]]></sourcecode>
<t><tt>refund_amount</tt> carries the actual refunded value; the verifier
compares against the original via <tt>original_payment_ref</tt> to confirm
the refund is strictly less than the original. PARTIAL does not
close the consumer's right under consumer-rights statutes; further
remedy may remain.</t>
</section>

<section anchor="a-3-rejected-refund-psd2-article-89-dispute-evidence"><name>A.3. REJECTED refund (PSD2 Article 89 dispute evidence)</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "jcs-rfc8785-v1",
  "jurisdiction_flags": ["UK", "EU"],
  "original_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
  "refund_amount": {"amount_minor": "100000", "asset_id": "USDC.6"},
  "refund_provider_did": "did:example:refund-provider-1",
  "refund_result": "REJECTED",
  "refund_timestamp_ms": 1716494400000
}
]]></sourcecode>
<t>A refund request was processed and denied. <tt>refund_amount</tt> carries
the requested-but-denied amount so the denial-evidence chain can
record the operational claim. Under PSD2 Article 89, a payer denied
a refund must receive a documented denial; this receipt fulfils
that documentation obligation.</t>
</section>
</section>

<section anchor="appendix-b-reference-implementations-informative"><name>Appendix B. Reference Implementations (Informative)</name>
<t>The following open-source packages implement the format specified
in this document. None of these implementations is privileged; the
format is fully specified by Section 3.</t>

<ul>
<li><t>algovoi-refund-receipt (Python) on PyPI:
<eref target="https://pypi.org/project/algovoi-refund-receipt/"> target="https://pypi.org/project/algovoi-refund-receipt/"</eref>
Provides <tt>build_refund_receipt()</tt>. Depends on algovoi-substrate for
the JCS canonicalisation primitive. Apache 2.0 licensed.</t>
</li>
<li><t>@algovoi/refund-receipt (TypeScript) on npm:
<eref target="https://www.npmjs.com/package/@algovoi/refund-receipt"> target="https://www.npmjs.com/package/@algovoi/refund-receipt"</eref>
Byte-for-byte parity with the Python sibling. Depends on
@algovoi/substrate for the JCS canonicalisation primitive. Apache
2.0 licensed.</t>
</li>
<li><t>algovoi-substrate (Python) on PyPI:
<eref target="https://pypi.org/project/algovoi-substrate/"> target="https://pypi.org/project/algovoi-substrate/"</eref>
Provides <tt>build_compliance_receipt()</tt> and the JCS canonicalisation
primitive used by the refund receipt builder. Apache 2.0 licensed.</t>
</li>
<li><t>@algovoi/substrate (TypeScript) on npm:
<eref target="https://www.npmjs.com/package/@algovoi/substrate"> target="https://www.npmjs.com/package/@algovoi/substrate"</eref>
Byte-for-byte parity with the Python substrate. Apache 2.0 licensed.</t>
</li>
<li><t>algovoi-audit-verifier (Python) on PyPI:
<eref target="https://pypi.org/project/algovoi-audit-verifier/"> target="https://pypi.org/project/algovoi-audit-verifier/"</eref>
Implements the audit-chain verification logic (Section 5.2)
including per-row content_hash recomputation and chain linkage
walk. MIT licensed.</t>
</li>
<li><t>@algovoi/audit-verifier (TypeScript) on npm:
<eref target="https://www.npmjs.com/package/@algovoi/audit-verifier"> target="https://www.npmjs.com/package/@algovoi/audit-verifier"</eref>
Byte-for-byte parity with the Python verifier. MIT licensed.</t>
</li>
</ul>
<t>Cross-implementation conformance vectors are published at:</t>
<t><eref target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors"> target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors"</eref></t>
<t>The refund_receipt_v1 vector set is at vectors/refund_receipt_v1/
and includes eight byte-level reference vectors, five pair
invariants, and three chain invariants.</t>
<t>The eight-implementation cross-validation attestation records dated
2026-05-24 (JCS canonicalisation layer and RFC 9421 transport
layer) apply to refund receipts as they do to compliance receipts.</t>
</section>

<section anchor="appendix-c-acknowledgments"><name>Appendix C. Acknowledgments</name>
<t>This document, the receipt format it specifies, and the
conformance vectors derived from it are AlgoVoi-authored work.
Substrate authorship history, including production code anchored
on 2026-04-12 and the eight-implementation cross-validation
attestation records, is catalogued at
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance"> target="https://docs.algovoi.co.uk/substrate-authorship-provenance"</eref>.</t>
<t>The canonicalisation discipline pinned by Section 4 (<tt>urn:x402:
canonicalisation:jcs-rfc8785-v1</tt>) is normatively specified in
draft-hopley-x402-canonicalisation-jcs. It was originally
formalised in x402-foundation/x402 pull request #2436, authored
by the document author with subsequent review co-signatures from
seritalien (Vauban Pay, APPROVED 2026-05-22) and arian-gogani
(Arian Gogani, LGTM). The framework-bound-retention scoping
clause in that discipline was contributed by feedoracle
(FeedOracle).</t>
<t>This document is the post-settlement companion to the
admission-time compliance receipt format specified in
draft-hopley-x402-compliance-receipt-00 by the same author. The
two documents share the same canonicalisation pin, audit-chain
shape, and integer-millisecond timestamp encoding so that a
verifier walking the full payment lifecycle requires only one
implementation of the canonicalisation discipline.</t>
</section>
</back>

</rfc>
