Skip to content

Invoice ​

Allowed query parameters ​

Filters ​

FilterTypeDescription
searchStringFull-text search
ownBooleanShow only own invoices
projectIdFilter by Project Id
companyStringFilter by Company Id
contactStringFilter by Contact Id
productStringFilter by Product Id
statusStringFilter based on status:
paid, pending, overdue, draft, dunned, paidOrPending, cancelled
date_rangeDateRangeFilter by issued date
<start-date>,<end-date>
total_rangeNumberRangeFilter by total amount
<min-amount>,<max-amount> or just <min-amount>
net_total_rangeNumberRangeFilter by net total amount
<min-amount>,<max-amount> or just <min-amount>
memberStringFilter by Member Id
recurringBooleanShow only recurring invoices
exportedBooleanShow only exported invoices
custom_fieldKey,StringFilter by Custom Field (eg. my_internal_id,42)
trashedBooleanInclude soft-deleted invoices

Sorting ​

issued_at, due_at, paid_at, number_sequence, created_at

Includes ​

project.invoices, project.unbilledExpenses, contact.company.media, company.media, elements.tag, elements.product, member.user.media, createdBy.user.media, updatedBy.user.media, activities, expenses, expensesCount, lockedTimes, lockedTimesCount, sourceOffer, bankAccount, commentsCount, comments.commentator.media, payments.bankAccount, media, latestOutgoingMail

Appends ​

(Available append parameters for additional computed fields)

current_dunning_level, next_dunning_level, auto_dunning_active, dunning_text, vat_detailed

vat_detailed contains the invoice's VAT amounts grouped by VAT Rate: [{ "id": <vat-rate-id|null>, "rate": 7.7, "total": 8271.35, "amount": 591.35 }], where total is the gross amount and amount the VAT share (both in document currency).

Create an invoice ​

post
/invoice
Attribute (* required)TypeDescription
nameString?Invoice title (max 255 characters)
project_idString?A Project Id (min 10 characters). For a sub-project, its parent is assigned
contact_id *StringA Contact Id (min 10 characters)
include_vatBooleanWith/without taxes
issued_atDateIssue date
due_atDate?Due date (must be after or equal to issued_at)
due_withinNumber?Due in days (0-365, used when due_at is empty)
paid_atDate?Deprecated — Paid date (on or after issued_at)
descriptionString?Invoice description
remindedNumberDunning level (0 to max dunning levels)
addressString?Recipient Address
headerString?Header text
footerString?Footer text
has_page_break_after_headerBooleanAdd page break after header
has_page_break_before_footerBooleanAdd page break before footer
recurring_typeString?Recurrence type (weeks, months, years)
recurring_everyNumber?Recurrence interval (1-99)
recurring_ends_atDate?Recurrence end date
revenue_account_noString?Revenue account number
bank_account_idString?Bank account ID (min 10 characters)
custom_fieldsObject?Custom data as Custom Fields

Deprecated: paid_at

Setting paid_at directly still works for backwards compatibility, but is deprecated and will not mark the invoice as paid the way the app does — it fires no paid side effects (no Paid webhook, notifications, or dashboard updates). To record a payment, add an invoice payment or use Update invoice status with status: paid.

Example response ​

json
// HTTP 201 Created
{
    // an invoice object
}

Update an invoice ​

put
/invoice/{id}
Attribute (* required)TypeDescription
nameString?Invoice title (max 255 characters)
project_idString?A Project Id (min 10 characters). For a sub-project, its parent is assigned
contact_idStringA Contact Id (min 10 characters)
totalNumber?Total amount (max 99999999.99)
include_vatBooleanWith/without taxes
is_scheduled_for_sendingBooleanSchedule invoice for auto-sending
issued_atDateIssue date (must be before or equal to due_at)
due_atDateDue date (must be after or equal to issued_at)
paid_atDate?Deprecated — Paid date (on or after issued_at)
sent_atDate?Sent date
descriptionString?Invoice description
remindedNumberDunning level (0 to max dunning levels)
is_dunning_pausedBooleanExclude from automatic dunning («Mahnstopp»)
addressStringRecipient Address
headerString?Header text
footerString?Footer text
has_page_break_after_headerBooleanAdd page break after header
has_page_break_before_footerBooleanAdd page break before footer
recurring_typeString?Recurrence type (weeks, months, years)
recurring_everyNumber?Recurrence interval (1-99)
recurring_ends_atDate?Recurrence end date
revenue_account_noString?Revenue account number
is_exportedBooleanWhether invoice has been exported
bank_account_idString?Bank account ID (min 10 characters)
custom_fieldsObject?Custom data as Custom Fields

