Excited about a cross-application payment spec on atproto, happy to see that moving forward! I have one piece of recurring confusion with the CID-without-signature scheme – I guess this is badge.blue – so I figured I’d take the chance to write out a strawman proposal for a very simple payment record. Please poke holes in this until I realize what I’m missing!
Scenario: I’m (did:plc:iameli) buying a goose sticker from @goose.art (did:plc:goose) over Stripe (did:web:stripe.com) for $5.00. In this scenario we’re imagining Stripe is all-in on atproto and facilitating atproto-native payments, I guess.
My simplified spec involves all three participants in the exchange: broker, recipient, and payer, writing the same record to the same rkey. So the following will be a com.iameli.money.payment record. I’ve copied as much as possible from network.attested.payment.oneTime to try and make the comparison as clear as possible. The following record (with cid=bafyreiamlxptjneem5b7tuwnrjt36urnlcdpcdogjippqptuqwkklmchkq) is written to these three locations:
at://did:plc:iameli/com.iameli.money.payment/01J7N5S6YRHW0XPBDN4H1UHEVat://did:plc:goose/com.iameli.money.payment/01J7N5S6YRHW0XPBDN4H1UHEVat://did:web:stripe.com/com.iameli.money.payment/01J7N5S6YRHW0XPBDN4H1UHEV
{
"$type": "com.iameli.money.payment",
"payer": "did:plc:iameli",
"recipient": "did:plc:goose",
"broker": "did:web:stripe.com",
"amount": 500,
"currency": "USD",
"txnid": "01J7N5S6YRHW0XPBDN4H1UHEV",
"memo": "Goose sticker",
"createdAt": "2026-03-20T14:30:00.000Z",
"entitlements": [
{
"$type": "com.atproto.repo.strongRef",
"uri": "at://did:plc:goose/com.example.sticker/funny-goose-sticker",
"cid": "bafyreif8xxgb6tcoqd4ne7gqkvrulzpfnwjmcc6fsgqjdx5huswnhzbekdd"
}
]
}
So now all three of us have the same record at the same rkey. Verifying that we all agree is trivial: in the happy case, all three repos referenced in payer, recipient, and broker all have precisely the same CID; just check those three and you know that everyone agrees. If there’s disagreement that’s similarly easy to detect via CID mismatch and the disagreements can be resolved in the same manner. Records can’t be shifted between repos or anything like that: publishing this record to at://did:plc:malicious-attacker/com.iameli.money.payment/01J7N5S6YRHW0XPBDN4H1UHEV isn’t valid to anybody; that DID isn’t listed in the body of the JSON.
What did I miss?