The Rules of Recurring Payments: Every Constraint Has a Story

This is the second article in our “Building Recurring Payments in Public” series.

Part 1: Why We’re Building Recurring Payments Differently

Part 2: The Rules of Recurring Payments. Every Constraint Has a Story

Part 3: Scenarios That Shape Our System

Part 4: Locked Open. Why Anyone Can Be a Broker

In Part 1 , we explained our vision that recurring payments should be a partnership between creators and fans. Now, we’ll look at the specific rules for how recurring payments work and the reasons behind each rule.

Terms Records: The Contract Both Parties Can Verify

A new record type, com.atprotofans.terms, is central to how recurring payments work.

To accept recurring support, a creator sets up a terms record that lists the offer’s amount, currency, and billing frequency. For example, they might offer $5 per month for casual supporters, $20 per month for dedicated fans, or $50 per month billed annually for those who want to pay in advance.

When a fan subscribes, they agree to a specific terms record. This reference includes the record’s content hash (CID), which locks in the agreement. Even if the creator updates the terms later, the fan’s agreement stays with the original, unchangeable version.

This separation is important. The terms record is the contract, showing what was agreed to. The recurring payment record shows what is happening now. Fans can always check what they signed up for, and creators can see what they offered. Both sides can verify details without relying on us.

Terms come in three types:

One-time: A single payment at a fixed amount

Recurring: Ongoing payments with no fixed end

Schedule: A fixed number of payments at specific intervals (reserved for future use)

A terms record for a recurring payment would include the amount, current, unit, and frequency. This is what a $10/month recurring payment looks like:

{
"$type": "com.atprotofans.terms#recurring",
"amount": 1000,
"currency": "USD",
"unit": "monthly",
"frequency": 1
}

A terms record for a one-time payment looks the same, without the unit and frequency:

{
"$type": "com.atprotofans.terms#onetime",
"amount": 1000,
"currency": "USD"
}

The serviceRef Pattern

Terms act as contracts that balance public records and private interactions. Details of fan-creator relationships are sensitive and should stay confidential between the fan and creator. While a fan may not want to share how much they spend, they might still want to show public support.

To address this mix of privacy and transparency, we introduced the “com.atprotofans.serviceRef” record.