Deprecated: paid_at

Setting paid_at directly still works for backwards compatibility, but is deprecated and will not mark the invoice as paid the way the app does — it fires no paid side effects (no Paid webhook, notifications, or dashboard updates). To record a payment, add an invoice payment or use Update invoice status with status: paid.

Example response ​

json
// HTTP 200 OK
{
    // an invoice object
}

Dunning pause («Mahnstopp»)

is_dunning_paused: true takes a single invoice out of the automatic reminder run and stamps dunning_paused_at with the current time; sending false clears it again. Re-sending true on an already paused invoice keeps the original timestamp. The pause suppresses automatic reminders only — the invoice stays overdue, keeps its dunning level, and can still be dunned manually. It is cleared automatically when the invoice is set back to draft, and is never copied to a cloned or recurring follow-up invoice.

The pause is an update-only field: sending is_dunning_paused when creating an invoice is rejected (new invoices are never paused). dunning_paused_at is read-only: it is rejected on create and silently ignored on update (so a client may echo the whole invoice back) — write the boolean instead, so the original “paused since” date is preserved.

The read-only auto_dunning_active field tells you whether this invoice will actually be dunned automatically: it is true only when the invoice is not paused and automatic reminders are effectively on — the customer’s company setting decides when it is set (it can switch reminders on even if the organization default is off), otherwise the organization default applies. Resolving it can cost an extra query per invoice, so it is only returned when you ask for it: ?append=auto_dunning_active.

Retrieve an invoice ​

get
/invoice/{id}

Example response ​

json
// HTTP 200 OK
{
    "id": "D4rNdYjlGy",
    "number": "RE-01234",
    "name": "Jahresretainer 2023",
    "description": null,
    "reminded": 0,
    "current_dunning_level": null,
    "next_dunning_level": null,
    "dunning_text": null,
    "is_dunning_paused": false,
    "dunning_paused_at": null,
    "auto_dunning_active": true,
    "total": 7680.0,
    "total_with_vat": 8271.35,
    "external_total": 0.0,
    "total_paid": 0.0,
    "total_open": 8271.35,
    "include_vat": true,
    "vat_detailed": [
        {
            "id": "eqNdV92mQ3",
            "rate": 7.7,
            "total": 8271.35,
            "amount": 591.35
        }
    ],
    "status": "pending",
    "is_paid": false,
    "is_sent": false,
    "is_scheduled_for_sending": false,
    "is_rfd": false,
    "is_locked": true,
    "is_exported": false,
    "is_overdue": false,
    "is_overpaid": false,
    "is_cancelled": false,
    "issued_at": "2022-09-19",
    "due_at": "2022-10-19",
    "sent_at": null,
    "locked_at": "2022-09-19T13:51:35.000000Z",
    "paid_at": null,
    "cancelled_at": null,
    "days_overdue": 0,
    "payable_in_days": 30,
    "address": "<p><strong>StrawBlond</strong><br> Alice Cooper<br>Rütistrasse 2<br>CH-8645 Rapperswil</p>",
    "header": "<p>Sehr geehrte Damen und Herren</p><p>Vielen Dank für Ihren Auftrag. Wir stellen Ihnen folgende Leistungen/Lieferungen in Rechnung:</p>",
    "footer": "<p>Vielen Dank für eine fristgerechte Zahlung.</p><p>Freundliche Grüsse<br>StrawBlond GmbH</p>",
    "address_personalized": "<p><strong>StrawBlond</strong><br> Alice Cooper<br>Rütistrasse 2<br>CH-8645 Rapperswil</p>",
    "header_personalized": "<p>Sehr geehrte Damen und Herren</p><p>Vielen Dank für Ihren Auftrag. Wir stellen Ihnen folgende Leistungen/Lieferungen in Rechnung:</p>",
    "footer_personalized": "<p>Vielen Dank für eine fristgerechte Zahlung.</p><p>Freundliche Grüsse<br>StrawBlond GmbH</p>",
    "has_page_break_after_header": false,
    "has_page_break_before_footer": false,
    "show_qrbill": true,
    "pdf_url": "https://api.blond.swiss/api/invoice/1502/pdf?expires=1666195512&signature=af336a31dc989b7755b4a1391e7134226d5697e926711080130aaa12b2689470",
    "pdf_dunning_url": "https://api.blond.swiss/api/invoice/1502/pdf?expires=1666195512&options%5BwithDunningText%5D=1&signature=f476ce81ccc72230e5efdb9e7cc09af83f4b7fdf266dfd176fbd72e066400d14",
    "preview_url": "https://api.blond.swiss/api/invoice/1502/view?signature=89c4deac39578b4a961a15eddb7a2c648edeb60ccd30a091c13cc8cd48435d30",
    "mail_preview_url": "https://api.blond.swiss/api/document/mail-preview?type=invoice&id=D4rNdYjlGy",
    "project": {
        // Project object when included
    },
    "contact": {
        // Contact object when included
    },
    "member": {
        // Member object when included
    },
    "created_by": {
        // Member object when included
    },
    "updated_by": {
        // Member object when included
    },
    "company": {
        // Company object when included
    },
    "elements": [
        // Only present when included `elements` relation
        {
            // a document element object
        }
    ],
    "activities": [
        // Only present when included `activities` relation
    ],
    "expenses": [
        // Only present when included `expenses` relation
    ],
    "locked_times": [
        // Only present when included `lockedTimes` relation
    ],
    "locked_times_count": 0,
    "attachments_download_url": null,
    "source_offer": {
        // Offer object when included
    },
    "revenue_account_no": "3000",
    "is_recurring": false,
    "recurring_invoice": {
        // Invoice object when included
    },
    "recurring_type": null,
    "recurring_every": 1,
    "recurring_ends_at": null,
    "next_recurring_issue_date": null,
    "next_recurring_due_date": null,
    "bank_account_id": "AbCdEfGhIj",
    "bank_account": {
        // BankAccount object when included
    },
    "comments": [
        // Only present when included `comments` relation
    ],
    "comments_count": 3, // Only present when included `commentsCount`
    "payments": [
        // Only present when included `payments` relation
    ],
    "payment_status": "unpaid",
    "attachments": [
        // Only present when included `media` relation
    ],
    "latest_outgoing_mail": {
        // Only present when included `latestOutgoingMail` relation, see Delivery status
    },
    "custom_fields": {},
    "created_at": "2022-09-19T13:50:07.000000Z",
    "updated_at": "2022-09-19T13:51:35.000000Z",
    "deleted_at": null
}

