Invoices
An invoice is a finalized bill. The document you send to a customer when it’s time to pay. MarginFront generates invoices automatically based on each customer’s subscription and logged usage events. The API lets you read those invoices back so you can display them in your own product, sync them to accounting tools, or hand them to your finance team. Invoice creation happens automatically at the end of each billing period (driven by the subscription’s billing cycle). You can also generate a draft invoice on demand for any active subscription using the generate endpoint — useful for mid-cycle billing, one-click “bill now” flows, and previewing what a customer’s next invoice will look like.The endpoints
List invoices
Method & URL:customerExternalId: filter to a single customerstatus: filter by state. Valid values aredraft,pending,issued,paid,overdue,void,refunded(see Invoice statuses below)startDate/endDate: filter by invoice date rangelimit/offset: pagination
200 OK):
Read one invoice
Method & URL:Generate a draft invoice
Turns a subscription’s tracked usage into a draft invoice you can preview, edit, or send. Line items and totals are computed server-side from the period’s real usage events plus any recurring, seat, or one-time charges on the plan. Method & URL:
When
billingPeriodStart / billingPeriodEnd are omitted, the subscription’s current billing period is used — the right answer for “bill now” flows.
Example:
201 Created): the full draft invoice, including line items and totals. The invoice starts in draft status — it is not sent until you move it to issued (manually, or via the auto-finalize step at the end of the billing period).
Common errors:
400 Bad Request:customerIdorsubscriptionIdis missing or not a UUID.401 Unauthorized: API key missing or wrong.404 Not Found: the customer or subscription does not exist in this org, or the customer does not own that subscription.
Send an invoice email
Emails an invoice to the customer with a “Pay Now” button that opens Stripe Checkout pre-filled with the invoice details. Use this after/v1/invoices/generate to actually deliver the draft, or to re-send an invoice that has already been issued. The customer’s stored email address is used by default — pass recipientEmail to override (for example, to route the invoice to a different billing contact).
Method & URL:
Example:
200 OK):
emailId is the provider’s message ID for delivery tracking. recipientEmail echoes back the address the email was actually sent to (after applying any override).
Side effect — auto-finalize: if the invoice was still in draft status when this call landed, sending it auto-finalizes the status from draft to issued. This matches the behavior of the dashboard’s Send button and the end-of-period auto-finalize step. No separate “finalize” call is needed first.
After payment: once the customer clicks the Stripe Checkout link in the email and pays, the invoice status flips to paid automatically via webhook. You do not need to poll or make a follow-up call to confirm.
Common errors:
400 Bad Request: the invoice cannot be sent (for example, it is alreadypaidorvoid).401 Unauthorized: API key missing or wrong.404 Not Found: no invoice with that ID exists in this org.
Invoice statuses
MarginFront invoices move through one of seven statuses over their lifetime. Every invoice in the API has itsstatus field set to exactly one of these.
The natural “happy path” is
draft → pending → issued → paid. Most invoices go through exactly those four.
Refund flow
Refunds are recorded against a payment, not directly against the invoice. When you create a refund usingPOST /v1/invoices/:invoiceId/payments/:paymentId/refund, MarginFront records the refund and, if the refund covers the entire invoice, moves the invoice from paid to refunded. Partial refunds leave the invoice in paid and just reduce the net collected amount.
Once an invoice is refunded:
- It is excluded from collected revenue totals.
- It is excluded from billed revenue totals (as if it had never been invoiced).
- The underlying payment and refund records are preserved for audit.
refunded correctly. If you are rolling your own accounting sync, treat refunded invoices the same way you would treat void invoices for revenue-recognition purposes.
Common errors
401 Unauthorized: API key missing or wrong.404 Not Found: no invoice with that ID exists in this org.
Using the Node SDK
Analytics vs invoices: which do I want?
Quick disambiguation since both expose “cost” numbers:
If the number needs to match what lands on the customer’s credit card, use invoices. If it’s a “heads up, here’s what you’re using” display, use analytics.

