> For the complete documentation index, see [llms.txt](https://teamleader-sdk.mcore-services.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://teamleader-sdk.mcore-services.dev/api-reference/invoicing/invoices.md).

# Invoices

Manage invoices in Teamleader Focus.

Invoices in Teamleader Focus.

**Untitled sections.** In `grouped_lines`, the `section` key is optional. A group with no title must omit the key entirely — Teamleader rejects both `['section' => ['title' => null]]` and `['section' => ['title' => '']]` with HTTP 400. This matters on read-modify-write: `info()` returns `section.title` as `null` for untitled sections, so echoing that value straight back is rejected. Drop the key instead:

```
foreach ($info['data']['grouped_lines'] as $group) {
    $out = ['line_items' => $lineItems];

    if (! empty($group['section']['title'])) {
        $out['section'] = ['title' => $group['section']['title']];
    }

    $groupedLines[] = $out;
}
```

Untitled sections are common: Teamleader's UI creates them by default when the user does not name a section.

```php
Teamleader::invoices()
```

|                          |                                                                       |
| ------------------------ | --------------------------------------------------------------------- |
| Class                    | `McoreServices\TeamleaderSDK\Resources\Invoicing\Invoices`            |
| Create / update / delete | ✓ / ✓ / ✓                                                             |
| Pagination               | `page_size` / `page_number`; no totals — a short page is the last one |

## Endpoints

* `invoices.book`
* `invoices.copy`
* `invoices.credit`
* `invoices.creditPartially`
* `invoices.delete`
* `invoices.download`
* `invoices.draft`
* `invoices.info`
* `invoices.list`
* `invoices.registerPayment`
* `invoices.removePayments`
* `invoices.send`
* `invoices.sendViaPeppol`
* `invoices.update`
* `invoices.updateBooked`

## Filters

Passed as the first argument to `list()`. Any other key throws.

| Filter                  | Description                                                                     |
| ----------------------- | ------------------------------------------------------------------------------- |
| `customer`              | Customer object with type and id                                                |
| `deal_id`               | Filter on deal UUID                                                             |
| `department_id`         | Filter on department (company entity)                                           |
| `ids`                   | Array of invoice UUIDs                                                          |
| `invoice_date_after`    | Date (inclusive, YYYY-MM-DD)                                                    |
| `invoice_date_before`   | Date (inclusive, YYYY-MM-DD)                                                    |
| `invoice_number`        | Full invoice number (fiscal year / number)                                      |
| `payment_reference`     | Payment reference                                                               |
| `project_id`            | Filter on project UUID                                                          |
| `purchase_order_number` | Purchase order number                                                           |
| `status`                | Array of statuses (draft, outstanding, matched)                                 |
| `subscription_id`       | Filter on subscription UUID                                                     |
| `term`                  | Search on invoice number, purchase order number, payment reference and invoicee |
| `updated_since`         | ISO 8601 datetime                                                               |

## Sorting

Pass `sort` (and optionally `sort_order`) in the options. Any other field throws.

| Field            | Description    |
| ---------------- | -------------- |
| `invoice_date`   | Invoice date   |
| `invoice_number` | Invoice number |

## Includes

`list()` and `info()` accept the same includes:

`late_fees`, `totals.due_incasso_inclusive`, `totals.fixed_late_fee`, `totals.interest`

## Accepted values

Public constants on the class. Body fields and enum values outside these lists throw before the request is sent.

| Constant               | Values                                                                                                                                                                                                                                                                       |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DRAFT_FIELDS`         | `invoicee`, `department_id`, `payment_term`, `grouped_lines`, `invoice_date`, `discounts`, `note`, `currency`, `purchase_order_number`, `project_id`, `quotation_id`, `expected_payment_method`, `custom_fields`, `document_template_id`, `delivery_date`, `invoice_content` |
| `INCLUDES`             | `late_fees`, `totals.due_incasso_inclusive`, `totals.fixed_late_fee`, `totals.interest`                                                                                                                                                                                      |
| `INVOICE_CONTENT`      | `goods`, `services`, `goods_and_services`                                                                                                                                                                                                                                    |
| `UPDATE_BOOKED_FIELDS` | `invoicee`, `payment_term`, `grouped_lines`, `invoice_date`, `note`, `project_id`, `expected_payment_method`, `custom_fields`, `invoice_content`                                                                                                                             |
| `UPDATE_FIELDS`        | `invoicee`, `payment_term`, `grouped_lines`, `invoice_date`, `discounts`, `note`, `currency`, `purchase_order_number`, `project_id`, `expected_payment_method`, `custom_fields`, `document_template_id`, `delivery_date`, `invoice_content`                                  |

## Methods

### `info()`

```php
info($id, $includes = null): array
```

Get detailed information about a specific invoice

Response includes all list fields plus: discounts, grouped\_lines (with full line item detail), payment\_term, payments, payment\_reference, note, currency, currency\_exchange\_rate, expected\_payment\_method, on\_hold\_since, custom\_fields, document\_template, delivery\_date (nullable), peppol\_status (nullable)

* `$id` — Invoice UUID
* `$includes` — late\_fees, totals.due\_incasso\_inclusive, totals.fixed\_late\_fee, totals.interest

**Throws** `InvalidArgumentException` When an include is not valid for this endpoint

### `create()`

```php
create(array $data): array
```

Draft a new invoice

Required fields:

* invoicee (object): customer {type, id} and optional for\_attention\_of
* department\_id (string): Department UUID
* payment\_term (object): type and optional days
* grouped\_lines (array): sections with line\_items

Optional fields:

* currency (object): code and optional exchange\_rate
* project\_id (string): Project UUID
* quotation\_id (string): links the invoice to a source quotation and its deal, and marks the deal as won
* purchase\_order\_number (string)
* invoice\_date (string): YYYY-MM-DD
* discounts (array)
* note (string)
* expected\_payment\_method (object): method and optional reference
* custom\_fields (array)
* document\_template\_id (string)
* delivery\_date (string|null): YYYY-MM-DD — the delivery/service date shown on the invoice
* `$data` — Invoice data

### `update()`

```php
update($id, array $data): array
```

Update a draft invoice Note: Booked invoices cannot be updated with this method

Updatable fields:

* invoicee (object): customer {type, id} and optional for\_attention\_of
* payment\_term (object): nullable, type and optional days
* currency (object): code and optional exchange\_rate
* project\_id (string)
* purchase\_order\_number (string)
* grouped\_lines (array): sections with line\_items
* invoice\_date (string): YYYY-MM-DD
* note (string|null)
* discounts (array)
* expected\_payment\_method (object|null)
* custom\_fields (array)
* document\_template\_id (string)
* delivery\_date (string|null): YYYY-MM-DD — the delivery/service date shown on the invoice
* `$id` — Invoice UUID
* `$data` — Invoice data to update

### `updateBooked()`

```php
updateBooked(string $id, array $data): array
```

Update a booked invoice Note: Only available when editing booked invoices is allowed through the settings

* `$id` — Invoice UUID
* `$data` — Invoice data to update

### `delete()`

```php
delete($id, ...$additionalParams): array
```

Delete an existing invoice Only possible for draft invoices or the last booked invoice

* `$id` — Invoice UUID
* `$additionalParams` — Additional parameters (not used for invoices)

### `book()`

```php
book(string $id, string $on): array
```

Book a draft invoice

* `$id` — Invoice UUID
* `$on` — Booking date (YYYY-MM-DD format)

### `copy()`

```php
copy(string $id): array
```

Copy an invoice to create a new draft

* `$id` — Invoice UUID to copy

### `credit()`

```php
credit(string $id, string $creditNoteDate): array
```

Credit an invoice completely

* `$id` — Invoice UUID
* `$creditNoteDate` — Credit note date (YYYY-MM-DD format)

### `creditPartially()`

```php
creditPartially(string $id, string $creditNoteDate, array $groupedLines, ?array $discounts = null): array
```

Credit an invoice partially

* `$id` — Invoice UUID
* `$creditNoteDate` — Credit note date (YYYY-MM-DD format)
* `$groupedLines` — Grouped lines to credit
* `$discounts` — Optional discounts

### `download()`

```php
download(string $id, string $format = 'pdf'): array
```

Download an invoice in a specific format

* `$id` — Invoice UUID
* `$format` — Format (pdf, ubl/e-fff, ubl/peppol\_bis\_3, ubl/xrechnung)

### `send()`

```php
send(string $id, array $content, array $recipients = [], ?array $attachments = null): array
```

Send an invoice via email

* `$id` — Invoice UUID
* `$content` — Email content (subject, body, optional mail\_template\_id)
* `$recipients` — Recipients (to, cc, bcc arrays)
* `$attachments` — Optional file IDs to attach

### `sendViaPeppol()`

```php
sendViaPeppol(string $id): array
```

Send an invoice via the Peppol network

* `$id` — Invoice UUID

### `registerPayment()`

```php
registerPayment(string $id, array $payment, string $paidAt, ?string $paymentMethodId = null): array
```

Register a payment for an invoice

* `$id` — Invoice UUID
* `$payment` — Payment data (amount, currency)
* `$paidAt` — Payment date (ISO 8601 format)
* `$paymentMethodId` — Optional payment method UUID

### `removePayments()`

```php
removePayments(string $id): array
```

Remove all payments from an invoice (marks as unpaid)

* `$id` — Invoice UUID

### `draft()`

> **Deprecated** Use listDrafts() — draft() is easily confused with create(), which is what actually creates a draft (POST invoices.draft).

```php
draft(array $additionalFilters = [], array $options = []): array
```

List draft invoices.

* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `listDrafts()`

```php
listDrafts(array $additionalFilters = [], array $options = []): array
```

List draft invoices.

* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `list()`

```php
list(array $filters = [], array $options = []): array
```

List invoices with filtering and sorting

Response includes: id, department, invoice\_number, invoice\_date, status, due\_on, paid, paid\_at, sent, purchase\_order\_number, payment\_reference, invoicee, total, currency\_exchange\_rate, created\_at, updated\_at, web\_url, file, deal, project, subscription (nullable object: {id, type}), delivery\_date (nullable), peppol\_status (nullable)

* `$filters` — Filter parameters
* `$options` — Pagination and sorting options

### `outstanding()`

```php
outstanding(array $additionalFilters = [], array $options = []): array
```

Get outstanding invoices

* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `matched()`

```php
matched(array $additionalFilters = [], array $options = []): array
```

Get matched invoices

* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `forCustomer()`

```php
forCustomer(string $customerType, string $customerId, array $additionalFilters = [], array $options = []): array
```

Get invoices for a specific customer

* `$customerType` — Customer type (contact or company)
* `$customerId` — Customer UUID
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `forProject()`

```php
forProject(string $projectId, array $additionalFilters = [], array $options = []): array
```

Get invoices for a specific project

* `$projectId` — Project UUID
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `forDeal()`

```php
forDeal(string $dealId, array $additionalFilters = [], array $options = []): array
```

Get invoices for a specific deal

* `$dealId` — Deal UUID
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `forDepartment()`

```php
forDepartment(string $departmentId, array $additionalFilters = [], array $options = []): array
```

Get invoices for a specific department

* `$departmentId` — Department UUID
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `search()`

```php
search(string $term, array $additionalFilters = [], array $options = []): array
```

Search invoices by term

* `$term` — Search term
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `updatedSince()`

```php
updatedSince(string $datetime, array $additionalFilters = [], array $options = []): array
```

Get invoices updated since a specific date

* `$datetime` — ISO 8601 datetime
* `$additionalFilters` — Additional filters to apply
* `$options` — Pagination and sorting options

### `getResponseStructure()`

```php
getResponseStructure(): array
```

Get response structure documentation

### `getValidPeppolStatuses()`

```php
getValidPeppolStatuses(): array
```

Get the possible Peppol submission statuses.

These are the values that may appear in the (nullable) `peppol_status` field of info()/list() responses. Peppol status is read-only — it is not a request parameter or a list filter.

## Examples

Get all invoices:

```php
$invoices = Teamleader::invoices()->list();
```

Draft a new invoice:

```php
$invoice = Teamleader::invoices()->create([...]);
```

Draft a new invoice with a delivery date:

```php
$invoice = Teamleader::invoices()->create([..., 'delivery_date' => '2025-12-08']);
```

Get outstanding invoices:

```php
$invoices = Teamleader::invoices()->outstanding();
```

Get invoices for a specific customer:

```php
$invoices = Teamleader::invoices()->forCustomer('company', 'customer-uuid');
```

Get detailed invoice information:

```php
$invoice = Teamleader::invoices()->info('invoice-uuid');
```

Get invoice with late fee calculations:

```php
$invoice = Teamleader::invoices()->info('invoice-uuid', 'late_fees');
```

Get the most recent invoices first:

```php
$invoices = Teamleader::invoices()->list([], ['sort' => 'invoice_date', 'sort_order' => 'desc']);
```

Book a draft invoice:

```php
$result = Teamleader::invoices()->book('invoice-uuid', '2024-01-15');
```

Create a new draft based on existing invoice:

```php
$newInvoice = Teamleader::invoices()->copy('invoice-uuid');
```

Update a draft invoice:

```php
$result = Teamleader::invoices()->update('invoice-uuid', [...]);
```

Update the delivery date on a draft invoice:

```php
$result = Teamleader::invoices()->update('invoice-uuid', ['delivery_date' => '2025-12-08']);
```

Update a booked invoice (if allowed in settings):

```php
$result = Teamleader::invoices()->updateBooked('invoice-uuid', [...]);
```

Credit an invoice completely:

```php
$creditNote = Teamleader::invoices()->credit('invoice-uuid', '2024-02-04');
```

Credit an invoice partially:

```php
$creditNote = Teamleader::invoices()->creditPartially('invoice-uuid', '2024-02-04', [...]);
```

Download invoice as PDF:

```php
$download = Teamleader::invoices()->download('invoice-uuid', 'pdf');
```

Send invoice via email:

```php
$result = Teamleader::invoices()->send('invoice-uuid', [...]);
```

Send invoice via Peppol:

```php
$result = Teamleader::invoices()->sendViaPeppol('invoice-uuid');
```

Register a payment for an invoice:

```php
$result = Teamleader::invoices()->registerPayment('invoice-uuid', [...]);
```

Remove all payments from an invoice:

```php
$result = Teamleader::invoices()->removePayments('invoice-uuid');
```

Delete a draft or last booked invoice:

```php
$result = Teamleader::invoices()->delete('invoice-uuid');
```