Delivery status ​

Include latestOutgoingMail to see whether the last email sent for the invoice (the invoice itself or a payment reminder) reached its recipients. It is null when the invoice was never emailed, and only returned when the API user may see the outgoing mail log.

AttributeTypeDescription
idStringID of the outgoing email
subjectStringSubject of the email
recipientsArrayAll recipients (to, cc and bcc)
delivery_statusString?sent, deferred, delivered or failed; null when the email went out over the organization's own SMTP server
recipient_statusesObject?Per recipient (lowercase address): status, at and, for a failed delivery, the receiving server's reason
created_atStringWhen the email was sent

failed means at least one recipient's server rejected the email or it could not be delivered; delivered means every recipient's server accepted it.

json
"latest_outgoing_mail": {
    "id": "bG8mEqYmMZ",
    "subject": "Rechnung: Website Relaunch",
    "recipients": ["anna@example.com", "accounting@example.com"],
    "delivery_status": "failed",
    "recipient_statuses": {
        "anna@example.com": { "status": "delivered", "at": "2026-10-23T09:24:15+00:00" },
        "accounting@example.com": {
            "status": "failed",
            "reason": "550 5.1.1 Recipient address rejected: User unknown",
            "at": "2026-10-23T09:24:16+00:00"
        }
    },
    "created_at": "2026-10-23T09:24:10.000000Z"
}

Delete an invoice ​

delete
/invoice/{id}

Moves a draft invoice to the trash. Deleting an invoice that is already in the trash (filter[trashed]=only) removes it permanently.

Deleting a draft releases the time entries and expenses it billed, so they can be billed again.

A locked invoice (is_locked: true) cannot be deleted and returns 422 Unprocessable Entity. To void a sent invoice, cancel it instead.

Example response ​

json
// HTTP 204 No Content

Delete many invoices ​

post
/invoice/delete-many

Deletes multiple draft invoices at once. The request body is a JSON array of invoice ids. Returns 200 OK with deleted and skipped arrays — see Bulk delete.

