Draft — Not yet published. This specification is in active development and is not ready for review or critique. Stay tuned for formal announcements.

Example Scenarios

Real-world usage patterns showing how attested payments work end-to-end.

Podcast Subscription

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.

How it works

The podcast creator publishes their content on ATProtocol and uses a broker to handle subscriptions. When a listener subscribes, three things happen:

  1. The listener’s client initiates a payment through the broker via network.attested.payment.initiate
  2. The broker processes the $10/month payment and writes a network.attested.payment.recurring record to the listener’s repository, including an entitlements reference pointing to the podcast’s product record
  3. The broker and creator each write payment.proof attestation records to their own repositories, linked via the payment’s signatures array

From that point on, any app can verify the subscription by calling network.attested.payment.lookup with the entitlement AT-URI. No centralized subscription database needed.

sequenceDiagram
    participant L as Listener's Client
    participant B as Broker
    participant LR as Listener's Repo
    participant CR as Creator's Repo
    participant BR as Broker's Repo
    participant App as Podcast App

    L->>B: network.attested.payment.initiate
    B-->>L: { token, url }
    L->>B: Complete payment ($10/month)

    B->>LR: Write payment.recurring record
    Note right of LR: Includes entitlements[]
pointing to product record par Attestations B->>BR: Write payment.proof B->>CR: Notify creator CR->>CR: Write payment.proof end App->>B: network.attested.payment.lookup
?payer=...&recipient=...
&paymentType=...recurring
&entitlements=at://...product/... B-->>App: { payments: [recurring record] } App->>App: Subscription verified, grant access

The payment record

The recurring payment record lives in the listener’s repository. It declares the $10/month commitment, references the podcast’s product record as an entitlement, and carries attestation signatures from both the creator and broker.

Listener's repo — recurring payment
{
  "$type": "network.attested.payment.recurring",
  "subject": "did:plc:podcast-creator",
  "amount": 1000,
  "currency": "USD",
  "unit": "monthly",
  "frequency": 1,
  "txnid": "01J6M4R5XQHV8WNBCM3G9RFBT",
  "createdAt": "2026-03-01T00:00:00.000Z",
  "entitlements": [
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:podcast-creator/com.example.podcast.subscription/premium",
      "cid": "bafyreig7xxgb5tcoqd3ne6gqkvrulzpfnwjmcc5fsgqjdx4huswnhzbekcc"
    }
  ],
  "signatures": [
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:podcast-creator/network.attested.payment.proof/3la8rxz3vdc4t",
      "cid": "bafyreigyh7s6lqf5n3xke4jt6r2x3mqkzf4wpgicbqhqg5k3vdjn7aomfe"
    },
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:broker-payments/network.attested.payment.proof/3la8ry4ldsc4u",
      "cid": "bafyreih7wwfa3tcoqd2ne5gqkvrulzpfnwjmcc5fsgqjdx4huswnhzaehqu"
    }
  ]
}

Verifying access

When a listener opens the podcast in any ATProtocol app, the app checks for an active subscription by querying the broker’s lookup endpoint. The key is filtering by both the recurring payment type and the specific entitlement.

Lookup request
// Does this listener have an active premium subscription?
GET /xrpc/network.attested.payment.lookup
  ?payer=did:plc:listener123
  &recipient=did:plc:podcast-creator
  &paymentType=network.attested.payment.recurring
  &entitlements=at://did:plc:podcast-creator/com.example.podcast.subscription/premium

If the response contains a payment record, the listener has an active subscription and the app grants access to premium episodes. If the payments array is empty, the listener either hasn’t subscribed or their subscription has lapsed.

App-agnostic verification. 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’t locked into a single client—their subscription follows them across the ecosystem.

Entitlements are flexible. The com.example.podcast.subscription/premium record is defined by the podcast creator, not by this spec. It could contain tier details, feature flags, or access rules—whatever makes sense for the product. The payment record simply references it as a strongRef, linking proof of payment to what was purchased.

One-Time Purchase

A user makes a one-time payment to unlock something tied to a specific recipient—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.

How it works

A user wants to support a creator and get something in return—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.

  1. The user selects a purchase option in the app (e.g. “Buy Supporter Badge” or “Unlock Bonus Pack”). The app initiates the payment via network.attested.payment.initiate on the creator’s broker
  2. The broker processes the one-time payment and writes a network.attested.payment.oneTime record to the payer’s repository. The record includes an entitlements reference pointing to the specific product—a badge, an award, DLC content, or whatever the creator has defined
  3. The broker and creator each write payment.proof attestation records to their own repositories, completing the cryptographic chain

When any app wants to check whether the user has purchased that item, it calls network.attested.payment.lookup 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.

sequenceDiagram
    participant U as User's Client
    participant B as Broker
    participant UR as User's Repo
    participant CR as Creator's Repo
    participant BR as Broker's Repo
    participant App as Social App

    U->>B: network.attested.payment.initiate
    B-->>U: { token, url }
    U->>B: Complete payment (one-time)

    B->>UR: Write payment.oneTime record
    Note right of UR: Includes entitlements[]
pointing to badge/product record par Attestations B->>BR: Write payment.proof B->>CR: Notify creator CR->>CR: Write payment.proof end App->>B: network.attested.payment.lookup
?payer=...&recipient=...
&entitlements=at://...badge/... B-->>App: { payments: [oneTime record] } App->>App: Show badge on profile

The payment record

The one-time payment record lives in the payer’s repository. In this example, a user pays $5 to get a supporter badge on a creator’s profile. The entitlement references the creator’s badge record.

Payer's repo — one-time payment
{
  "$type": "network.attested.payment.oneTime",
  "subject": "did:plc:creator-xyz",
  "amount": 500,
  "currency": "USD",
  "txnid": "01J7N5S6YRHW0XPBDN4H1UHEV",
  "memo": "Supporter badge",
  "createdAt": "2026-03-20T14:30:00.000Z",
  "entitlements": [
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:creator-xyz/com.example.app.badge/supporter",
      "cid": "bafyreif8xxgb6tcoqd4ne7gqkvrulzpfnwjmcc6fsgqjdx5huswnhzbekdd"
    }
  ],
  "signatures": [
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:creator-xyz/network.attested.payment.proof/3ld4txz5xfe5v",
      "cid": "bafyreigyh8s7lqf6n4xke5jt7r3x4mqkzf5wpgicbqhqg6k4vdjn8bomge"
    },
    {
      "$type": "com.atproto.repo.strongRef",
      "uri": "at://did:plc:broker-payments/network.attested.payment.proof/3ld4ty5mdtc5w",
      "cid": "bafyreih8wwfa4tcoqd3ne6gqkvrulzpfnwjmcc6fsgqjdx5huswnhzafiqu"
    }
  ]
}

Verifying the purchase

When an app renders a user’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.

Lookup request
// Does this user have the supporter badge for this creator?
GET /xrpc/network.attested.payment.lookup
  ?payer=did:plc:user456
  &recipient=did:plc:creator-xyz
  &paymentType=network.attested.payment.oneTime
  &entitlements=at://did:plc:creator-xyz/com.example.app.badge/supporter

If the payments array contains a matching record, the app displays the badge on the user’s profile. Because this is a one-time payment, it persists indefinitely—there’s no renewal to check.

Many forms, same pattern. 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—the payment spec just links proof of payment to whatever was purchased. Different apps can define different products, all verified the same way.