top of page

Invoices API

Create, find, update, close and resend invoices with the REST v5 contract.

Authentication and sandbox

These operations use a merchant API key in the Authorization header. The published OpenAPI server is https://sandbox.nmi.com/api. Keep the private key on your server. The examples below target sandbox and use placeholders; supply your own sandbox records and an email inbox you control. Source review only. No invoice, product, API request or email was created or sent while preparing this guide.

Create an invoice

POST /v5/invoices creates the invoice and emails the customer. Treat this as an external communication, not a draft-saving endpoint. The only schema-required property is amount; customer delivery still needs a usable recipient. Request field Contract amount Number greater than zero; decimal currency amount. currency Uppercase three-letter ISO currency code. billing_address.email Email string for the billing contact. order_details.order_id / customer_id Strings, each at most 255 characters. payment_terms String; upon_receipt by default, or a day count from 0 to 999. payment_methods_allowed Array containing cc, ck or cs. subtotal Optional nonnegative number. POST /api/v5/invoices HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> Content-Type: application/json { "amount": 25.00, "currency": "USD", "billing_address": { "email": "sandbox-recipient@example.com" }, "order_details": { "order_id": "demo-order-001", "customer_id": "demo-customer-001" }, "payment_terms": "upon_receipt", "payment_methods_allowed": ["cc"] } Replace the example address with an inbox you control before an authorized sandbox test. The schema mentions up to 99 item_* sets without defining their exact names here; this guide does not invent a line-item payload.

List and paginate

GET /v5/invoices returns invoices, per_page, has_more and next_cursor. Start without cursor, then pass the returned opaque string unchanged. next_cursor can be absent when results end. Query Contract status open, partially_paid, paid, closed or overdue. customer_id Exact-match string, up to 255 characters. date_from / date_to Inclusive creation-date bounds, valid YYYY-MM-DD calendar dates. cursor Returned string, up to 512 characters. per_page Integer 1–100; default 10. GET /api/v5/invoices?status=open&per_page=10 HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> HTTP 400 covers invalid calendar dates or invalid cursors. HTTP 422 covers disallowed or unsupported parameters, malformed values, or an overly broad search. Narrow the filter when necessary.

Get an invoice and read the response

GET /v5/invoices/{invoice_id} takes an integer invoice ID. A successful read returns the same InvoiceResponse shape used by create, update, close and send. A missing record returns HTTP 404. Response field Type and meaning object / id object is invoice; id is an integer. These are the schema-required fields. status open, partially_paid, paid, closed or overdue. amount / subtotal amount is a decimal string; subtotal is a nullable number. currency / payment_terms Currency string and human-readable terms string. created_date / updated_date Nullable ISO 8601 UTC date-time strings. billing_address / shipping_address Contact and address objects. order_details / merchant_defined_fields Order metadata and merchant-defined values. GET /api/v5/invoices/12345 HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key>

Update without sending another email

PUT /v5/invoices/{invoice_id} accepts a JSON update object. Fields are optional: send only intended changes. The operation does not send a replacement email. Read the returned invoice before deciding whether to send it separately. PUT /api/v5/invoices/12345 HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> Content-Type: application/json { "amount": 30.00, "payment_terms": "30" } The schema includes amount, subtotal, payment_terms, payment_methods_allowed, processor_id, billing_address, shipping_address, order_details and merchant_defined_fields. HTTP 200 returns InvoiceResponse; documented failure statuses are 400, 401 and 404. Source inconsistency: the narrative excludes currency changes, although UpdateInvoiceRequest includes currency. Do not rely on changing invoice currency until NMI confirms the behavior.

Close an invoice

DELETE /v5/invoices/{invoice_id} closes the invoice. It does not represent a payment refund. A closed invoice cannot be paid or modified. Confirm the selected record and intended lifecycle action before calling it. DELETE /api/v5/invoices/12345 HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> No request body is defined. HTTP 200 returns InvoiceResponse. Failures include 400, 401 and 404. Recommended application behavior: retain the invoice ID and returned status in your audit record.

Send an existing invoice

POST /v5/invoices/{invoice_id}/send emails the existing invoice. Use it deliberately after a change or an authorized resend request. Do not automatically resend after a timeout: delivery might already have occurred. POST /api/v5/invoices/12345/send HTTP/1.1 Host: sandbox.nmi.com Authorization: <sandbox-private-key> No request body is defined. HTTP 200 returns InvoiceResponse. Failures include 400, 401 and 404. The source does not establish an idempotency key or email-delivery receipt contract for this operation.

Join the community and get the latest biz news & tips

Thanks for submitting!

© 2025 Betterpay. All Rights Reserved.

bottom of page