When the array contains a locked invoice, the request returns 422 Unprocessable Entity and deletes none of the invoices.

List invoices ​

get
/invoice

The list endpoint accepts the same parameters as in Retrieve an invoice and returns a paginated array of the same invoice object in the data property.

Read more about Pagination, Filtering, Sorting and Includes on the Introduction page.

Invoice line items ​

You may use the Document Element endpoint to create, update or delete line items on an invoice.

Line items of a locked invoice (is_locked: true) are frozen — see Locked documents.

Add products to an invoice ​

post
/invoice/{id}/add-products
Attribute (* required)TypeDescription
products *ArrayArray of Product IDs to add to the invoice
beforeOrderNumber?Order position to insert products before (if not provided, adds to the end)

Fails with 422 Unprocessable Entity when the invoice is locked.

Example request ​

json
{
    "products": ["6k2KpJY3By", "8m3LqKZ4Cx"],
    "beforeOrder": 2
}

Example response ​

json
// HTTP 200 OK
{
    // an invoice object
}

Update invoice status ​

post
/invoice/{id}/status

Updates the status of an invoice, handling appropriate transitions and side effects like payments, notifications, and activity logging.

Attribute (* required)TypeDescription
status *StringInvoice status: draft, pending, or paid
paid_atDate?Payment date (required when status is paid)
notify_customerBooleanSend notification to customer when marking as paid (default: false)

Status transitions ​

  • draft: Removes all payments, unlocks invoice, clears sent/paid dates and cancels scheduled sending (is_scheduled_for_sending becomes false)
  • pending: Locks invoice, marks as sent, removes latest payment if exists
  • paid: Creates payment record for remaining balance, sets paid date

Example request ​

json
{
    "status": "paid",
    "paid_at": "2023-10-15",
    "notify_customer": true
}

Example response ​

json
// HTTP 200 OK
{
    // an invoice object
}

Send an invoice ​

post
/invoice/{id}/send
Attribute (* required)TypeDescription
recipientsString | ArrayList of emails, as an array or a string separated by ";" (max. 5, Default: Contact email)
increaseDunningLevelBooleanAuto increase dunning level on overdue invoice
messageString?Custom message to include with the invoice (max. 5000 characters, links are removed)
ccToOwnerBooleanSend a carbon copy to self
adjustDatesBooleanAdjust dates to today on draft invoice
attachmentsArrayArray of media UUIDs to attach to the invoice

Sending limits

A document can be sent to at most 5 recipients per request. Organizations without a paid subscription are limited to 10 recipient deliveries per day across all invoices and offers; exceeding either limit returns 422 Unprocessable Entity with a descriptive message.

No recipient

When no recipients are given and the invoice's contact has no email address, there is nobody to send to: the request fails with 422 Unprocessable Entity and a descriptive message, and the invoice is left unchanged (not locked, not marked as sent).

Test mode without a subscription

Without an active paid subscription, documents are not delivered to the given recipients: the email is redirected to the sending user's own (verified) email address instead and carries a notice naming the original recipients. The response is still 200 OK and the document is marked as sent.

Example response ​

json
// HTTP 200 OK
{
    // an invoice object
}

Invoice payments ​

You can manage incoming customer payments for invoices using the Invoice Payment endpoints. These payments automatically handle overpayments, update invoice payment status, and integrate with customer account management for comprehensive payment tracking.

Invoice status ​

status sums up where an invoice stands:

ValueMeaning
draftNot locked yet (is_locked: false)
scheduledLocked and scheduled for sending (is_scheduled_for_sending: true)
pendingLocked and open, not yet due
overdueLocked, open and past due_at
paidFully settled
cancelledFully cancelled without any customer payment, see Cancelled invoices

Cancelled invoices ​

A sent invoice that should not have been issued is cancelled with an invoice payment of type cancellation. A cancelled invoice keeps its number and returns:

AttributeTypeDescription
statusStringcancelled
is_cancelledBooleantrue when the invoice has a cancellation payment, no customer_payment, customer_debit or customer_credit, and is fully settled
cancelled_atDate?The executed_at of the cancellation, null when is_cancelled is false
is_paidBooleanfalse, even though nothing is left open

Filter cancelled invoices with filter[status]=cancelled. When an invoice becomes fully cancelled, the invoice/cancelled webhook event is sent. Cancelling the remainder of a partly paid invoice settles it instead: it gets status paid and sends invoice/paid.