this repo has no description attested.network/
at main 284 lines 19 kB view raw
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>Scenarios — attested.network</title> 7 <meta name="description" content="Real-world usage scenarios for attested payments on ATProtocol."> 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 &mdash; 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">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" class="active">Scenarios</a></li> 54 </ul> 55 </nav> 56 </div> 57</div> 58 59<!-- Hero --> 60<div class="hero-sm"> 61 <div class="hero-inner"> 62 <div class="breadcrumb"><a href="index.html">Home</a> / Scenarios</div> 63 <h1>Example <span>Scenarios</span></h1> 64 <p class="subtitle">Real-world usage patterns showing how attested payments work end-to-end.</p> 65 </div> 66</div> 67 68<main class="container"> 69 70 <!-- Podcast Subscription --> 71 <section id="podcast-subscription"> 72 <h2>Podcast Subscription</h2> 73 <p class="section-desc">A podcast offers a $10/month premium subscription. Supporters pay through a broker, which creates a recurring payment record with an entitlement that grants access to premium content. Any app, tile, or appview can verify the subscription by checking for an active payment with the matching entitlement.</p> 74 75 <h3>How it works</h3> 76 <p>The podcast creator publishes their content on ATProtocol and uses a broker to handle subscriptions. When a listener subscribes, three things happen:</p> 77 78 <ol class="steps"> 79 <li>The listener&rsquo;s client initiates a payment through the broker via <code>network.attested.payment.initiate</code></li> 80 <li>The broker processes the $10/month payment and writes a <code>network.attested.payment.recurring</code> record to the listener&rsquo;s repository, including an <code>entitlements</code> reference pointing to the podcast&rsquo;s product record</li> 81 <li>The broker and creator each write <code>payment.proof</code> attestation records to their own repositories, linked via the payment&rsquo;s <code>signatures</code> array</li> 82 </ol> 83 84 <p>From that point on, any app can verify the subscription by calling <code>network.attested.payment.lookup</code> with the entitlement AT-URI. No centralized subscription database needed.</p> 85 86 <div class="mermaid-wrapper"> 87 <pre class="mermaid"> 88sequenceDiagram 89 participant L as Listener's Client 90 participant B as Broker 91 participant LR as Listener's Repo 92 participant CR as Creator's Repo 93 participant BR as Broker's Repo 94 participant App as Podcast App 95 96 L->>B: network.attested.payment.initiate 97 B-->>L: { token, url } 98 L->>B: Complete payment ($10/month) 99 100 B->>LR: Write payment.recurring record 101 Note right of LR: Includes entitlements[]<br/>pointing to product record 102 103 par Attestations 104 B->>BR: Write payment.proof 105 B->>CR: Notify creator 106 CR->>CR: Write payment.proof 107 end 108 109 App->>B: network.attested.payment.lookup<br/>?payer=...&recipient=...<br/>&paymentType=...recurring<br/>&entitlements=at://...product/... 110 B-->>App: { payments: [recurring record] } 111 App->>App: Subscription verified, grant access 112 </pre> 113 </div> 114 115 <h3 style="margin-top: 40px;">The payment record</h3> 116 <p>The recurring payment record lives in the listener&rsquo;s repository. It declares the $10/month commitment, references the podcast&rsquo;s product record as an entitlement, and carries attestation signatures from both the creator and broker.</p> 117 118 <div class="code-block"> 119 <div class="code-label">Listener's repo &mdash; recurring payment</div> 120<pre><span class="hl-punc">{</span> 121 <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> 122 <span class="hl-key">"subject"</span><span class="hl-punc">:</span> <span class="hl-str">"did:plc:podcast-creator"</span><span class="hl-punc">,</span> 123 <span class="hl-key">"amount"</span><span class="hl-punc">:</span> <span class="hl-num">1000</span><span class="hl-punc">,</span> 124 <span class="hl-key">"currency"</span><span class="hl-punc">:</span> <span class="hl-str">"USD"</span><span class="hl-punc">,</span> 125 <span class="hl-key">"unit"</span><span class="hl-punc">:</span> <span class="hl-str">"monthly"</span><span class="hl-punc">,</span> 126 <span class="hl-key">"frequency"</span><span class="hl-punc">:</span> <span class="hl-num">1</span><span class="hl-punc">,</span> 127 <span class="hl-key">"txnid"</span><span class="hl-punc">:</span> <span class="hl-str">"01J6M4R5XQHV8WNBCM3G9RFBT"</span><span class="hl-punc">,</span> 128 <span class="hl-key">"createdAt"</span><span class="hl-punc">:</span> <span class="hl-str">"2026-03-01T00:00:00.000Z"</span><span class="hl-punc">,</span> 129 <span class="hl-key">"entitlements"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span> 130 <span class="hl-punc">{</span> 131 <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> 132 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:podcast-creator/com.example.podcast.subscription/premium"</span><span class="hl-punc">,</span> 133 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreig7xxgb5tcoqd3ne6gqkvrulzpfnwjmcc5fsgqjdx4huswnhzbekcc"</span> 134 <span class="hl-punc">}</span> 135 <span class="hl-punc">]</span><span class="hl-punc">,</span> 136 <span class="hl-key">"signatures"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span> 137 <span class="hl-punc">{</span> 138 <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> 139 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:podcast-creator/network.attested.payment.proof/3la8rxz3vdc4t"</span><span class="hl-punc">,</span> 140 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreigyh7s6lqf5n3xke4jt6r2x3mqkzf4wpgicbqhqg5k3vdjn7aomfe"</span> 141 <span class="hl-punc">}</span><span class="hl-punc">,</span> 142 <span class="hl-punc">{</span> 143 <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> 144 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:broker-payments/network.attested.payment.proof/3la8ry4ldsc4u"</span><span class="hl-punc">,</span> 145 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreih7wwfa3tcoqd2ne5gqkvrulzpfnwjmcc5fsgqjdx4huswnhzaehqu"</span> 146 <span class="hl-punc">}</span> 147 <span class="hl-punc">]</span> 148<span class="hl-punc">}</span></pre> 149 </div> 150 151 <h3 style="margin-top: 40px;">Verifying access</h3> 152 <p>When a listener opens the podcast in any ATProtocol app, the app checks for an active subscription by querying the broker&rsquo;s lookup endpoint. The key is filtering by both the recurring payment type and the specific entitlement.</p> 153 154 <div class="code-block"> 155 <div class="code-label">Lookup request</div> 156 <pre><span class="hl-comment">// Does this listener have an active premium subscription?</span> 157GET /xrpc/network.attested.payment.lookup 158 <span class="hl-punc">?</span><span class="hl-key">payer</span><span class="hl-punc">=</span><span class="hl-str">did:plc:listener123</span> 159 <span class="hl-punc">&amp;</span><span class="hl-key">recipient</span><span class="hl-punc">=</span><span class="hl-str">did:plc:podcast-creator</span> 160 <span class="hl-punc">&amp;</span><span class="hl-key">paymentType</span><span class="hl-punc">=</span><span class="hl-str">network.attested.payment.recurring</span> 161 <span class="hl-punc">&amp;</span><span class="hl-key">entitlements</span><span class="hl-punc">=</span><span class="hl-str">at://did:plc:podcast-creator/com.example.podcast.subscription/premium</span></pre> 162 </div> 163 164 <p>If the response contains a payment record, the listener has an active subscription and the app grants access to premium episodes. If the <code>payments</code> array is empty, the listener either hasn&rsquo;t subscribed or their subscription has lapsed.</p> 165 166 <div class="callout"> 167 <p><strong>App-agnostic verification.</strong> Because the payment record and its entitlements live on the protocol, any podcast app, tile, or appview can independently verify the subscription. The listener isn&rsquo;t locked into a single client&mdash;their subscription follows them across the ecosystem.</p> 168 </div> 169 170 <div class="callout" style="margin-top: 16px;"> 171 <p><strong>Entitlements are flexible.</strong> The <code>com.example.podcast.subscription/premium</code> record is defined by the podcast creator, not by this spec. It could contain tier details, feature flags, or access rules&mdash;whatever makes sense for the product. The payment record simply references it as a <code>strongRef</code>, linking proof of payment to what was purchased.</p> 172 </div> 173 </section> 174 175 <!-- One-Time Purchase --> 176 <section id="one-time-purchase"> 177 <h2>One-Time Purchase</h2> 178 <p class="section-desc">A user makes a one-time payment to unlock something tied to a specific recipient&mdash;a profile badge in a social app, a tip that comes with an award, downloadable content, or any other digital good. The payment is linked to an entitlement record that the app checks to gate access or display.</p> 179 180 <h3>How it works</h3> 181 <p>A user wants to support a creator and get something in return&mdash;maybe a supporter badge that appears on their profile, or access to bonus content. The app presents the option, the user pays through a broker, and the resulting payment record carries an entitlement that any app can verify.</p> 182 183 <ol class="steps"> 184 <li>The user selects a purchase option in the app (e.g. &ldquo;Buy Supporter Badge&rdquo; or &ldquo;Unlock Bonus Pack&rdquo;). The app initiates the payment via <code>network.attested.payment.initiate</code> on the creator&rsquo;s broker</li> 185 <li>The broker processes the one-time payment and writes a <code>network.attested.payment.oneTime</code> record to the payer&rsquo;s repository. The record includes an <code>entitlements</code> reference pointing to the specific product&mdash;a badge, an award, DLC content, or whatever the creator has defined</li> 186 <li>The broker and creator each write <code>payment.proof</code> attestation records to their own repositories, completing the cryptographic chain</li> 187 </ol> 188 189 <p>When any app wants to check whether the user has purchased that item, it calls <code>network.attested.payment.lookup</code> filtered by the entitlement AT-URI. If a matching one-time payment exists, the user has paid and the app renders the badge, unlocks the content, or grants whatever the entitlement represents.</p> 190 191 <div class="mermaid-wrapper"> 192 <pre class="mermaid"> 193sequenceDiagram 194 participant U as User's Client 195 participant B as Broker 196 participant UR as User's Repo 197 participant CR as Creator's Repo 198 participant BR as Broker's Repo 199 participant App as Social App 200 201 U->>B: network.attested.payment.initiate 202 B-->>U: { token, url } 203 U->>B: Complete payment (one-time) 204 205 B->>UR: Write payment.oneTime record 206 Note right of UR: Includes entitlements[]<br/>pointing to badge/product record 207 208 par Attestations 209 B->>BR: Write payment.proof 210 B->>CR: Notify creator 211 CR->>CR: Write payment.proof 212 end 213 214 App->>B: network.attested.payment.lookup<br/>?payer=...&recipient=...<br/>&entitlements=at://...badge/... 215 B-->>App: { payments: [oneTime record] } 216 App->>App: Show badge on profile 217 </pre> 218 </div> 219 220 <h3 style="margin-top: 40px;">The payment record</h3> 221 <p>The one-time payment record lives in the payer&rsquo;s repository. In this example, a user pays $5 to get a supporter badge on a creator&rsquo;s profile. The entitlement references the creator&rsquo;s badge record.</p> 222 223 <div class="code-block"> 224 <div class="code-label">Payer's repo &mdash; one-time payment</div> 225<pre><span class="hl-punc">{</span> 226 <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> 227 <span class="hl-key">"subject"</span><span class="hl-punc">:</span> <span class="hl-str">"did:plc:creator-xyz"</span><span class="hl-punc">,</span> 228 <span class="hl-key">"amount"</span><span class="hl-punc">:</span> <span class="hl-num">500</span><span class="hl-punc">,</span> 229 <span class="hl-key">"currency"</span><span class="hl-punc">:</span> <span class="hl-str">"USD"</span><span class="hl-punc">,</span> 230 <span class="hl-key">"txnid"</span><span class="hl-punc">:</span> <span class="hl-str">"01J7N5S6YRHW0XPBDN4H1UHEV"</span><span class="hl-punc">,</span> 231 <span class="hl-key">"memo"</span><span class="hl-punc">:</span> <span class="hl-str">"Supporter badge"</span><span class="hl-punc">,</span> 232 <span class="hl-key">"createdAt"</span><span class="hl-punc">:</span> <span class="hl-str">"2026-03-20T14:30:00.000Z"</span><span class="hl-punc">,</span> 233 <span class="hl-key">"entitlements"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span> 234 <span class="hl-punc">{</span> 235 <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> 236 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:creator-xyz/com.example.app.badge/supporter"</span><span class="hl-punc">,</span> 237 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreif8xxgb6tcoqd4ne7gqkvrulzpfnwjmcc6fsgqjdx5huswnhzbekdd"</span> 238 <span class="hl-punc">}</span> 239 <span class="hl-punc">]</span><span class="hl-punc">,</span> 240 <span class="hl-key">"signatures"</span><span class="hl-punc">:</span> <span class="hl-punc">[</span> 241 <span class="hl-punc">{</span> 242 <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> 243 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:creator-xyz/network.attested.payment.proof/3ld4txz5xfe5v"</span><span class="hl-punc">,</span> 244 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreigyh8s7lqf6n4xke5jt7r3x4mqkzf5wpgicbqhqg6k4vdjn8bomge"</span> 245 <span class="hl-punc">}</span><span class="hl-punc">,</span> 246 <span class="hl-punc">{</span> 247 <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> 248 <span class="hl-key">"uri"</span><span class="hl-punc">:</span> <span class="hl-str">"at://did:plc:broker-payments/network.attested.payment.proof/3ld4ty5mdtc5w"</span><span class="hl-punc">,</span> 249 <span class="hl-key">"cid"</span><span class="hl-punc">:</span> <span class="hl-str">"bafyreih8wwfa4tcoqd3ne6gqkvrulzpfnwjmcc6fsgqjdx5huswnhzafiqu"</span> 250 <span class="hl-punc">}</span> 251 <span class="hl-punc">]</span> 252<span class="hl-punc">}</span></pre> 253 </div> 254 255 <h3 style="margin-top: 40px;">Verifying the purchase</h3> 256 <p>When an app renders a user&rsquo;s profile, it checks whether the user has purchased the supporter badge for that creator by querying the lookup endpoint with the entitlement AT-URI.</p> 257 258 <div class="code-block"> 259 <div class="code-label">Lookup request</div> 260 <pre><span class="hl-comment">// Does this user have the supporter badge for this creator?</span> 261GET /xrpc/network.attested.payment.lookup 262 <span class="hl-punc">?</span><span class="hl-key">payer</span><span class="hl-punc">=</span><span class="hl-str">did:plc:user456</span> 263 <span class="hl-punc">&amp;</span><span class="hl-key">recipient</span><span class="hl-punc">=</span><span class="hl-str">did:plc:creator-xyz</span> 264 <span class="hl-punc">&amp;</span><span class="hl-key">paymentType</span><span class="hl-punc">=</span><span class="hl-str">network.attested.payment.oneTime</span> 265 <span class="hl-punc">&amp;</span><span class="hl-key">entitlements</span><span class="hl-punc">=</span><span class="hl-str">at://did:plc:creator-xyz/com.example.app.badge/supporter</span></pre> 266 </div> 267 268 <p>If the <code>payments</code> array contains a matching record, the app displays the badge on the user&rsquo;s profile. Because this is a one-time payment, it persists indefinitely&mdash;there&rsquo;s no renewal to check.</p> 269 270 <div class="callout"> 271 <p><strong>Many forms, same pattern.</strong> This scenario covers any one-time digital purchase: supporter badges, tip awards, DLC content packs, custom emoji sets, premium filters, or exclusive stickers. The entitlement record is defined by the app or creator&mdash;the payment spec just links proof of payment to whatever was purchased. Different apps can define different products, all verified the same way.</p> 272 </div> 273 </section> 274 275</main> 276 277<footer> 278 <div class="container"> 279 <p>attested.network &middot; Built on <a href="https://badge.blue">badge.blue</a> attestations &middot; <a href="https://atproto.com">ATProtocol</a></p> 280 </div> 281</footer> 282 283</body> 284</html>