MercanPay Blog

Crypto Subscription Payments with Renewal Invoices, Explained

How to take crypto subscription payments without auto-debit: renewal invoices, reminders, grace periods and order_id design for a reliable recurring flow.

Published: October 31, 20266 min readTürkçe oku
Crypto Subscription Payments with Renewal Invoices, Explained

The first question businesses ask about crypto subscription payments is usually "Can I automatically charge the customer's wallet every month?" The short answer is no, but that doesn't stop you from selling subscriptions for crypto. This guide explains why auto-debit isn't possible and how to build a solid subscription flow with renewal invoices, step by step.

Why crypto has no auto-debit

With cards, the customer hands over their card details once and the merchant pulls the amount every month. With crypto, money only moves when the customer pushes it from their own wallet, and the merchant has no authority to take funds out of it. That's both a security advantage of crypto and the key difference for subscriptions. The same property is why there are no chargebacks, as explained in what "no chargebacks" really means.

To be clear: MercanPay has no built-in subscription or automatic recurring billing feature. You keep the subscription logic in your own system and create one invoice per billing period. The good news is that this approach is simple, transparent and familiar to customers, since many services already run on a "renewal reminder + payment link" model.

How the renewal invoice model works

In outline:

  1. The customer makes the first payment and the subscription starts.
  2. A few days before the period ends, your system creates a new invoice.
  3. The customer receives the payment link by email or message.
  4. When the payment arrives, a webhook extends the subscription by one period.
  5. If the invoice expires unpaid, a new invoice goes out with a reminder the next day.
  6. If nothing arrives during the grace period either, access is suspended.

We recommended the same model for gaming, VPN and hosting businesses in crypto payments for gaming, VPN and hosting.

Step 1: Keep the subscription record on your side

Store at least the following for each subscription:

Field Example Meaning
subscription_id 42 The subscription's id
plan pro-monthly Plan and price
period_end 2026-12-09 End of the current period
status active active, grace, suspended
renewal_attempt 1 Which invoice this is for the period

Step 2: Create the renewal invoice

A USD-priced invoice suits renewals: your price stays the same every month while the customer picks TRX or USDT. This PHP example can be called from a scheduled job that runs daily:

<?php
require 'vendor/autoload.php';

use MercanPay\MercanPay;

$zp = new MercanPay('https://mercanpay.com', getenv('MERCANPAY_API_KEY'));

function createRenewalInvoice(MercanPay $zp, array $sub): array
{
    // Unique per period and attempt, yet stable if the job runs twice
    $orderId = sprintf('sub-%d-%s-%d', $sub['id'], $sub['period_end'], $sub['renewal_attempt']);

    return $zp->createUsdInvoice($sub['price_usd'], [
        'order_id'           => $orderId,
        'description'        => 'Pro plan renewal · 1 month',
        'expires_in_minutes' => 1440,
        'success_url'        => 'https://myapp.com/account/subscription',
        'metadata'           => [
            'subscription_id' => $sub['id'],
            'period_end'      => $sub['period_end'],
        ],
    ]);
}

$invoice = createRenewalInvoice($zp, $sub);
sendRenewalEmail($sub['email'], $invoice['payment_url'], $invoice['expires_at']);

Two details matter here.

Designing the order_id. Repeating a request with the same order_id returns the existing invoice rather than creating a new one, so even if your job accidentally runs twice, the customer never gets two invoices. However, the same order_id also returns the existing invoice when that invoice has expired. So when an invoice expires unpaid, increment renewal_attempt to generate a new order_id. Using order_id for idempotent invoices goes deeper into this.

Validity. Invoices stay open for at most 24 hours (1440 minutes). Using the maximum for renewals gives the customer time to see the email and pay. If it expires, send a fresh invoice the next day.

Step 3: Extend the subscription from the webhook

Extend the subscription when invoice.paid or invoice.overpaid arrives:

$event = json_decode($body, true); // after verifying the signature
$inv   = $event['data']['invoice'];

if (in_array($event['type'], ['invoice.paid', 'invoice.overpaid'], true)) {
    $subId = $inv['metadata']['subscription_id'];
    // Start the new period from the previous end date, not from "today"
    extendSubscription($subId, $inv['metadata']['period_end'], $event['id']);
}

Things to watch:

  • Extend from the previous end date. A customer who pays two days early shouldn't lose two days, and one who pays two days late shouldn't gain them.
  • Deduplicate by event id. The same event can arrive more than once, so store $event['id'] to avoid extending the same period twice.
  • Accept late payments. A payment to an expired invoice is still credited to your balance, with data.payment.late set to true. If the customer paid, extending the subscription is the right call.

Signature verification is covered in how to verify webhook signatures, and every event in crypto payment webhook events.

Step 4: Reminders and a grace period

Without auto-debit, your reminder flow is what keeps subscriptions alive. A reasonable schedule:

  • 3 days before the period ends: first renewal invoice and email.
  • If the invoice expires: a second reminder with a new invoice the next day.
  • At the end of the period: the subscription moves into a grace period and access continues.
  • At the end of the grace period: without payment, access is suspended, and the customer can return any time with a new payment.

How long the grace period lasts is your business decision, shaped by the cost of the service and your relationship with the customer.

Plan changes and cancellations

Since the subscription logic lives in your system, plan changes and cancellations are entirely in your hands:

  • Upgrades: if a customer moves to a higher plan mid-period, work out a difference that accounts for the remaining time and create a separate invoice for it.
  • Downgrades: applying the change to the next renewal invoice is the simplest approach.
  • Cancellations: when a customer cancels, stop creating renewal invoices. With no auto-debit, there's no "payment mandate" to revoke, which is one of the most transparent aspects of crypto subscriptions from the customer's side.

Tips for a better customer experience

  • Offer multi-month plans. Prepaid 3, 6 or 12-month plans mean fewer payments and less renewal friction.
  • Put USDT first. USDT is a stablecoin that tracks the dollar, so the customer pays roughly the same amount every month. See crypto payment exchange rate risk.
  • Be clear in the email. Include the amount, the expiry time and a "use the TRON (TRC20) network only" note.
  • Show status in the account page. Customers should see when their subscription ends and whether an invoice is waiting.
  • Keep pricing simple. Network fees are included in the amount on the payment page, so your listed price stays the one the customer sees.

FAQ

Does MercanPay renew subscriptions automatically?

No. There is no built-in subscription feature. You create an invoice for each period through the API or the panel, and the subscription logic runs in your system.

Why can't I leave an invoice open for a month?

Invoices are valid for at most 24 hours, which keeps rates current, especially for a volatile coin like TRX. Use daily reminders with fresh invoices instead of one long wait.

What if a customer pays both invoices by mistake?

Both payments are credited to your balance. You can apply the extra as credit toward the next period, or refund it with a withdrawal from your balance to the customer's address.

Can I sell subscriptions without a website?

At a small scale, yes. Create an invoice in the panel each month and send the link. As your subscriber count grows, automating through the API becomes more efficient.

Get started with MercanPay

To run crypto subscriptions with renewal invoices, apply for a merchant account. API details and every field are in the documentation.

#Subscriptions#Invoice#PHP#Webhook

Related posts

Start accepting crypto payments in minutes

Accept USDT and TRX (TRC20). Fees from 0.4%, a hosted payment page, API and webhooks.