# Crypto payments for subscriptions and recurring billing

> Bill subscriptions in crypto: one invoice per billing period, priced in USD, a payment link in the renewal e-mail and a signed webhook that extends access.

Source: https://cryptolike.net/use-cases/subscriptions
Updated: 2026-09-25

CryptoLike bills a subscription in crypto one period at a time: your system creates an invoice for each renewal, the customer pays it from the link in your renewal e-mail, and a signed webhook tells your server to extend access. The price stays in USD or EUR; the customer pays the equivalent in Bitcoin, USDT or another enabled asset at a rate locked for the invoice.

## Why can't crypto be charged automatically each month?

A crypto payment is always pushed by the payer's wallet; nobody can pull it from the customer later, the way a card is charged on file. So a crypto subscription is a series of invoices, not a stored payment method. The customer confirms each period, which suits annual plans, B2B contracts and customers who prefer to prepay; your product decides what happens when a period is not paid.

## How recurring billing works with CryptoLike invoices

Your billing system keeps the schedule; CryptoLike handles each period's payment. A renewal takes one API call and one webhook, and the same code works for monthly, quarterly and annual plans.

1. **A few days before renewal, create the invoice.** `POST /v1/invoices` with the plan price in USD, an `order_id` that names the subscription and the period, and a time to pay of up to 30 days (`ttl_seconds` up to 2,592,000).
2. **Send the `checkout_url`** in your renewal e-mail or show it in the customer's account. The page shows the amount, the network, the address with a QR code and the time left.
3. **Extend access on `invoice.paid`.** Verify the webhook signature, find the subscription by `order_id` or `metadata`, and move the paid-until date by one period.
4. **Handle the other outcomes.** `invoice.underpaid` — ask for the rest to the same address before the deadline; `invoice.expired` — start your grace period or pause the plan and offer a new invoice.

```json
{
  "amount": "49.00",
  "currency": "USD",
  "order_id": "sub-4821-2026-10",
  "idempotency_by_order_id": true,
  "ttl_seconds": 604800,
  "metadata": { "subscription_id": "4821", "period": "2026-10" },
  "return_url": "https://app.example.com/billing"
}
```

With `idempotency_by_order_id`, a retried job for the same period returns the open invoice instead of billing twice. `metadata` comes back in every `invoice.*` webhook and is never shown to the payer.

## Which renewal model fits your product?

Three patterns cover most subscription businesses. They differ in who starts the payment and how your system learns about it; all three use the same statuses and webhooks.

| Model | How it works | Best for |
|---|---|---|
| Invoice per period | Your system creates an invoice before each renewal and e-mails the link | SaaS plans, memberships, hosting |
| Prepaid balance | Each customer gets a [static address](https://cryptolike.net/glossary/static-address); every top-up is credited and your system deducts the plan price from the internal balance | Usage-based billing, credits, frequent small charges |
| Payment link by hand | Your finance team creates the monthly invoice in the cabinet or the Telegram bot and sends the link | B2B contracts, a few large customers |

The prepaid model is described in [deposits to static addresses](https://cryptolike.net/use-cases/deposits), and manual invoices in [payment links](https://cryptolike.net/use-cases/payment-links).

## Pricing in fiat and the exchange rate

The plan price stays in your currency. When the customer picks the coin on the payment page, CryptoLike converts the amount at the current rate and locks it until the invoice expires, so a long time to pay does not change what the customer owes in crypto once the coin is chosen. Price in a stablecoin instead if you want the amount fixed in USDT from the start. The platform fee per confirmed payment is on the [pricing page](https://cryptolike.net/pricing).

## How to connect

Subscriptions need a backend that stores the secret key and receives webhooks. Install an SDK — [TypeScript SDK](https://cryptolike.net/integrations/sdk-typescript), [Python SDK](https://cryptolike.net/integrations/sdk-python), [PHP SDK](https://cryptolike.net/integrations/sdk-php) or [Go SDK](https://cryptolike.net/integrations/sdk-go) — create a key with `create_invoice` and `read`, and test the whole renewal on test networks with a `ck_test_` key and the test API URL from CryptoLike support. The full request and webhook reference is in the [API overview](https://cryptolike.net/docs/api); more patterns for services are in [crypto payments for digital goods and SaaS](https://cryptolike.net/use-cases/digital-goods).

## FAQ

### Can CryptoLike charge my customers automatically every month?

No. A crypto transfer is always sent by the payer's own wallet, so nothing can be charged without the customer confirming it. CryptoLike subscriptions work with one invoice per billing period: your system creates it before the renewal, the customer pays from the link, and the `invoice.paid` webhook extends access. A prepaid balance on a static address is the alternative for frequent charges.

### How long can a renewal invoice stay open?

Up to 30 days: `ttl_seconds` accepts 60 to 2,592,000 seconds, and without it the account's default time to pay (30 minutes) applies. For renewals, 3 to 7 days is common. Once the customer chooses a coin, the exchange rate is locked until the invoice expires, so the crypto amount they see does not change while the invoice is open.

### What if the customer pays less than the plan price?

The invoice becomes `underpaid` and stays open to a top-up to the same address until its deadline; `remaining_amount` tells your system how much is missing, and the customer sees it on the payment page. If the rest arrives in time, `invoice.paid` follows. If not, the invoice closes as underpaid and you decide whether to extend access or refund.

### How do I avoid billing the same period twice?

Use an `order_id` that names the subscription and the period, such as `sub-4821-2026-10`, and send `idempotency_by_order_id: true`. A retried job or a second request for the same period then returns the open invoice instead of creating a new one, and a period that has already received money is refused with `409 conflict`.