A serviceRef includes three parts: the DID and service fragment (ours is did:plc:7ewx3bksukdk6a4vycoykhhw#SupportBroker), the AT-URI of the record, and its CID. When a broker proof record points to a terms record, it uses a serviceRef. Any app can get terms records from our service with the com.atproto.repo.getRecord XRPC method and check that the CID matches.

This approach is useful beyond our own system. It lets you create verifiable links between ATProtocol and service-hosted data. Other brokers can use this pattern for their own terms as well.

A serviceRef record looks very similar to a strongRef record, because it effectively is one, but with the addition of the service that the record is requested from.

An example serviceRef record for the above one-time payment terms record would look like this:

{
"$type": "com.atprotofans.serviceRef",
"service": "did:plc:7ewx3bksukdk6a4vycoykhhw#SupportBroker",
"uri": "at://did:plc:7ewx3bksukdk6a4vycoykhhw/com.atprotofans.terms/01JNXYZ123TERMS01",
"cid": "bafyreifrilkyeypdng4odqwnzodslqs3ks46kl7wccragxgnljyfeebgc4"
}

A quick note on security: This setup is a workaround because there isn’t yet a formal way to make on-protocol private or semi-private records. We use certain existing features together and want to highlight their pros and cons. Broker-proof records are published and cryptographically verifiable, just like other ATProtocol records. Terms records, however, are not published and can only be accessed from the “SupportBroker” XRPC service linked to the broker’s DID, using the “com.atproto.repo.getRecord” XRPC method with inter-service authentication as either the supporter (fan) or the beneficiary (creator). The broker proof record includes an AT-URI and CID of the terms record, so even though the terms record isn’t published, a checksum (DAG-CBOR SHA256) is available.

Amount Boundaries

Recurring payments must be at least $5 and no more than $250 per month.

We set the $5 minimum because payment processing has fixed costs. If payments are too small, fees take up too much, making it not worthwhile for creators or for us. Five dollars is the lowest amount where the numbers make sense.

The $250 maximum helps manage risk. Larger amounts increase the chance of fraud and chargebacks. As trust in the system grows, we may raise this limit. For now, $250 per month keeps risk low but still allows for meaningful support.

For billing periods longer than a month, the charge can be more than $250. For example, a fan paying $250 per month but billed annually would pay $3,000 once a year. The limit is on the monthly rate, not the total charge.

Why You Can’t Edit a Recurring Payment

Once a recurring payment is created, you can’t change the amount, billing date, or frequency. This might seem limiting, but there’s a reason for it.

The broker proof confirms the exact terms: “This fan agreed to support this creator at this amount on this schedule.” If either side could change the terms partway through, the proof would no longer be accurate. The cryptographic record would not reflect the real agreement.

To change the terms, the fan cancels the current payment and starts a new one. This creates a new anniversary date, but it also keeps a clear record: the old agreement ends, a new one begins, and both can be checked independently.

This approach helps keep the system trustworthy.

Billing Frequencies and Anniversary Dates

Creators can choose from four billing options: monthly, every three months, every six months, or yearly. Fans pick from the options the creator offers.

Each payment is billed on its anniversary date, which is the day the fan first subscribed. For example, if you start on the 15th, you’ll be charged on the 15th each period. This keeps billing predictable and connected to the actual subscription, not our internal schedule.

We handle month-end dates carefully. If a fan subscribes on the 31st, we track the original day and adjust each month. If there’s no 31st, we charge on the last day of the month. For example, someone who signs up on January 31st is charged on February 28th (or 29th in leap years), then March 31st, then April 30th.

Individual Charges

If a fan supports three creators, they’ll have three separate charges. These could be on different cards and have different billing dates.

We could combine charges to lower processor fees, but we decided not to. Here’s why:

If one payment fails, it doesn’t affect the others. For example, if a card is declined for Creator B, support for Creator A continues as usual. Each relationship is separate, and our payment system is built to reflect that.

Fans can use different payment methods for different creators. For example, they might use a business card for work-related subscriptions and a personal card for hobbies. This flexibility matches how people manage their money.

The Retry Schedule

If a charge fails, we don’t stop right away. Cards can fail for temporary reasons like expiration, being over the limit, or a bank issue. We try again on day 1, day 3, and day 7 after the first failure.

If all retries fail, there’s a 24-hour grace period. On day 8, if payment still hasn’t gone through, we mark the broker proof as inactive. The attestation ends, and anyone checking the support relationship will see it’s no longer valid.

This timing gives fans a fair chance to fix payment problems and helps creators know who is actually supporting them.

Cancellation Behaviors

What happens when a fan cancels depends on the payment’s current state:

If the payment is active, cancellation is delayed. Since the fan has already paid for the current period, support continues until it ends. On the next billing date, instead of charging again, we complete the cancellation and mark the attestation as inactive.

If the payment is in retry status, cancellation happens right away. If a fan’s card is failing and they cancel, we stop all retry attempts and charges. The relationship ends immediately.

If the fan has prepaid, support continues until the prepaid period ends. Fans keep the benefits they’ve already paid for.

Pre-Payment

Fans can pre-pay for up to 12 months in one transaction. Why do we offer this?

Some fans want to commit in advance. They might want to secure their support for a year or prefer a single annual charge instead of monthly payments. Pre-payment lets them do this.

For creators, pre-payment means committed support. If a fan has paid for the next six months, their support is guaranteed for that time.

If a pre-paid fan cancels, their support continues until the prepaid period ends. The proof remains valid for the time they’ve already paid for.

What’s Next

These rules are the foundation for a trustworthy creator-fan partnership. Each rule helps keep the system honest and easy to verify.

In Part 3, we’ll go through real scenarios: what happens when payments succeed or fail, when fans cancel during a retry, and when creators are removed. Seeing the rules in action makes them clearer.