# Accepting USDC subscriptions for SaaS: a 2026 developer guide

> Recurring stablecoin billing without 2.9% to Stripe. Webhooks, idempotency, dunning, refunds, taxes. The code patterns and the failure modes.
- **Author**: Ari Volkov
- **Published**: 2026-05-12
- **Category**: Developers
- **URL**: https://www.plaitr.com/blog/accept-usdc-subscriptions-saas

---

Stripe Billing takes 0.5% per recurring transaction on top of card fees. For a $99/mo SaaS that is roughly $0.50 of margin gone every month per seat. A USDC subscription replaces both the card fee and the billing surcharge with a flat monthly gateway fee.

The hard part is not the accept side. It is the recurring side: dunning, retries, idempotency, refunds, and tax reporting on assets that fluctuate (which, for USDC, mostly do not).

## TL;DR

- Recurring stablecoin payments require three primitives: a signed authorization, a deterministic retry path, and an event log your accounting trusts.
- [Plaitr](https://plaitr.com) exposes all three via REST: payment intents, HMAC-signed webhooks, and idempotency keys on every mutation.
- USDC is the right default because it does not move against USD. USDT works too. Native tokens are a bad idea for subscriptions because invoice math gets messy.
- Best chain depends on your customer base. For US/EU SaaS, [USDC on Base](https://plaitr.com/accept/base) is cheap and fast. For global SaaS, [USDT on Tron](https://plaitr.com/accept/tron) is the cheapest at scale.
- Stripe Billing fee on $99/mo: about $3.36 between card + billing surcharge. Plaitr fee on same: $499 fixed per month no matter how many subs.

## What architecture do you need for USDC subscriptions?

Three services, loosely coupled:

1. A billing engine (your code) that decides who owes what when.
2. A payment intent service (Plaitr API) that creates the payable artifact.
3. A webhook receiver (your code) that reconciles ledger entries when payments confirm on-chain.

The billing engine is the boring part. It is the same as a card-based billing engine. Subscription state machine, dunning rules, grace periods. None of this changes because the rails are crypto.

The payment intent service creates a unique payable object per invoice. With Plaitr:

```
POST /v1/payments
{
  "amount": "99.00",
  "currency": "USDC",
  "chain": "base",
  "customer_id": "cus_xK82m",
  "metadata": { "invoice_id": "inv_4271", "period": "2026-05" },
  "idempotency_key": "inv_4271_2026-05"
}
```

Idempotency is non-negotiable. Network retries are normal. Without an idempotency key the customer can be double-billed. Plaitr deduplicates on the key for 24 hours; your billing engine must persist the key on the invoice row.

The webhook receiver is where most teams get this wrong. Webhooks are at-least-once delivery. Treat the database row, not the webhook event, as the source of truth.

## Webhook handling

For each event Plaitr sends:

- Verify the HMAC signature in the `X-Plaitr-Signature` header against your webhook secret.
- Parse the event id and dedupe against an event_log table.
- Update the invoice row inside a transaction.
- Acknowledge with 2xx within 5 seconds; we retry exponentially up to 24 hours otherwise.

The events that matter:

- `payment.confirmed`: the on-chain settlement is final. Mark the invoice paid and trigger downstream provisioning.
- `payment.refunded`: the merchant initiated a refund. Reverse the ledger entry.
- `payout.settled`: Plaitr sent the consolidated payout to your wallet or bank. Useful for accounting reconciliation.

When confirmation finality is reached varies by chain. On Solana about 0.4 seconds. On Base 2 seconds. On Ethereum mainnet roughly 60 seconds to be safe (we wait 12 blocks).

## Dunning

The customer's wallet ran out of USDC. The payment intent expires after 24 hours. Your dunning logic should:

1. Create a fresh payment intent with a new idempotency key.
2. Email the customer the new payment link plus a 7-day grace period.
3. After 3 failed attempts, suspend the subscription. Do not delete. Customer wallets refill.
4. Resume on first successful payment.

Unlike card dunning, you do not need a retry-with-different-card flow. Crypto wallets either have funds or they do not.

## Refunds and partial credits

Refunds in crypto are a separate transaction, not a reversal. From the API:

```
POST /v1/refunds
{
  "payment_id": "pay_xK82m",
  "amount": "99.00",
  "to_wallet": "<customer-provided refund wallet>"
}
```

Key detail: the refund goes to a wallet the customer specifies, which may not be the wallet that paid. Make this an explicit checkout step in your portal.

Partial credits (e.g., proration on plan upgrade) are best handled as a ledger credit, not an on-chain refund. Apply the credit to the next invoice.

## How should USDC subscriptions be reported for tax?

USDC is treated as a stablecoin asset in most jurisdictions. For US SaaS:

- Revenue is recognized at the fiat value at the moment of confirmation (almost always $1.00 USDC = $1.00 USD).
- The accounting entry is straightforward: AR -> revenue, just like cards.
- The 1099-K threshold mechanics apply to your payment processor. Plaitr is non-custodial; no 1099-K is issued by Plaitr because Plaitr never holds the funds. Talk to your accountant about how your jurisdiction classifies non-custodial gateways.

## Failure modes I have seen

- Forgetting the idempotency key on retry. Double-billing within minutes. Fix: persist the key per invoice on the invoice row.
- Treating the webhook payload as the source of truth. Replay attacks become possible. Fix: dedupe by event id + verify signature, but update the invoice row from a fresh API GET.
- Hard-coding chain. Customers in Argentina want Tron. Customers in the US want Base. Offer a chain picker at checkout.
- Quoting in native tokens (ETH, SOL, BNB). Invoice math becomes a price-feed nightmare. Quote in USDC. Always.

## Fee comparison (worked example)

1,000 paying customers at $99/mo:

- Stripe Billing on cards: ($99 * 0.029 + $0.30) * 1000 = $3,170/mo plus the 0.5% billing surcharge = $3,665/mo. Annual: $43,980.
- BitPay at 1% on USDC subs: $99 * 0.01 * 1000 = $990/mo. Annual: $11,880.
- Plaitr Growth plan: $499/mo flat. Annual: $5,988.

For a SaaS that scales past 1,000 paying subs, Plaitr is the cheapest non-custodial option by a wide margin. Read the [Plaitr vs Stripe comparison](https://plaitr.com/compare/stripe) for the broader card-vs-crypto question.

## When not to use crypto subscriptions

B2B SaaS selling to CFOs who only know how to read card statements. The accounting story is the friction, not the engineering. Wait until your customers ask for it. They will.

## Bottom line

USDC subscriptions are a clean engineering exercise once you accept three primitives: signed intents, idempotent retries, and ledger-as-source-of-truth. The savings compound with subscriber count. Stripe's billing fees scale linearly with revenue. Plaitr's do not.

> Plaitr is the crypto subscription billing API for SaaS that wants to keep 100% of recurring revenue. REST API, HMAC webhooks, idempotency. Zero KYC. Flat monthly fee.
---
- [More Developers articles](https://www.plaitr.com/blog/category/developers)
- [All articles](https://www.plaitr.com/blog)