> ## Documentation Index
> Fetch the complete documentation index at: https://developers.novala.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Invoices API — List, Retrieve, and Update Invoices

> Access invoice records with line items and payment history. Filter by status and date range, and update notes, due dates, and custom fields via PATCH.

Invoices track billable amounts sent to companies. Each invoice moves through a lifecycle from draft to payment and includes line items, tax calculations, and payment records. You can filter the list by status and date, retrieve full detail with line items and payments, and update metadata fields via PATCH.

<Note>
  All invoice endpoints are scoped to your tenant. Pass your API key in the `Authorization: Bearer` header on every request.
</Note>

## Invoice statuses

| Status           | Meaning                               |
| ---------------- | ------------------------------------- |
| `draft`          | Created but not yet sent.             |
| `sent`           | Sent to the customer.                 |
| `viewed`         | Customer has opened the invoice.      |
| `partially_paid` | Payment received but balance remains. |
| `paid`           | Fully paid.                           |
| `overdue`        | Past the due date and unpaid.         |
| `voided`         | Cancelled; no payment expected.       |

***

## List invoices

`GET /api/invoices`

Returns a paginated list of invoices for the authenticated tenant, with company name included in each row.

### Query parameters

<ParamField query="status" type="string">
  Filter by invoice status. One of: `draft`, `sent`, `viewed`, `partially_paid`, `paid`, `overdue`, `voided`.
</ParamField>

<ParamField query="search" type="string">
  Search by invoice number or company name (case-insensitive).
</ParamField>

<ParamField query="dateFrom" type="string">
  Return invoices with `issuedDate` on or after this date (`YYYY-MM-DD`).
</ParamField>

<ParamField query="dateTo" type="string">
  Return invoices with `issuedDate` on or before this date (`YYYY-MM-DD`).
</ParamField>

<ParamField query="page" type="integer" default="1">
  1-based page index.
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Results per page. Maximum `100`.
</ParamField>

### Response

