Create plans and subscriptions
Use gateway-managed billing where supported and keep subscription state distinct from payment state.
Choose the billing owner
A plan defines terms such as amount and frequency. A subscription connects those terms to a customer’s payment method. NMI’s Recurring Module submits scheduled payments for configured subscriptions. If your product needs usage-based timing or custom orchestration, a server-controlled credential-on-file implementation may be more appropriate. The Recurring Module is documented only for regions outside PSD2 requirements. Sandbox can create plans/subscriptions but does not submit scheduled transactions.
Create a monthly plan
This sandbox example defines twelve 29.00 payments on the first day of each month. Use the actual agreement and confirm the intended start behavior before creating customer subscriptions. Do not interpret the example as an approved Betterpay price or commercial offer. The endpoint defines start_date on the subscription, with YYYYMMDD or YYYYMMDDHHMMSS format; when omitted, the next billing date follows the plan schedule. POST /api/v5/plans HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> Content-Type: application/json { "id": "membership-annual-12", "plan_name": "Membership monthly payments", "plan_amount": 29.00, "plan_payments": 12, "month_frequency": 1, "day_of_month": 1 }
Attach a saved customer
When Customer Vault is enabled and a record already exists, create a subscription using plan_id and customer_vault.id. This example follows the current Create Subscription OpenAPI schema, which requires exactly one payment source. Do not send payment_details together with an existing vault reference. The higher-level recurring guide shows an older top-level customer_vault_id form; verify this schema-based request in sandbox before rollout. POST /api/v5/subscriptions HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> Content-Type: application/json { "plan_id": "membership-annual-12", "customer_vault": { "id": "CUST-001" } } Source mismatch: the current endpoint schema uses customer_vault.id; the narrative recurring guide still shows customer_vault_id. This guide follows the endpoint schema.
Model the lifecycle in your software
Creating a subscription is not proof that a scheduled charge succeeded. Store the subscription identifier, plan, customer, consent record and state. The Recurring Module’s transactions produce transaction.sale webhook events; use verified event handling and reconciliation to update paid periods. Object or event Application action Plan created Store billing configuration and review schedule Subscription created Associate customer and plan; do not mark future invoices paid Scheduled sale approved Link payment to the correct billing period Payment failed Apply the agreed notification and recovery policy Cancellation requested Update the gateway subscription and verify resulting state
Before releasing subscriptions
Test creation, lookup and cancellation with sandbox records, then validate simulated event handling in your own test harness. Because sandbox does not run scheduled billing, arrange any live charge validation through the agreed production launch process. For PSD2 or custom billing, review credential-on-file classification, customer authentication and processor-specific fields before sending recurring charges.
Handle cancellation responses
Cancel with DELETE /api/v5/subscriptions/<subscription-id>. In the October 16 sandbox check, a successful cancellation returned HTTP 204 with no response body, although the endpoint reference documented 200. A subsequent GET returned the historical record with delayed_condition set to inactive. Handle an empty successful response; do not require JSON or assume cancellation must make GET return 404. Verify the resulting subscription state before confirming cancellation to a customer. This is an observed sandbox result, not a guarantee of every account or API version. Keep billing state and customer messaging consistent with the actual response.