An invoice represents a billed amount a merchant sends to a customer for payment.
A normal collection is an amount received immediately at the point of sale. A direct transaction captures a customer's card or bank details right away.
An invoice works differently. It lets the merchant establish the amount owed first. The customer can then act on it separately. The customer reviews an itemized total. Then the customer pays by card or ACH, on their own schedule.
This guide covers building invoicing into a business application with Flute's Invoices API. It covers creating an invoice and associating it with a customer. It also covers delivering the invoice to the customer. Finally, it covers tracking payment status, and modifying or canceling invoices.
Creating an invoice requires the customer being billed and line items that make up the charge.
To create an invoice, use: POST /pay-int-api/invoices
Some request fields are also stored as the default. For details of these values, see Checking Invoice Defaults.
The following example represents a common request.
{
"customerId": "fd9198a4-eb6f-4620-9603-4f4638289de5",
"merchantContactInfoId": "bdf4b5c6-7d8e-4f9a-0b1c-2d3e4f5a6b92",
"additionalNotes": "Extension permitted for 30 days.",
"lineItems":
[
{
"lineItemId": "b2c1d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d69",
"unitTypeId": 1,
"quantity": 3
},
{
"lineItemId": "c3d2e5f6-7a8b-4c9d-0e1f-2a3b4c5d6e70",
"unitTypeId": 1,
"quantity": 1,
"unitPrice": 15.00
}
]
}This request includes two lines items. For more information about line items, see Adding Line Items.
An invoice bills a specific customer. Passing customerId bills an existing customer record.
Not passing customerId works differently. Supply the customer's details instead. Flute then creates a new customer record from that information. It attaches the new record to the invoice.
The following is an example of not including a customerId.
"customer": {
"name": "Jordan Alvarez",
"email": "jordan.alvarez@example.com",
"phone": "+15551234567",
"billingAddress": {
"line1": "482 Birchwood Ave",
"city": "Austin",
"state": "TX",
"postalCode": "78701",
"country": "US"
}
}
...
"merchantContactInfoId": "bdf4b5c6-7d8e-4f9a-0b1c-2d3e4f5a6b92"The invoice also carries merchantContactInfoId. This identifies which of the merchant's own stored contact records appears on the invoice. That record holds the address, phone, and similar details for the biller.
The response only includes the id field, also called the invoiceId.
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}Specific information is retrieved from GET /pay-int-api/invoices/{{invoiceId}}. This includes identifiers and totals Flute calculates based on the lineItems listing. The following is an example from that call.
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"number": "INV-1042",
"status": 1,
"subTotalAmount": 3219.45,
"totalAmount": 3219.45,
"merchantId": "46063d32-10fa-44cb-b118-20ddd085ce3f",
"customerId": "fd9198a4-eb6f-4620-9603-4f4638289de5",
"dueDate": "2026-09-15"
}The id field is the invoice identifier.
All invoices begin in the Draft (1) status. While an invoice is in Draft, it can be freely edited or deleted. Editing uses PUT /pay-int-api/invoices/{invoiceId}.
Deleting uses DELETE /pay-int-api/invoices/{invoiceId}.
Nothing has been sent to the customer yet, so nothing is locked. That changes once the invoice is published. For details of publishing an invoice, see Publishing an Invoice.
A line item is a single billable product or service on an invoice. An invoice's total is built from one or more line items.
Line items come from a separate catalog or source. Each catalog entry has a name, description, SKU, unit price, unit type, and tax rate. Building a line items catalog lets the merchant reuse existing items, rather than re-entering them on each invoice. A line item can reference an existing catalog entry by the lineItemId field. It can optionally belong to a category to help organize the catalog.
This applies equally to creating an invoice and editing a draft one. Both POST /pay-int-api/invoices and PUT /pay-int-api/invoices/{invoiceId} accept a lineItems array. See the code example below.
{
"customerId": "fd9198a4-eb6f-4620-9603-4f4638289de5",
"dueDate": "2026-09-15",
"lineItems":
[
{
"lineItemId": "b2c1d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d69", // Adding a predefined line item
"quantity": 3,
"unitTypeId": 1
},
{
"lineItemId": "c3d2e5f6-7a8b-4c9d-0e1f-2a3b4c5d6e70", // Adding a predefined line item...
"unitPrice": 15.00, // ...but overriding the predefined price
"quantity": 1,
"unitTypeId": 1
}
]
}In this example: The first entry bills three units of a catalog item at its stored price.
The second overrides that catalog item's price for this invoice only.
This option is available only if canOverWriteInvoiceLineItemPrice is true. This value can be verified using GET /pay-int-api/merchants/{{merchantId}}/invoices/settings.
It can be set with PUT /pay-int-api/merchants/{{merchantId}}/invoices/settings
Creating an invoice uses some fields that are also stored as defaults.
Those defaults live at the merchant level, separate from any individual invoice. GET /pay-int-api/merchants/{merchantId}/invoices/settings retrieves them. This includes the default number of days until an invoice is due, dueDateAfterDays. It also includes whether tax, discount, shipping, and processing fees are enabled, and at what rate. It includes the merchant's chosen payment method type and processors. It includes staff permissions, such as whether a team member can override a line item's price. It also covers whether a team member can manually enter line items. Use: PUT /pay-int-api/merchants/{merchantId}/invoices/settings
This updates the full set. This replaces the whole settings object. The request must resend every field, not just the ones changing.
Publishing is what makes an invoice real for the customer. Use: POST /pay-int-api/invoices/publish.
The following example represents a common request. The invoiceId is the id returned from creating the invoice.
{
"invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}This moves its status from Draft (1) to Published (2). From that point, the invoice can no longer be edited or deleted.
Publishing alone doesn't notify anyone. Delivery is a separate, explicit step.
Use POST /pay-int-api/invoices/{invoiceId}/send-email-notification to email the customer a link to review and pay the invoice.
Use POST /pay-int-api/invoices/{invoiceId}/send-published-sms-notification to send the customer an SMS text message with a link to review and pay the invoice.
The merchant's invoice settings also control automatic notifications after a payment attempt. These are independent of the merchant-triggered sends above. isSmsNotificationAfterPaymentEnabled and isSmsNotificationAfterPaymentFailedEnabled control these automatic texts. They toggle whether the customer gets a text when payment succeeds or fails.
Every invoice also carries fullUrl and shortUrl. These are generated by Flute and are the hosted page the customer opens to pay. An application can link to either directly. This can be instead of, or in addition to, Flute's built-in notifications.
Some cases call for a document rather than a link. One example is attaching the invoice to an existing email or filing system. GET /pay-int-api/invoices/{invoiceId}/download-pdf returns a PDF copy for these cases.
An invoice's status field indicates where it stands in its lifecycle. It only moves in the directions the API defines:
| Value | Status | Meaning |
|---|---|---|
| 1 | Draft | The invoice has been created but not yet published, and it's still fully editable. |
| 2 | Published | The invoice has been sent to the customer, and it can no longer be deleted. |
| 3 | Paid | The invoice's payment has been collected. |
| 4 | Expired | The invoice passed its due date without payment. |
| 5 | Canceled | The merchant canceled a published, unpaid invoice. |
| 6 | ProcessingPayment | The ACH invoice's payment submission is in progress.. |
| 7 | Refunded | A paid invoice was refunded. |
Once an invoice is Published, payment is collected by submitting it.
POST /pay-int-api/invoices/{invoiceId}/submit submits a card payment.
Upon successful payment, the status becomes Paid.
POST /pay-int-api/invoices/{invoiceId}/ach/submit submits an ACH payment.
The ACH clearing process sets the status to ProcessingPayment first. If the payment is successful, the status becomes Paid. However, an ACH payment may also be declined or failed, which reverts it to 'Published'. In addition, it may also become Refunded.
Ultimately, the intent is to move the invoice Paid.
Sometimes payment happens outside the API entirely. One example is a check received in person. A check received in person doesn't flow through the invoice payment API. There is no card or ACH transaction to process. Instead, it's handled with PUT /pay-int-api/invoices/{{invoiceId}}/mark-as-paid. This distinguishes it from a payment collected through Flute. This endpoint moves the invoice directly to Paid without processing any payment. It only works on invoices currently marked as Published. This implies the invoice is due or past due and that it is not already paid.
GET /pay-int-api/invoices/{invoiceId}/calculations recomputes an invoice's totals on demand. This is useful for confirming the final amount before submitting payment. Sometimes it helps to check status across many invoices at once. GET /pay-int-api/invoices lists a merchant's invoices for this.
It supports filtering by the query parameters the endpoint accepts. Flute also keeps a history on each invoice. This records the events the invoice has passed through. It's returned as part of the invoice detail from GET /pay-int-api/invoices/{invoiceId}.
Editing is meant for the Draft stage.
PUT /pay-int-api/invoices/{invoiceId} updates a draft's customer, line items, or terms. It requires resending the invoice's complete set of fields. This applies even when only one field changed.
DELETE /pay-int-api/invoices/{invoiceId} removes a draft outright. This only works for a draft. Once an invoice is published, deletion is no longer available. This is by design, since the customer may already have seen it.
An invoice can become Published but no longer owed. PUT /pay-int-api/invoices/{invoiceId}/cancel cancels it, moving it to Canceled status.
This is restricted to published, unpaid invoices. There's no undoing a payment through this endpoint. A paid invoice is refunded through the transaction it produced. It is not canceled as an invoice.
This section lists every endpoint covered in this guide. For detailed information about each endpoint, see Invoices API Reference
- To retrieve a merchant's invoice settings, see
GET /pay-int-api/merchants/{merchantId}/invoices/settings. - To update a merchant's invoice settings, see
PUT /pay-int-api/merchants/{merchantId}/invoices/settings. - To list invoices for the current merchant, see
GET /pay-int-api/invoices. - To create a new invoice in Draft status, see
POST /pay-int-api/invoices. - To retrieve a single invoice's details, see
GET /pay-int-api/invoices/{invoiceId}. - To update a specified invoice, see
PUT /pay-int-api/invoices/{invoiceId}. - To delete a draft invoice, see
DELETE /pay-int-api/invoices/{invoiceId}. - To publish an invoice, sending it to the customer, see
POST /pay-int-api/invoices/publish. - To submit an invoice for card payment processing, see
POST /pay-int-api/invoices/{invoiceId}/submit. - To submit an invoice for ACH payment processing, see
POST /pay-int-api/invoices/{invoiceId}/ach/submit. - To cancel a published, unpaid invoice, see
PUT /pay-int-api/invoices/{invoiceId}/cancel. - To mark a published, unpaid invoice as paid, see
PUT /pay-int-api/invoices/{invoiceId}/mark-as-paid. - To retrieve the calculated totals for an invoice, see
GET /pay-int-api/invoices/{invoiceId}/calculations. - To download a PDF copy of the invoice, see
GET /pay-int-api/invoices/{invoiceId}/download-pdf. - To send the invoice to the customer by email, see
POST /pay-int-api/invoices/{invoiceId}/send-email-notification. - To send the invoice to the customer by SMS, see
POST /pay-int-api/invoices/{invoiceId}/send-published-sms-notification.