this repo has no description
attested.network/
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>attested.network — Proof of Payment for ATProtocol</title>
7 <meta name="description" content="An open specification for decentralized, cryptographically verifiable proof of payments.">
8 <link rel="preconnect" href="https://fonts.googleapis.com">
9 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11 <link rel="icon" type="image/svg+xml" href="logo.svg">
12 <link rel="stylesheet" href="styles.css">
13 <script type="module">
14 import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
15 mermaid.initialize({
16 startOnLoad: true,
17 theme: 'base',
18 themeVariables: {
19 primaryColor: '#f5f3ff',
20 primaryTextColor: '#111827',
21 primaryBorderColor: '#ddd6fe',
22 secondaryColor: '#f8f9fb',
23 tertiaryColor: '#ffffff',
24 lineColor: '#8b5cf6',
25 textColor: '#111827',
26 mainBkg: '#f5f3ff',
27 nodeBorder: '#ddd6fe',
28 clusterBkg: '#faf9fc',
29 clusterBorder: '#e5e7eb',
30 fontFamily: 'Inter, -apple-system, system-ui, sans-serif',
31 fontSize: '13px'
32 }
33 });
34 </script>
35</head>
36<body>
37
38<div class="draft-banner">
39 <p><strong>Draft — Not yet published.</strong> This specification is in active development and is not ready for review or critique. Stay tuned for formal announcements.</p>
40</div>
41
42<!-- Top navigation -->
43<div class="topnav">
44 <div class="topnav-inner">
45 <a class="topnav-logo" href="/"><img src="logo.svg" alt="" class="topnav-logo-img"><span><span>attested</span>.network</span></a>
46 <nav>
47 <ul class="topnav-links">
48 <li><a href="index.html" class="active">Spec</a></li>
49 <li><a href="brokers.html">Brokers</a></li>
50 <li><a href="app-developers.html">App Developers</a></li>
51 <li><a href="recipients.html">Recipients</a></li>
52 <li><a href="payers.html">Payers</a></li>
53 <li><a href="scenarios.html">Scenarios</a></li>
54 </ul>
55 </nav>
56 </div>
57</div>
58
59<!-- Hero -->
60<div class="hero">
61 <h1>Proof of Payment<br>for <span>ATProtocol</span></h1>
62 <p class="subtitle">An open specification for decentralized, cryptographically verifiable proof of payments.</p>
63 <div class="hero-badges">
64 <a class="hero-badge" href="https://badge.blue">
65 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
66 Built on badge.blue
67 </a>
68 <a class="hero-badge" href="https://atproto.com">
69 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
70 ATProtocol
71 </a>
72 </div>
73</div>
74
75<main class="container">
76
77 <!-- Guides -->
78 <section id="guides" style="padding-bottom: 0;">
79 <h2>Documentation</h2>
80 <p class="section-desc">Guides for every role in the attested payments ecosystem.</p>
81 <div class="guide-grid">
82 <a class="guide-card" href="brokers.html">
83 <h4>Payment Brokers</h4>
84 <p>Implement a payment servicer that processes transactions and writes attestation proofs.</p>
85 <span class="guide-arrow">Read guide →</span>
86 </a>
87 <a class="guide-card" href="app-developers.html">
88 <h4>App Developers</h4>
89 <p>Integrate payment verification into your ATProtocol application.</p>
90 <span class="guide-arrow">Read guide →</span>
91 </a>
92 <a class="guide-card" href="recipients.html">
93 <h4>Recipients</h4>
94 <p>Set up your identity to accept attested payments from supporters.</p>
95 <span class="guide-arrow">Read guide →</span>
96 </a>
97 <a class="guide-card" href="payers.html">
98 <h4>Payers</h4>
99 <p>Understand how your payments are recorded, verified, and portable.</p>
100 <span class="guide-arrow">Read guide →</span>
101 </a>
102 <a class="guide-card" href="scenarios.html">
103 <h4>Scenarios</h4>
104 <p>Real-world examples showing attested payments in action.</p>
105 <span class="guide-arrow">Browse scenarios →</span>
106 </a>
107 </div>
108 </section>
109
110 <!-- Overview -->
111 <section id="overview">
112 <h2>Overview</h2>
113 <p class="section-desc">Payment proofs replace centralized payment databases with cryptographic attestation records distributed across ATProtocol repositories. Any application can independently verify a payment—no single platform controls the relationship.</p>
114
115 <h3>Three-party attestation</h3>
116 <p>Every payment creates records across three independent repositories. The supporter declares intent, the creator confirms receipt, and a broker—which facilitates and witnesses the exchange—writes its own proof. Each record is content-addressed and bound to its repository, preventing replay attacks.</p>
117
118 <div class="mermaid-wrapper">
119 <pre class="mermaid">
120graph LR
121 subgraph SR["Supporter's Repo"]
122 PAY["Payment Record<br/><i>oneTime | recurring | scheduled</i>"]
123 SIG["signatures: [strongRef, ...]"]
124 end
125
126 subgraph CR["Creator's Repo"]
127 CP["payment.proof<br/><i>Attests via CID</i>"]
128 end
129
130 subgraph BR["Broker's Repo"]
131 BP["payment.proof<br/><i>Attests via CID</i>"]
132 end
133
134 SIG -- "strongRef" --> CP
135 SIG -- "strongRef" --> BP
136 </pre>
137 </div>
138
139 <div class="card-grid">
140 <div class="card">
141 <h4>Data Ownership</h4>
142 <p>Each party controls their own records in their own repository. No single entity holds the full picture.</p>
143 </div>
144 <div class="card">
145 <h4>Cryptographic Integrity</h4>
146 <p>CID-based content addressing ensures records cannot be modified after attestation. Change the data, break the hash.</p>
147 </div>
148 <div class="card">
149 <h4>Portable Relationships</h4>
150 <p>Support relationships survive platform changes. Records live on ATProtocol’s network, not in proprietary databases.</p>
151 </div>
152 <div class="card">
153 <h4>Open Broker Model</h4>
154 <p>Any entity can serve as a broker because brokers facilitate payment. A broker might process Stripe transactions, handle peer-to-peer cash, or simply witness a virtual high-five. The role is to facilitate and witness the exchange between payer and recipient.</p>
155 </div>
156 </div>
157
158 <div class="callout" style="margin-top: 32px;">
159 <p>This spec builds on <a href="https://badge.blue">badge.blue</a>’s CID-first attestation framework. Every attestation CID is computed from the record content, metadata, and the repository DID—meaning a record copied to a different repository automatically invalidates all its attestations.</p>
160 </div>
161
162 <div class="callout" style="margin-top: 16px;">
163 <p><strong>Public & private proofs.</strong> Payment records and proofs can live in a user’s public repository for open verification, or within a <a href="https://dholms.leaflet.pub/3mhj6bcqats2o">Permissioned Data Space</a> for private access. The implementation is effectively identical in both cases—the same attestation mechanics, CID binding, and strongRef signatures apply. The only difference is that the payment servicer additionally manages creation of the permissioned space in the payer’s repository and ensures all parties (creator, broker) have appropriate read access and permissions.</p>
164 </div>
165
166 <h3 style="margin-top: 32px;">Payment Intent</h3>
167 <p>When a recipient wants to accept a payment, a structured discovery and initiation flow connects payer, recipient, and payment servicer:</p>
168
169 <ol class="steps">
170 <li>The <strong>recipient</strong> signals which payment servicers they use by publishing an ordered list of DIDs that have a <code>#AttestedNetwork</code> service endpoint in their DID document</li>
171 <li>The <strong>payer’s client</strong> resolves these DIDs and presents the available servicers. The payer selects which one to use</li>
172 <li>The payer’s client makes an <strong>authenticated request</strong> (using inter-service authentication) to <code>network.attested.payment.initiate</code> on the selected servicer, passing the product identifier. The response includes a <strong>token</strong> and a <strong>URL</strong></li>
173 <li>The payer is <strong>directed through a browser</strong> to the URL to complete the payment process (entering payment details, confirming terms, etc.)</li>
174 <li>The payer’s client polls <code>network.attested.payment.status</code> with the token. The response is either a <strong>strongRef</strong> pointing to the completed payment record, or a <strong>failed</strong> status</li>
175 </ol>
176
177 <div class="mermaid-wrapper">
178 <pre class="mermaid">
179sequenceDiagram
180 participant P as Payer's Client
181 participant R as Recipient
182 participant S as Payment Servicer
183 participant B as Browser
184
185 P->>R: Resolve DID document
186 R-->>P: Service endpoints with #AttestedNetwork DIDs
187 P->>P: Select servicer from list
188
189 P->>S: network.attested.payment.initiate (authenticated)
190 Note right of P: Sends product identifier
191 S-->>P: { token, url }
192
193 P->>B: Redirect payer to URL
194 B->>S: Complete payment flow
195 S-->>B: Payment confirmed
196
197 P->>S: network.attested.payment.status (token)
198 S-->>P: { strongRef } or { failed }
199 </pre>
200 </div>
201
202 <h3 style="margin-top: 32px;">Verification</h3>
203 <p>Any application can verify a payment by checking the cryptographic chain:</p>
204 <ol class="steps">
205 <li>Strip the <code>signatures</code> array from the payment record</li>
206 <li>Prepare attestation metadata—add the repository DID, strip <code>cid</code> and <code>signature</code> fields</li>
207 <li>Insert metadata as the <code>$sig</code> field, serialize to DAG-CBOR</li>
208 <li>Hash with SHA-256 and wrap as CIDv1 (codec <code>0x71</code>)</li>
209 <li>Fetch proof records via <code>strongRef</code> URIs and confirm CIDs match</li>
210 </ol>
211
212 <h3 style="margin-top: 32px;">Trust Models</h3>
213 <p>Applications can implement different validation strategies:</p>
214 <ul class="trust-list">
215 <li><strong>Strict</strong> <span>Require proofs from both the creator and a specific trusted broker. Highest assurance.</span></li>
216 <li><strong>Creator-Trusted</strong> <span>Accept any payment the creator has attested. Simpler, trusts creators to vouch for supporters.</span></li>
217 <li><strong>Federated</strong> <span>Accept attestations from a set of trusted brokers. Enables regional verification networks.</span></li>
218 </ul>
219 </section>
220
221 <!-- Lexicon -->
222 <section id="lexicon">
223 <h2>Lexicon</h2>
224 <p class="section-desc">Four record types and three XRPC methods define the payment specification. Payment records live in the supporter’s repository and carry a <code>signatures</code> array referencing proof records from creators and brokers.</p>
225
226 <!-- oneTime -->
227 <div class="lexicon-block">
228 <div class="lexicon-header">
229 <div class="lexicon-tag">Record</div>
230 <div class="lexicon-name">network.attested.payment.oneTime</div>
231 <p class="lexicon-desc">A one-time payment from a supporter to a creator. Represents a single, non-recurring financial transaction attested by one or more parties.</p>
232 </div>
233 <div class="lexicon-body">
234 <table class="schema-table">
235 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
236 <tbody>
237 <tr><td class="field-name">subject</td><td class="field-type">string <span class="constraint">(did)</span></td><td class="field-desc">DID of the creator receiving payment</td></tr>
238 <tr><td class="field-name">amount</td><td class="field-type">integer</td><td class="field-desc">Payment amount in smallest currency unit (e.g. cents). Min: 1</td></tr>
239 <tr><td class="field-name">currency</td><td class="field-type">string</td><td class="field-desc">ISO 4217 currency code (e.g. <code>USD</code>, <code>EUR</code>)</td></tr>
240 <tr><td class="field-name">txnid</td><td class="field-type">string</td><td class="field-desc">Unique transaction identifier for deduplication</td></tr>
241 <tr><td class="field-name">memo</td><td class="field-type">string</td><td class="field-desc">Optional note from the supporter. Max 256 chars</td></tr>
242 <tr><td class="field-name">createdAt</td><td class="field-type">string <span class="constraint">(datetime)</span></td><td class="field-desc">Timestamp of record creation</td></tr>
243 <tr><td class="field-name">entitlements</td><td class="field-type">array(<code>com.atproto.repo.strongRef</code>)</td><td class="field-desc">Optional list of strong references to records representing any goods or services the payer is entitled to as a result of this payment</td></tr>
244 <tr><td class="field-name">signatures</td><td class="field-type">array</td><td class="field-desc">Attestation entries (inline or <code>com.atproto.repo.strongRef</code>)</td></tr>
245 </tbody>
246 </table>
247 </div>
248 </div>
249
250 <div class="callout">
251 <p><strong>Entitlements.</strong> The <code>entitlements</code> field is an optional array of <code>com.atproto.repo.strongRef</code> objects. Each reference points to a record representing a good or service the payer is entitled to as a result of this payment. The referenced records can use any lexicon—they are not defined by this spec. This allows brokers, recipients, or third parties to define their own product or access records and link them directly to the payment that granted them.</p>
252 </div>
253
254 <!-- recurring -->
255 <div class="lexicon-block">
256 <div class="lexicon-header">
257 <div class="lexicon-tag">Record</div>
258 <div class="lexicon-name">network.attested.payment.recurring</div>
259 <p class="lexicon-desc">A recurring payment commitment. Immutable once created—supporters cancel and create new subscriptions to change terms. Bills on anniversary dates with automatic retry on failure.</p>
260 </div>
261 <div class="lexicon-body">
262 <table class="schema-table">
263 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
264 <tbody>
265 <tr><td class="field-name">subject</td><td class="field-type">string <span class="constraint">(did)</span></td><td class="field-desc">DID of the creator receiving payment</td></tr>
266 <tr><td class="field-name">amount</td><td class="field-type">integer</td><td class="field-desc">Amount per billing period in smallest currency unit. Min: 500, Max: 25000 (monthly equivalent)</td></tr>
267 <tr><td class="field-name">currency</td><td class="field-type">string</td><td class="field-desc">ISO 4217 currency code</td></tr>
268 <tr><td class="field-name">unit</td><td class="field-type">string</td><td class="field-desc">Billing period: <code>monthly</code> | <code>quarterly</code> | <code>semiannual</code> | <code>yearly</code></td></tr>
269 <tr><td class="field-name">frequency</td><td class="field-type">integer</td><td class="field-desc">Billing frequency multiplier. Default: 1, Min: 1</td></tr>
270 <tr><td class="field-name">txnid</td><td class="field-type">string</td><td class="field-desc">Unique transaction identifier for deduplication</td></tr>
271 <tr><td class="field-name">createdAt</td><td class="field-type">string <span class="constraint">(datetime)</span></td><td class="field-desc">Timestamp of initial subscription creation</td></tr>
272 <tr><td class="field-name">entitlements</td><td class="field-type">array(<code>com.atproto.repo.strongRef</code>)</td><td class="field-desc">Optional list of strong references to records representing any goods or services the payer is entitled to as a result of this payment</td></tr>
273 <tr><td class="field-name">signatures</td><td class="field-type">array</td><td class="field-desc">Attestation entries (inline or <code>com.atproto.repo.strongRef</code>)</td></tr>
274 </tbody>
275 </table>
276 </div>
277 </div>
278
279 <!-- scheduled -->
280 <div class="lexicon-block">
281 <div class="lexicon-header">
282 <div class="lexicon-tag">Record</div>
283 <div class="lexicon-name">network.attested.payment.scheduled</div>
284 <p class="lexicon-desc">A fixed series of payments. Unlike recurring payments that continue indefinitely, scheduled payments specify a total count and terminate automatically upon completion.</p>
285 </div>
286 <div class="lexicon-body">
287 <table class="schema-table">
288 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
289 <tbody>
290 <tr><td class="field-name">subject</td><td class="field-type">string <span class="constraint">(did)</span></td><td class="field-desc">DID of the creator receiving payment</td></tr>
291 <tr><td class="field-name">amount</td><td class="field-type">integer</td><td class="field-desc">Amount per payment in smallest currency unit</td></tr>
292 <tr><td class="field-name">currency</td><td class="field-type">string</td><td class="field-desc">ISO 4217 currency code</td></tr>
293 <tr><td class="field-name">unit</td><td class="field-type">string</td><td class="field-desc">Interval: <code>monthly</code> | <code>quarterly</code> | <code>semiannual</code> | <code>yearly</code></td></tr>
294 <tr><td class="field-name">count</td><td class="field-type">integer</td><td class="field-desc">Total number of scheduled payments. Min: 2, Max: 60</td></tr>
295 <tr><td class="field-name">txnid</td><td class="field-type">string</td><td class="field-desc">Unique transaction identifier for deduplication</td></tr>
296 <tr><td class="field-name">createdAt</td><td class="field-type">string <span class="constraint">(datetime)</span></td><td class="field-desc">Timestamp of schedule creation; first payment date</td></tr>
297 <tr><td class="field-name">entitlements</td><td class="field-type">array(<code>com.atproto.repo.strongRef</code>)</td><td class="field-desc">Optional list of strong references to records representing any goods or services the payer is entitled to as a result of this payment</td></tr>
298 <tr><td class="field-name">signatures</td><td class="field-type">array</td><td class="field-desc">Attestation entries (inline or <code>com.atproto.repo.strongRef</code>)</td></tr>
299 </tbody>
300 </table>
301 </div>
302 </div>
303
304 <!-- proof -->
305 <div class="lexicon-block">
306 <div class="lexicon-header">
307 <div class="lexicon-tag">Record</div>
308 <div class="lexicon-name">network.attested.payment.proof</div>
309 <p class="lexicon-desc">A remote attestation record stored in the attestor’s repository (creator or broker). Referenced via <code>com.atproto.repo.strongRef</code> in the payment record’s <code>signatures</code> array.</p>
310 </div>
311 <div class="lexicon-body">
312 <table class="schema-table">
313 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
314 <tbody>
315 <tr><td class="field-name">cid</td><td class="field-type">string <span class="constraint">(cid)</span></td><td class="field-desc">Attestation CID computed per the <a href="https://badge.blue">badge.blue</a> spec from the payment record, metadata, and repository DID</td></tr>
316 <tr><td class="field-name">status</td><td class="field-type">string</td><td class="field-desc">Optional status indicator for the attestation</td></tr>
317 </tbody>
318 </table>
319 </div>
320 </div>
321
322 <!-- lookup -->
323 <div class="lexicon-block">
324 <div class="lexicon-header">
325 <div class="lexicon-tag">Query (HTTP GET)</div>
326 <div class="lexicon-name">network.attested.payment.lookup</div>
327 <p class="lexicon-desc">Look up verified payment records between a payer and recipient. Returns only records whose attestations have been cryptographically verified. Results may include any combination of <code>oneTime</code>, <code>recurring</code>, and <code>scheduled</code> payment records.</p>
328 </div>
329 <div class="lexicon-body">
330 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Parameters</h4>
331 <table class="schema-table">
332 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
333 <tbody>
334 <tr><td class="field-name">payer</td><td class="field-type">string <span class="constraint">(did, required)</span></td><td class="field-desc">DID of the payer (supporter)</td></tr>
335 <tr><td class="field-name">recipient</td><td class="field-type">string <span class="constraint">(did, required)</span></td><td class="field-desc">DID of the recipient (creator)</td></tr>
336 <tr><td class="field-name">paymentType</td><td class="field-type">string</td><td class="field-desc">Optional filter by payment collection. Must be a full NSID: <code>network.attested.payment.oneTime</code>, <code>network.attested.payment.recurring</code>, or <code>network.attested.payment.scheduled</code></td></tr>
337 <tr><td class="field-name">brokers</td><td class="field-type">array(string) <span class="constraint">(did, optional, repeating)</span></td><td class="field-desc">Optional list of broker DIDs. When provided, only returns payments that have at least one validating signature from an identity in this list</td></tr>
338 <tr><td class="field-name">entitlements</td><td class="field-type">array(string) <span class="constraint">(at-uri, optional, repeating)</span></td><td class="field-desc">Optional list of entitlement AT-URIs. When provided, only returns payments whose <code>entitlements</code> array contains one or more of the given references</td></tr>
339 </tbody>
340 </table>
341
342 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Response</h4>
343 <table class="schema-table">
344 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
345 <tbody>
346 <tr><td class="field-name">payments</td><td class="field-type">array(union)</td><td class="field-desc">List of verified payment records. Each element is a union of <code>network.attested.payment.oneTime</code>, <code>network.attested.payment.recurring</code>, or <code>network.attested.payment.scheduled</code></td></tr>
347 </tbody>
348 </table>
349 </div>
350 </div>
351
352 <!-- initiate -->
353 <div class="lexicon-block">
354 <div class="lexicon-header">
355 <div class="lexicon-tag">Procedure (HTTP POST)</div>
356 <div class="lexicon-name">network.attested.payment.initiate</div>
357 <p class="lexicon-desc">Begin a payment flow. Called by the payer’s client against the selected payment servicer using inter-service authentication. Returns a token for status polling and a URL to direct the payer through the payment process.</p>
358 </div>
359 <div class="lexicon-body">
360 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Input</h4>
361 <table class="schema-table">
362 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
363 <tbody>
364 <tr><td class="field-name">product</td><td class="field-type">string <span class="constraint">(required)</span></td><td class="field-desc">Product identifier for the payment being initiated</td></tr>
365 </tbody>
366 </table>
367
368 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Response</h4>
369 <table class="schema-table">
370 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
371 <tbody>
372 <tr><td class="field-name">token</td><td class="field-type">string</td><td class="field-desc">Opaque token used to poll payment status via <code>payment.status</code></td></tr>
373 <tr><td class="field-name">url</td><td class="field-type">string <span class="constraint">(uri)</span></td><td class="field-desc">URL to direct the payer to in a browser to complete the payment</td></tr>
374 </tbody>
375 </table>
376 </div>
377 </div>
378
379 <!-- status -->
380 <div class="lexicon-block">
381 <div class="lexicon-header">
382 <div class="lexicon-tag">Query (HTTP GET)</div>
383 <div class="lexicon-name">network.attested.payment.status</div>
384 <p class="lexicon-desc">Check the status of a payment initiated via <code>payment.initiate</code>. Returns either a <code>com.atproto.repo.strongRef</code> pointing to the completed payment record, or a failed status.</p>
385 </div>
386 <div class="lexicon-body">
387 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Parameters</h4>
388 <table class="schema-table">
389 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
390 <tbody>
391 <tr><td class="field-name">token</td><td class="field-type">string <span class="constraint">(required)</span></td><td class="field-desc">Token returned from <code>payment.initiate</code></td></tr>
392 </tbody>
393 </table>
394
395 <h4 style="font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin: 20px 0 4px;">Response</h4>
396 <table class="schema-table">
397 <thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
398 <tbody>
399 <tr><td class="field-name">status</td><td class="field-type">string</td><td class="field-desc"><code>pending</code> | <code>completed</code> | <code>failed</code></td></tr>
400 <tr><td class="field-name">ref</td><td class="field-type">com.atproto.repo.strongRef</td><td class="field-desc">Present when status is <code>completed</code>. Points to the attested payment record in the payer’s repository</td></tr>
401 </tbody>
402 </table>
403 </div>
404 </div>
405 </section>
406
407 <!-- Examples -->
408 <section id="examples">
409 <h2>Examples</h2>
410 <p class="section-desc">Complete record examples showing how attested payments work in practice, using <a href="https://badge.blue">badge.blue</a> remote attestations with <code>com.atproto.repo.strongRef</code> entries.</p>
411
412 <!-- Example 1: One-time tip -->
413 <h3>One-time tip with dual attestation</h3>
414 <p>A supporter sends a $25 tip to a creator. Both the creator and broker independently attest the payment by writing proof records to their own repositories.</p>
415
416 <div class="code-block">
417 <div class="code-label">Supporter's repo — payment record</div>
418<pre><span class="hl-punc">{</span>
419 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"network.attested.payment.oneTime"</span><span class="hl-punc">,</span>
420 <span class="hl-key">"subject"</span><span class="hl-punc">:</span> <span class="hl-str">"did:plc:v5jkrb2oncmnhc7rtqhrdzwi"</span><span class="hl-punc">,</span>
421 <span class="hl-key">"amount"</span><span class="hl-punc">:</span> <span class="hl-num">2500</span><span class="hl-punc">,</span>
422 <span class="hl-key">"currency"</span><span class="hl-punc">:</span> <span class="hl-str">"USD"</span><span class="hl-punc">,</span>
423 <span class="hl-key">"txnid"</span><span class="hl-punc">:</span> <span class="hl-str">"01J5K9P3XQHV7WNBCM2G8RFAT"</span><span class="hl-punc">,</span>
424 <span class="hl-key">"memo"</span><span class="hl-punc">:</span> <span class="hl-str">"Great stream, keep it up!"</span><span class="hl-punc">,</span>
425 <span class="hl-key">"createdAt"</span><span class="hl-punc">:</span> <span class="hl-str">"2025-07-14T19:22:00.000Z"</span><span class="hl-punc">,</span>
426 <span class="hl-key">"signatures"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span>
427 <span class="hl-punc">{</span>
428 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
429 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:v5jkrb2oncmnhc7rtqhrdzwi/network.attested.payment.proof/3la7qxz2vbc2s"</span><span class="hl-punc">,</span>
430 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreigyh7s6lqf5n3xke4jt6r2x3mqkzf4wpgicbqhqg5k3vdjn7aomfe"</span>
431 <span class="hl-punc">}</span><span class="hl-punc">,</span>
432 <span class="hl-punc">{</span>
433 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
434 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:broker-payments-xyz/network.attested.payment.proof/3la7qy2kbrc2t"</span><span class="hl-punc">,</span>
435 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreih7wwfa3tcoqd2ne5gqkvrulzpfnwjmcc5fsgqjdx4huswnhzaehqu"</span>
436 <span class="hl-punc">}</span>
437 <span class="hl-punc">]</span>
438<span class="hl-punc">}</span></pre>
439 </div>
440
441 <div class="code-block">
442 <div class="code-label">Creator's repo — proof record</div>
443<pre><span class="hl-punc">{</span>
444 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"network.attested.payment.proof"</span><span class="hl-punc">,</span>
445 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreifdw3gy6ef4mcep5forx72cilu6wbsvuajkgsxnluqemkpa5xvzrwu"</span>
446<span class="hl-punc">}</span></pre>
447 </div>
448
449 <div class="callout">
450 <p><strong>How the CID binds to the repo:</strong> The proof’s <code>cid</code> field is computed from the payment record with the supporter’s DID baked into the <code>$sig</code> metadata. If someone copies the payment record to a different repository, recomputing the CID produces a different value—verification fails automatically.</p>
451 </div>
452
453 <!-- Example 2: Monthly recurring -->
454 <h3 style="margin-top: 40px;">Monthly recurring subscription</h3>
455 <p>A $10/month recurring support commitment. The record is immutable—to change the amount, the supporter cancels and creates a new subscription.</p>
456
457 <div class="code-block">
458 <div class="code-label">Supporter's repo — recurring payment</div>
459<pre><span class="hl-punc">{</span>
460 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"network.attested.payment.recurring"</span><span class="hl-punc">,</span>
461 <span class="hl-key">"subject"</span><span class="hl-punc">:</span> <span class="hl-str">"did:plc:v5jkrb2oncmnhc7rtqhrdzwi"</span><span class="hl-punc">,</span>
462 <span class="hl-key">"amount"</span><span class="hl-punc">:</span> <span class="hl-num">1000</span><span class="hl-punc">,</span>
463 <span class="hl-key">"currency"</span><span class="hl-punc">:</span> <span class="hl-str">"USD"</span><span class="hl-punc">,</span>
464 <span class="hl-key">"unit"</span><span class="hl-punc">:</span> <span class="hl-str">"monthly"</span><span class="hl-punc">,</span>
465 <span class="hl-key">"frequency"</span><span class="hl-punc">:</span> <span class="hl-num">1</span><span class="hl-punc">,</span>
466 <span class="hl-key">"txnid"</span><span class="hl-punc">:</span> <span class="hl-str">"01J5KBR4WMHV8XNBDM3G9SFBT"</span><span class="hl-punc">,</span>
467 <span class="hl-key">"createdAt"</span><span class="hl-punc">:</span> <span class="hl-str">"2025-08-01T00:00:00.000Z"</span><span class="hl-punc">,</span>
468 <span class="hl-key">"entitlements"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span>
469 <span class="hl-punc">{</span>
470 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
471 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:v5jkrb2oncmnhc7rtqhrdzwi/com.example.product/3miemuswqbyiw"</span><span class="hl-punc">,</span>
472 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreik3xxgb5tcoqd3ne6gqkvrulzpfnwjmcc5fsgqjdx4huswnhzbekaa"</span>
473 <span class="hl-punc">}</span>
474 <span class="hl-punc">]</span><span class="hl-punc">,</span>
475 <span class="hl-key">"signatures"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span>
476 <span class="hl-punc">{</span>
477 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
478 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:v5jkrb2oncmnhc7rtqhrdzwi/network.attested.payment.proof/3lb2rxz3vdc3t"</span><span class="hl-punc">,</span>
479 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreigyh7s6lqf5n3xke4jt6r2x3mqkzf4wpgicbqhqg5k3vdjn7aomfe"</span>
480 <span class="hl-punc">}</span><span class="hl-punc">,</span>
481 <span class="hl-punc">{</span>
482 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
483 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:broker-payments-xyz/network.attested.payment.proof/3lb2ry4ldsc3u"</span><span class="hl-punc">,</span>
484 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreih7wwfa3tcoqd2ne5gqkvrulzpfnwjmcc5fsgqjdx4huswnhzaehqu"</span>
485 <span class="hl-punc">}</span>
486 <span class="hl-punc">]</span>
487<span class="hl-punc">}</span></pre>
488 </div>
489
490 <!-- Example 3: Scheduled payments -->
491 <h3 style="margin-top: 40px;">Scheduled payment series</h3>
492 <p>Six monthly payments of $50 each, terminating automatically after the final installment. Useful for project-based sponsorships or fixed commitments.</p>
493
494 <div class="code-block">
495 <div class="code-label">Supporter's repo — scheduled payment</div>
496<pre><span class="hl-punc">{</span>
497 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"network.attested.payment.scheduled"</span><span class="hl-punc">,</span>
498 <span class="hl-key">"subject"</span><span class="hl-punc">:</span> <span class="hl-str">"did:plc:v5jkrb2oncmnhc7rtqhrdzwi"</span><span class="hl-punc">,</span>
499 <span class="hl-key">"amount"</span><span class="hl-punc">:</span> <span class="hl-num">5000</span><span class="hl-punc">,</span>
500 <span class="hl-key">"currency"</span><span class="hl-punc">:</span> <span class="hl-str">"USD"</span><span class="hl-punc">,</span>
501 <span class="hl-key">"unit"</span><span class="hl-punc">:</span> <span class="hl-str">"monthly"</span><span class="hl-punc">,</span>
502 <span class="hl-key">"count"</span><span class="hl-punc">:</span> <span class="hl-num">6</span><span class="hl-punc">,</span>
503 <span class="hl-key">"txnid"</span><span class="hl-punc">:</span> <span class="hl-str">"01J5KCS5XRHW9YOCEN4H0TGCU"</span><span class="hl-punc">,</span>
504 <span class="hl-key">"createdAt"</span><span class="hl-punc">:</span> <span class="hl-str">"2025-09-01T00:00:00.000Z"</span><span class="hl-punc">,</span>
505 <span class="hl-key">"signatures"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span>
506 <span class="hl-punc">{</span>
507 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"com.atproto.repo.strongRef"</span><span class="hl-punc">,</span>
508 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:broker-payments-xyz/network.attested.payment.proof/3lc3syz4wec4u"</span><span class="hl-punc">,</span>
509 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreif4xxgb5tcoqd3ne6gqkvrulzpfnwjmcc5fsgqjdx4huswnhzbekru"</span>
510 <span class="hl-punc">}</span>
511 <span class="hl-punc">]</span>
512<span class="hl-punc">}</span></pre>
513 </div>
514
515 <!-- Example 4: Broker proof -->
516 <h3 style="margin-top: 40px;">Broker proof record</h3>
517 <p>The broker’s independent attestation, stored in their own repository. This is the record referenced by the second <code>strongRef</code> in the examples above.</p>
518
519 <div class="code-block">
520 <div class="code-label">Broker's repo — proof record</div>
521<pre><span class="hl-punc">{</span>
522 <span class="hl-key">"$type"</span><span class="hl-punc">:</span> <span class="hl-str">"network.attested.payment.proof"</span><span class="hl-punc">,</span>
523 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreih7wwfa3tcoqd2ne5gqkvrulzpfnwjmcc5fsgqjdx4huswnhzaehqu"</span>
524<span class="hl-punc">}</span></pre>
525 </div>
526
527 <!-- Verification flow diagram -->
528 <h3 style="margin-top: 40px;">Verification flow</h3>
529 <p>How an application verifies a one-time payment with dual attestation:</p>
530
531 <div class="mermaid-wrapper">
532 <pre class="mermaid">
533sequenceDiagram
534 participant App as Verifying App
535 participant S as Supporter's Repo
536 participant C as Creator's Repo
537 participant B as Broker's Repo
538
539 App->>S: Fetch payment record
540 S-->>App: payment.oneTime + signatures[]
541
542 par Verify creator attestation
543 App->>C: Fetch proof via strongRef URI
544 C-->>App: payment.proof (cid)
545 App->>App: Recompute CID from payment + supporter DID
546 App->>App: Confirm CID matches proof.cid
547 and Verify broker attestation
548 App->>B: Fetch proof via strongRef URI
549 B-->>App: payment.proof (cid)
550 App->>App: Recompute CID from payment + supporter DID
551 App->>App: Confirm CID matches proof.cid
552 end
553
554 App->>App: Payment verified ✓
555 </pre>
556 </div>
557 </section>
558
559</main>
560
561<footer>
562 <div class="container">
563 <p>attested.network · Built on <a href="https://badge.blue">badge.blue</a> attestations · <a href="https://atproto.com">ATProtocol</a></p>
564 </div>
565</footer>
566
567</body>
568</html>