Recurring billing
Automate monthly invoices and collect recurring payments from your application.
How recurring billing works#
Manza does not auto-charge stored cards. Your application owns the subscription, billing dates and reminders; the customer authorizes a new payment each period. This guide covers collecting subscription payments, not scheduling outgoing transfers.
- Run a scheduled job in your application on each billing date.
- Create a fresh single-use link with
POST /api/payment_links. Use an open account belonging to your entity, and supply the amount and apayment_referencefor the billing period. - Store the returned link ID against that subscription and period before delivering it.
- Email or message the returned
urlto the customer from your application. - Confirm payment through
payment_link.paid, then renew access once for that period.
Use a key with payment_links:write to create links and payment_links:read to reconcile them. See Payment links for request examples, required fields and the deployment's minimum amount. Reusable links accept multiple payments; they do not schedule payments or charge cards automatically.
Fixed monthly subscriptions#
Your application owns the subscription schedule. The API creates individual invoices; it does not create a recurring invoice schedule or a subscription you can cancel. For a customer paying the same amount each month:
- Create the customer once with
POST /api/customersand store its ID. - Store the agreed line items, amount and billing day in your application.
- Each month, call
POST /api/invoiceswith the samecustomer_idand line items, updatedissue_dateanddue_date, and areferenceidentifying the billing period. - Use
invoices:writeandinvoices:auto_approveto issue each invoice without monthly manual approval. Includesend_to_emailto queue the invoice email. - Store the returned invoice ID against the subscription and billing period. When the subscription ends, stop future creation jobs in your application.
For example, Ruby can build the period reference as "club-#{club_id}-#{billing_month}".
Auto-approval is an API-key permission, not an approved=true request parameter. It is not restricted to a fixed amount or a particular agreement: your integration must enforce those rules. A sent status does not mean the email was delivered or that the customer has paid. Omitting send_to_email still returns sent, but does not queue an email.
For issuer logo setup and safe retries, see Recurring invoices and branding.
Automate invoice approval#
For an invoice each period, use POST /api/invoices with invoices:write and invoices:auto_approve. Supply the customer, issue and due dates, and line items described in Create invoice. Create customers first with customers:write if needed.
The response is already sent: Manza approves and sends the invoice in the create request. When send_to_email is set, it also queues the invoice email. Do not call POST /api/invoices/:id/send again for this path.
This scope bypasses the entity's approval rules, including multi-approval requirements. Grant it only to an integration trusted to issue invoices without a human decision.
An invoice is not automatically given a payment link. To deliver a card-payment request reliably with this path:
- Create the invoice without
send_to_emailso no invoice email is queued yet. - Call
POST /api/invoices/:id/payment_linkwithaccount_idand a key carryingpayment_links:write. The link uses the invoice's amount and currency. - Store the returned link ID and send its
urlfrom your own application.
Setting send_to_email on creation queues email before you can attach the link; do not rely on a later attachment appearing in that email. See Create payment link from invoice.
Keep dashboard approval#
If invoices need human review, use a key without invoices:auto_approve:
- Create the invoice with
POST /api/invoicesandinvoices:write. It starts inpending_approval. Setsend_to_emailto the customer's email. - Attach its card-payment link using
POST /api/invoices/:id/payment_linkwithaccount_idandpayment_links:write, before sending the invoice. - A member completes Approve & Send in the dashboard (Invoicing → Invoices). Once the approval requirements are met, this also sends the invoice and queues its email, including the attached payment link. Do not send it again through the API.
- Only if an invoice is still
approved, usePOST /api/invoices/:id/sendwithinvoices:send. Check its current status first.
There is no public invoice-approve API endpoint. See Approval before send for both paths.
Confirm each renewal#
Verify the webhook signature and deduplicate deliveries using X-Manza-Event-Id. Match the payment link ID to the subscription and billing period you stored. Mark that period paid and extend access only once.
payment_link.paid confirms the customer's payment; the link can still be clearing while funds settle. If your service must wait for money to land, use payment_link.payment_settled instead. A browser redirect alone is not proof of payment. See Webhooks for verification and retry behavior.
Reconcile with GET /api/payment_links/:id, including its status and settled_at, if delivery is delayed or your integration needs to recover after an outage.
Retries, reminders and cancellation#
Keep one billing record per subscription and period in your own database and prevent concurrent jobs from creating duplicate requests. payment_reference is a reconciliation label, not an idempotency guarantee; the same applies to an invoice's reference. If creation times out, reconcile the result before creating another invoice or link.
Send reminders for the existing unpaid link rather than creating a new charge each time. If a link expires, reconcile its payment state before issuing a replacement. Stop future billing jobs when a subscription is cancelled; cancel an outstanding active link with POST /api/payment_links/:id/cancel when appropriate. Cancelling a link does not cancel an associated invoice or reverse an earlier payment.