Documentation for 4.0 (pre-release). Using 3.x? See the README on main.
Skip to content

Invoice Comments (Rechnungskommentare) ​

API wrapper for invoice comments at /invoice-comments.

Access ​

php
$billomat->invoices->comments

The generic Justpilot\Billomat\Api\CommentsApi, typed for InvoiceComment, InvoiceCommentCreateOptions and InvoiceCommentActionKey.

Overview ​

For each invoice, Billomat records a stream of comments: some are system-generated (status changes, received payments, emails sent), some are written manually by users. Both kinds live in the same resource and differ only in the actionkey field:

  • System comments have actionkey set (COMPLETE, PAYMENT, EMAIL, …) and user_id = null.
  • Manual comments usually have no actionkey and a specific user_id.

Endpoints ​

MethodHTTPPath
list($invoiceId, $actionKeys?, $filters?)GET/invoice-comments?invoice_id={id}
listPage(…) / iterateAll(…, $pageSize?)GET/invoice-comments?invoice_id={id} (paginated)
get($id) / getOrFail($id)GET/invoice-comments/{id}
create($invoiceId, $options)POST/invoice-comments
delete($id)DELETE/invoice-comments/{id}

There is intentionally no list() without invoice_id; Billomat requires the filter.

Methods ​

list(int $invoiceId, ?array $actionKeys = null, SubResourceFilter|array $filters = []): list<InvoiceComment> ​

Lists all comments of an invoice. You can optionally filter by InvoiceCommentActionKey values; the list is sent to Billomat comma-separated. Passing a different enum throws an InvalidArgumentException.

php
use Justpilot\Billomat\Api\OrderBy;
use Justpilot\Billomat\Api\SubResourceFilter;
use Justpilot\Billomat\Model\Enum\InvoiceCommentActionKey;

// All comments
$all = $billomat->invoices->comments->list(98765);

// Only payment and dunning entries
$financial = $billomat->invoices->comments->list(
    98765,
    [InvoiceCommentActionKey::PAYMENT, InvoiceCommentActionKey::DUNNING],
);

// Newest first, 20 per page
$latest = $billomat->invoices->comments->list(
    98765,
    filters: new SubResourceFilter(orderBy: OrderBy::desc('created'), perPage: 20),
);

SubResourceFilter (orderBy, page, perPage, extra) sorts and paginates. listPage() and iterateAll() take the same arguments (iterateAll() additionally $pageSize); see Pagination.

get(int $id): ?InvoiceComment / getOrFail(int $id): InvoiceComment ​

get() returns null on 404; getOrFail() throws a NotFoundException instead.

create(int $invoiceId, InvoiceCommentCreateOptions $options): InvoiceComment ​

php
use Justpilot\Billomat\Api\InvoiceCommentCreateOptions;

$comment = $billomat->invoices->comments->create(
    98765,
    new InvoiceCommentCreateOptions(
        comment: 'Client called for clarification; call back scheduled for 2026-06-05.',
    ),
);

actionkey is optional and should be left empty for manual comments; Billomat fills it automatically for system actions.

delete(int $id): void ​

Deletes a comment. Errors are thrown as exceptions.

Write model: InvoiceCommentCreateOptions ​

Constructor: new InvoiceCommentCreateOptions(string $comment, …). The object is immutable (final readonly) and has a with*() method per field. The invoice ID is the first argument of create(), which adds it to the payload as invoice_id.

PropertyBillomat fieldTypeNotes
commentcommentstringRequired (constructor)
actionkeyactionkey?InvoiceCommentActionKeyRarely set manually
publicpublic?boolVisible in the client's activity list (Billomat default: false)

toArray() drops null values.

Read model: InvoiceComment ​

final readonly class InvoiceComment.

PropertyTypeNotes
idint
invoiceIdint
comment?string
created?\DateTimeImmutable
userId?intnull for system comments
actionkey?InvoiceCommentActionKeynull for an unknown or missing value
actionkeyRaw?stringOriginal API string, even if the enum doesn't know the value
public?bool
byClient?bool
emailId?int
clientId?int
customfield?stringFree extra field, see custom meta attributes
extraarray<string, mixed>Fields the SDK doesn't map (yet), raw; see models

Enum: InvoiceCommentActionKey ​

InvoiceCommentActionKey covers the action keys observed in API output:

CaseWire value
CREATECREATE
EDITEDIT
OPENOPEN
COMPLETECOMPLETE
CANCELCANCEL
UNCANCELUNCANCEL
CHANGE_STATUSCHANGE_STATUS
PAYMENTPAYMENT
EMAILEMAIL
MAILMAIL
DUNNINGDUNNING
COMMENTCOMMENT

Billomat doesn't document a closed list. If new values show up, the SDK parses actionkey to null and fills actionkeyRaw with the original string, so nothing is lost.

Pitfalls ​

  • invoice_id is required. Without the filter Billomat responds with 400; list() sets it automatically.
  • Don't fake system comments. actionkey is primarily API output. Setting a value like PAYMENT manually can distort the activity view in the Billomat UI.
  • delete() also deletes system comments. Be careful when cleaning up: system entries are part of the audit trail.

End-to-end example ​

php
<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use Justpilot\Billomat\Api\InvoiceCommentCreateOptions;
use Justpilot\Billomat\BillomatClient;
use Justpilot\Billomat\Model\Enum\InvoiceCommentActionKey;

$billomat = BillomatClient::create(
    billomatId: 'mycompany',
    apiKey: getenv('BILLOMAT_API_KEY'),
);

$invoiceId = 98765;

// 1) Add a manual comment
$billomat->invoices->comments->create(
    $invoiceId,
    new InvoiceCommentCreateOptions(
        comment: 'Client asks for a 14-day extension.',
    ),
);

// 2) Show the full history
foreach ($billomat->invoices->comments->list($invoiceId) as $c) {
    printf(
        "[%s] %s: %s\n",
        $c->created?->format('Y-m-d H:i') ?? '???',
        $c->actionkey?->value ?? ($c->actionkeyRaw ?? 'manual'),
        $c->comment ?? '',
    );
}

// 3) Only the dunning history
$dunning = $billomat->invoices->comments->list(
    $invoiceId,
    [InvoiceCommentActionKey::DUNNING],
);
printf("Dunning entries: %d\n", count($dunning));

Unofficial SDK, not affiliated with Billomat GmbH. Released under the Apache License 2.0.