On this page
- Price the membership monthly (every 30 days) or yearly (every 365 days); the member approves once and every renewal is collected from their wallet into yours.
- Sell it from a shop, a payment link or the API, and keep the member list in step with subscription.created, subscription.past_due and subscription.ended, deduplicated on the event id.
- You pay nothing. There is no Fianto fee during the beta; the member pays a flat 0.01 USDC network fee with each charge today.
How should I price a USDC membership?
A membership on Fianto is a product with one or more recurring prices. Two billing periods exist: monthly, which renews every 30 days, and yearly, which renews every 365 days. A month here is 30 days from the day the member joined, so renewal dates drift against the dates on a wall calendar. There are no weekly, quarterly or usage-based prices, no free trials and no pause.
You can offer both periods as two prices on the same product, so a reader can choose: a shop listing shows both side by side, while a payment link or an API checkout sells one of them. Take an invented example, the Fenwhistle Gazette, a paid newsletter:
| Price | Renews | Lands in your wallet | Member pays per charge today |
|---|---|---|---|
| Monthly | Every 30 days | 9.00 USDC | 9.01 USDC |
| Yearly | Every 365 days | 90.00 USDC | 90.01 USDC |
The price you set is what lands in your wallet. The extra 0.01 USDC is the network fee the member pays with each charge today, the first one included, on plans created since 6 October 2026. A price can be anything from 0.01 to 1,000,000 USDC, with up to six decimals. There is no Fianto fee during the beta; after it, the member pays a Fianto fee of about 0.1 to 0.5% on top of your price, and you still pay nothing. The pricing page has the full table.
To raise the price later, add a new price to the same product. Ending the old price cancels its members at the end of the period they already paid for, so plan the switch and tell them first.
Shop, payment link or API: which way should I sell it?
There are three ways to put the membership in front of readers. All three open the same hosted checkout, and all three need your account to be approved by Fianto first.
| Shop | Payment link | API | |
|---|---|---|---|
| Code needed | None | None | A server that creates checkout sessions |
| Where readers start | Your page at <name>.fianto.xyz | A link at checkout.fianto.xyz/l/... | A button on your own site |
| How you know who joined | The email the buyer typed, and their wallet | The email, if you ask for it, and the wallet | Your own member ID, sent as customer_reference |
| Automatic access | Zapier or Make, or webhooks | Webhooks | Webhooks |
A shop
A shop is a page at your own name under fianto.xyz, built in the dashboard. A membership product gets a Join button and asks for the buyer's email by default. After payment the buyer gets your message, a link and, if you turn it on, a code of their own, by email and on the receipt page. The walk-through is in the no-code USDC shop post.
A payment link
A payment link is one reusable link for one price, created in the dashboard. Put it in a newsletter footer, a bio or a pinned post; every click opens a fresh subscription checkout. You choose whether to ask for an email. Fianto sends link payers no email, and the after-payment URL only applies to one-time prices, so a subscriber is not sent back to your site. More in USDC payment links.
The API
Your server calls POST /v1/checkout-sessions with mode: "subscription", the price_ of the monthly or yearly price, an order_, the member ID in customer_, and a success_ and cancel_. The member ID comes back on every event for that membership. Keep one order_ per member and plan: once a subscribe under it has completed, another one under the same order ID is refused with order_, even after the membership ends, so nobody ends up paying twice. Issue a new one after subscription..
Members approve once and renew every 30 or 365 days. No Fianto fee during the beta.
See memberships on FiantoHow do I grant and revoke access from webhooks?
Fianto does not host your newsletter or run your community. Your site, bot or mailing tool opens and closes access from signed events. A subscription creates no order, so order. never fires for it; memberships send subscription. events. The ones that change access:
| Event | What happened | What to do |
|---|---|---|
subscription. | The first period is paid | Add the member until current_period_end |
subscription. | A renewal was collected | Move their access to the new period end |
subscription. | The first attempt at a renewal failed | Your choice: keep access or limit it |
subscription. | An attempt failed (sent for every counted failure) | Read failure.attempt_no and failure.next_attempt_at |
subscription. | A cancel takes effect at period end | Keep access until then |
subscription. | The membership is over | Remove the member |
Past due and ended are different states. Past due means a renewal failed and Fianto is still trying; the member may top up and the next attempt collects. Ended is final: end_ says whether the member cancelled (PAYER_), you cancelled or ended the price (MERCHANT_), or every attempt failed (PAYMENT_).
Delivery is at least once and in no fixed order, so the same event can arrive twice and a renewal can arrive before an older event. Record each event id (evt_, the same value as the webhook-id header, stable across retries) in the same database transaction as the access change, and skip ids you have seen. A sketch with the Next.js SDK:
import { Webhooks } from '@fianto/nextjs';
import { db } from '@/lib/db';
// db.once is your own helper: it records event.id and runs the change in one transaction,
// and does nothing for an id it has seen.
export const POST = Webhooks({
secret: process.env.FIANTO_WEBHOOK_SECRET,
onSubscriptionCreated: (event) =>
db.once(event.id, (tx) =>
tx.grant(event.data.customer.reference, event.data.current_period_end)),
onSubscriptionRenewed: (event) =>
db.once(event.id, (tx) =>
tx.extend(event.data.customer.reference, event.data.current_period_end)),
onSubscriptionPastDue: (event) =>
db.once(event.id, (tx) => tx.flagPastDue(event.data.customer.reference)),
onSubscriptionEnded: (event) =>
db.once(event.id, (tx) =>
tx.revoke(event.data.customer.reference, event.data.end_reason)),
});Shop and payment-link sales run through a hidden application named Shop in the Developers section. It cannot hold API keys, but you can set its webhook URL and receive the same events; there, identify members by the email they typed, which nobody verifies, or by their wallet. Signatures, retries and the source of truth are covered in webhooks for access.
What do members see, and how do they cancel?
At checkout the member sees what is charged today, when the next charge comes, the network fee, the most you can take per period, and the Solana account rent before anything is signed. They sign one transaction. It sets up the subscription with a cap per period and pays the first period. Rent is about 0.00197 SOL today for the subscription account, which comes back when they reclaim it after the membership ends, plus about 0.00163 SOL once for wallet setup on a wallet's first subscription, which is not returned. Details are in account rent and reclaim.
After that the member signs nothing at renewal. To see or stop what they pay, they open the customer portal at fianto.xyz/my and sign in with a message from their wallet, which costs nothing and moves no funds. The portal lists every Fianto subscription that wallet pays, across merchants. Cancel takes one more signature, and the membership runs to the end of the paid period. The portal has no undo. After a membership the member cancelled has ended, the portal offers to return the rent.
Acme RPC
ProStops future payments. It stays active until the end of its current billing period.
Fianto sends members no renewal or reminder emails. The one email a payer can get is the shop buyer email, sent when a shop purchase is paid and the buyer gave an address; for a membership it includes a link to manage the subscription. If your readers expect a reminder before a yearly renewal, send it yourself. Put a line in your welcome email pointing to the customer portal, so nobody has to ask how to leave.
What happens when a renewal fails?
Nothing is taken and nothing is owed later. Fianto tries four times in all: on the due date, then about one hour, six hours and one day after the period starts. The failures that count are an empty or short wallet, a removed permission, and a frozen or closed token account; other errors are tried again without counting.
- The first counted failure sets the membership to past due and sends subscription.past_due, plus subscription.payment_failed.
- Each later failure sends subscription.payment_failed with its attempt number and the time of the next attempt.
- If an attempt succeeds, the membership is active again and subscription.renewed arrives with the new period end.
- If the fourth attempt fails, the membership ends with PAYMENT_FAILED and subscription.ended arrives. That period is never charged later.
Because the last attempt comes about a day after the period starts, a grace period costs you little: you can keep access during past due and remove it only at ended. Past-due memberships also show in the dashboard under Needs attention. The full schedule is in failed renewals and retries.
Can I offer a discount on a membership?
Yes, with a coupon from Billing, then Coupons, in the dashboard. A coupon takes a percentage off (1% to 99%) or a fixed USDC amount, and lasts for the first payment only, for several billing periods (1 to 120), or for every payment. Codes are 3 to 32 letters, digits and hyphens. You can add an end date, a cap on paid redemptions, and a once-per-wallet rule.
The member types the code in the Discount code field on the checkout page, which works for shop, payment-link and API checkouts alike and shows only while you have an active coupon. A discounted member stays on the same on-chain plan with the full price as its cap; Fianto simply collects less while the discount lasts, then the full price. The discounted price must stay at 0.01 USDC or more, so a coupon cannot make a membership free. Coupons are created in the dashboard only, with no API. More in discount codes for USDC payments.
A launch checklist
- Sign up, fill in the business profile, turn on two-factor sign-in, and prove your receiving wallet with a signed message. The wallet needs a USDC token account.
- Submit for review. Payments start only after Fianto approves the account; no review time is promised, so do this first.
- Create the membership product with its monthly and yearly prices.
- Choose the channel: open a shop, create a payment link, or add a checkout session call to your site.
- Set the webhook URL, verify it, send it a test event, and check that your handler records each event id once.
- There is no test mode. Join your own membership with a small real price, watch subscription.created arrive, cancel it in the portal, and see subscription.cancel_scheduled.
- Tell members where to manage their membership: fianto.xyz/my.
Keys, sessions and events are on the developers page, and the full reference is at docs.fianto.xyz.