```json theme={null}
{
  "data": [
    {
      "id": "inv-uuid-001",
      "invoiceNumber": "INV-2024-0042",
      "status": "sent",
      "companyName": "Acme Corp",
      "issuedDate": "2024-07-01",
      "dueDate": "2024-07-31",
      "totalAmount": "4500.00",
      "amountPaid": "0.00",
      "balanceDue": "4500.00",
      "createdAt": "2024-07-01T10:00:00Z"
    }
  ],
  "total": 15
}
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://app.novala.ai/api/invoices?status=sent&dateFrom=2024-07-01" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```typescript TypeScript theme={null}
  const params = new URLSearchParams({ status: 'sent', dateFrom: '2024-07-01' });
  const response = await fetch(`https://app.novala.ai/api/invoices?${params}`, {
    headers: { 'Authorization': `Bearer ${apiKey}` },
  });
  const { data, total } = await response.json();
  ```
</CodeGroup>

***

## Get an invoice

`GET /api/invoices/{id}`

Retrieves a full invoice record with company details, optional contact, all line items, and all payment records.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the invoice.
</ParamField>

### Response fields

<ResponseField name="id" type="string">UUID of the invoice.</ResponseField>
<ResponseField name="invoiceNumber" type="string">Human-readable invoice number (for example, `INV-2024-0042`).</ResponseField>
<ResponseField name="status" type="string">Current status of the invoice.</ResponseField>
<ResponseField name="companyId" type="string">UUID of the billed company.</ResponseField>
<ResponseField name="contactId" type="string | null">UUID of the associated contact.</ResponseField>
<ResponseField name="quoteId" type="string | null">UUID of the originating quote, if any.</ResponseField>
<ResponseField name="issuedDate" type="string | null">Issue date (`YYYY-MM-DD`).</ResponseField>
<ResponseField name="dueDate" type="string | null">Payment due date (`YYYY-MM-DD`).</ResponseField>
<ResponseField name="subtotal" type="string">Subtotal before tax as a decimal string.</ResponseField>
<ResponseField name="taxRate" type="string">Tax rate as a decimal string (for example, `"0.08"` for 8%).</ResponseField>
<ResponseField name="taxAmount" type="string">Calculated tax amount.</ResponseField>
<ResponseField name="totalAmount" type="string">Total amount including tax.</ResponseField>
<ResponseField name="amountPaid" type="string">Total amount paid to date.</ResponseField>
<ResponseField name="balanceDue" type="string">Remaining balance.</ResponseField>
<ResponseField name="notes" type="string | null">Internal notes.</ResponseField>
<ResponseField name="customerNotes" type="string | null">Notes visible to the customer on the invoice.</ResponseField>
<ResponseField name="customFields" type="object">Custom field key-value pairs.</ResponseField>
<ResponseField name="sentAt" type="string | null">Timestamp when the invoice was sent.</ResponseField>
<ResponseField name="paidAt" type="string | null">Timestamp when the invoice was fully paid.</ResponseField>

<ResponseField name="company" type="object">
  <Expandable title="Company object">
    <ResponseField name="name" type="string">Company name.</ResponseField>
    <ResponseField name="address" type="string | null">Billing address.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="contact" type="object | null">
  <Expandable title="Contact object">
    <ResponseField name="firstName" type="string">First name.</ResponseField>
    <ResponseField name="lastName" type="string">Last name.</ResponseField>
    <ResponseField name="email" type="string | null">Email address.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="lineItems" type="array">
  <Expandable title="Line item object">
    <ResponseField name="id" type="string">UUID.</ResponseField>
    <ResponseField name="description" type="string">Line item description.</ResponseField>
    <ResponseField name="quantity" type="string">Quantity as a decimal string.</ResponseField>
    <ResponseField name="unitPrice" type="string">Unit price as a decimal string.</ResponseField>
    <ResponseField name="total" type="string">Line total (`quantity × unitPrice`).</ResponseField>
    <ResponseField name="sortOrder" type="integer">Display order.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="payments" type="array">
  <Expandable title="Payment object">
    <ResponseField name="id" type="string">UUID.</ResponseField>
    <ResponseField name="amount" type="string">Amount paid.</ResponseField>
    <ResponseField name="paymentDate" type="string">Date of payment (`YYYY-MM-DD`).</ResponseField>
    <ResponseField name="paymentMethod" type="string">One of `check`, `ach`, `credit_card`, `cash`, `other`.</ResponseField>
    <ResponseField name="referenceNumber" type="string | null">Check number or transaction ID.</ResponseField>
    <ResponseField name="notes" type="string | null">Payment notes.</ResponseField>
  </Expandable>
</ResponseField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://app.novala.ai/api/invoices/inv-uuid-001 \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://app.novala.ai/api/invoices/inv-uuid-001', {
    headers: { 'Authorization': `Bearer ${apiKey}` },
  });
  const invoice = await response.json();
  // invoice.lineItems, invoice.payments, invoice.balanceDue, etc.
  ```
</CodeGroup>

***

## Update an invoice

`PATCH /api/invoices/{id}`

Updates metadata fields on an invoice. Status transitions (sending, voiding, recording payments) are handled by sub-routes not covered here; this endpoint is for notes, due date, and custom field overrides.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the invoice to update.
</ParamField>

### Request body

All fields are optional.

<ParamField body="notes" type="string | null">
  Updated internal notes. Pass `null` to clear.
</ParamField>

<ParamField body="customerNotes" type="string | null">
  Updated customer-facing notes. Pass `null` to clear.
</ParamField>

<ParamField body="dueDate" type="string | null">
  Updated due date (`YYYY-MM-DD`). Pass `null` to clear.
</ParamField>

<ParamField body="customFields" type="object">
  Replaces all custom field values with the provided map.
</ParamField>

### Response

Returns `200 OK` with the updated invoice object. Returns `404 Not Found` if the invoice does not exist or belongs to a different tenant.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://app.novala.ai/api/invoices/inv-uuid-001 \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "dueDate": "2024-08-15",
      "customerNotes": "Please remit via ACH to the account on file."
    }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://app.novala.ai/api/invoices/inv-uuid-001', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      dueDate: '2024-08-15',
      customerNotes: 'Please remit via ACH to the account on file.',
    }),
  });
  const updated = await response.json();
  ```
</CodeGroup>
