bexio API from Make and Zapier: what the ready-made modules cannot do

Make and Zapier offer bexio as a ready-made app: fill in a few fields and the invoice lands in your accounting. Yet the community forums of both services hold questions about bexio dating back to 2023 that never got solved, because the module lacks a field or an endpoint. I went through these threads and compared them with the official bexio API documentation. This guide shows, case by case, where the forum got stuck and which field of the bexio API solves it. It describes the modules as the people asking describe them; it is not based on my own experience with Make or Zapier.

Flow: the shop, form or payment provider delivers the data, a dedicated service talks to the bexio API with every field, api.bexio.com creates the invoice, quote or time entryShop, form, paymentproviderOrder, enquiry orpaymentDedicated serviceEvery field of theAPI, errors areretriedapi.bexio.comInvoice with lineitems, quote, timeentry, PDFFlow: the shop, form or payment provider delivers the data, a dedicated service talks to the bexio API with every field, api.bexio.com creates the invoice, quote or time entryShop, form, payment providerOrder, enquiry or paymentDedicated serviceEvery field of the API, errors areretriedapi.bexio.comInvoice with line items, quote, timeentry, PDF

Where the eight cases come from

The cases come from the public forums community.make.com and community.zapier.com, questions asked between 2023 and 2025. Each case is linked below. “Unsolved” means: the thread has no answer confirmed by the person asking, or the answer points to support. Several people report the same pattern, sometimes months apart. The solution through the API is backed by the documentation in every case; the paths appear there exactly as written.

Case 1: several line items on one invoice

The most common problem. In Make, someone wants to write several line items into one bexio invoice; the module rejects the list, and “Update Invoice” offers no line item at all. In Zapier the same thing fails with a Shopify order containing several products, with a WooCommerce order through a detour with a loop and temporary storage, and with a Payrexx payment, where the error says the list of amounts is not the same length as the list of items; what remains is a draft without line items and a total of 0.

In the API this is not a special case. POST /2.0/kb_invoice accepts an array positions, and the documentation states explicitly that position types can be mixed: KbPositionCustom for free lines, KbPositionArticle for items from the catalogue, plus text, subtotal, discount and page-break positions. An invoice with two lines looks like this:

{
  "contact_id": 14,
  "user_id": 1,
  "mwst_type": 0,
  "mwst_is_net": true,
  "positions": [
    { "type": "KbPositionArticle", "article_id": 3, "amount": "2", "unit_price": "45.00", "tax_id": 4 },
    { "type": "KbPositionCustom", "text": "Shipping", "amount": "1", "unit_price": "9.00", "tax_id": 4 }
  ]
}

bexio recommends at most 150 positions when creating a document; further lines are appended afterwards with POST /2.0/kb_invoice/{document_id}/kb_position_article or …/kb_position_custom. Shipping and discount are thus ordinary lines, no workaround needed.

Case 2: document number on quotes

A Zapier user cannot create a quote: bexio demands document_nr, the action has no field for it; a second person affected turns up in the same thread. Another cannot find a quote by its number, although the same number returns a hit in a different tool.

The documentation for POST /2.0/kb_offer explains the rule: document_nr must not be set when automatic numbering is active in bexio, and it is required when automatic numbering is switched off. A module without this field therefore only works with automatic numbering. Anyone keeping their own numbers sets them through the API. Searching goes through POST /2.0/kb_offer/search with document_nr as the search field:

[{ "field": "document_nr", "value": "AN-00001", "criteria": "=" }]

Without criteria, bexio searches with “like”, i.e. partial matches; for a number, = is the safe choice. The same search fields exist for invoices under POST /2.0/kb_invoice/search.

Case 3: tax rate per line item

An invoice arrives in bexio with 7.7% instead of 8.1%, and the tax rate cannot be chosen in the module. Zapier confirms a bug report in the thread; the workaround is to store the rate on the product in bexio.

In the API every position carries its field tax_id. The valid values come from GET /3.0/taxes?types=sales_tax&scope=active; this is exactly the call the documentation recommends, because only active sales taxes are allowed on quotes, orders and invoices. The response lists id, code, value and the years of validity for each rate. A service reads this list once and picks the tax_id by percentage instead of hard-coding a number that becomes wrong at the next rate change.

Case 4: reference for payment matching

Someone creates invoices from a Google Sheet and wants to write the 27-digit reference number into the reference field so that bexio matches incoming bank payments automatically. Zapier files a feature request; no date is given.

The invoice in the API has two reference fields. reference is free text on the document. api_reference, according to the documentation, can only be read and edited through the API and is meant to store references to other systems, such as the shop’s order number or the payment provider’s payment ID; it is also a search field of POST /2.0/kb_invoice/search. The response for an invoice also contains qr_invoice_id. A field for setting the reference of the QR payment part yourself is not described in the documentation.

Anyone who gets the payment reported by a payment provider anyway does not need bank matching for it: POST /2.0/kb_invoice/{invoice_id}/payment books the payment directly onto the invoice with date, value and bank_account_id. The payment then shows on the invoice in bexio, and nobody sends reminders to customers who paid long ago.

Case 5: user in time tracking

Time entries from a Google Sheet should belong to the right employee in bexio. In the Zapier module the user ID cannot be set; the field gets filled with a contact, and the person asking finds no way out.

POST /2.0/timesheet requires user_id as a mandatory field, along with client_service_id for the service, allowable_bill for “billable” and an object tracking, either as a duration (type: duration with date and duration) or as a time range (type: range). Users come from GET /3.0/users, services from GET /2.0/client_service. Contact and project are optional (contact_id, pr_project_id). An entry of one hour and forty minutes:

{
  "user_id": 1,
  "client_service_id": 1,
  "allowable_bill": true,
  "contact_id": 2,
  "tracking": { "type": "duration", "date": "2026-11-04", "duration": "01:40" }
}

Case 6: PDF of a quote

A Make user wants to archive quotes as PDF in DocuWare. There is a module for invoices but none for quotes; the attempt with an HTTP call yields a PDF that will not open. The only reply points to HTTP basics.

GET /2.0/kb_offer/{quote_id}/pdf returns the document, with or without letterhead (logopaper). The point where the person failed: the response is not a PDF but JSON with the fields name, size, mime and content, and content holds the file Base64-encoded. Only after decoding do you have a valid PDF file. The same applies to invoices (/2.0/kb_invoice/{invoice_id}/pdf) and orders (/2.0/kb_order/{order_id}/pdf).

Case 7: detecting changed invoices

According to one forum member, the Make trigger “Watch Invoices” delivers no records when an invoice is merely changed. One person replying suspects a bug in the module, a second suggests searching instead.

The API offers the search field updated_at with comparison criteria for this. A service remembers the timestamp of its last run and asks:

[{ "field": "updated_at", "value": "2026-11-04 06:00:00", "criteria": ">" }]

at POST /2.0/kb_invoice/search?order_by=updated_at_desc. The time format matches what bexio returns in updated_at. New and changed invoices thus show up the same way, for example a status change to “paid”.

Case 8: invoice from an order

A Shopify order becomes a bexio order in Make; the invoice from it is to be created by an HTTP call because there is no module for it. The call fails with status 415, while the same call works in Postman. Make support confirms a known issue in the thread and passes it on to development, without a date.

The endpoint is POST /2.0/kb_order/{order_id}/invoice. The body is optional: if it is missing, bexio takes over all positions of the order; otherwise positions names the desired lines with id, type and amount. Status 415 means the server does not accept the content type of the request; the documentation requires Accept: application/json and JSON as the body. A dedicated service sets the headers itself and does not depend on how an intermediary passes them on.

The eight cases at a glance

CaseIn the forumIn the bexio API
Several line itemslist rejected, draft with total 0positions in POST /2.0/kb_invoice, mixed types
Document numberrequired field missing, search without hitsdocument_nr, search with criteria: "="
Tax ratenot selectable, wrong ratetax_id per position, list from /3.0/taxes
Referencefield missing, feature request openreference, api_reference, payment via …/payment
Time trackinguser cannot be setuser_id in POST /2.0/timesheet
Quote PDFno module, unreadable file/2.0/kb_offer/{id}/pdf, decode content from Base64
Changed invoicestrigger does not reactsearch on updated_at with >
Invoice from orderno module, status 415POST /2.0/kb_order/{id}/invoice

On top of that comes a risk no field can fix: a Zapier user reports that bexio locked the client ID of the Zapier app and his connection stopped with it. Anyone connecting through a third-party app depends on its approval; your own app in the Developer Portal depends only on yours. How to create one is in the guide Create a bexio API token, the sign-in via OAuth 2 in the guide Connect the bexio API to WordPress.

When the direct connection pays off

For a contact from a form, the ready-made modules are usually enough. As soon as invoices with several lines, your own numbers, tax rates, time entries per employee or PDFs come into play, the detour through the intermediary platform costs more time than it saves: every missing field turns into a forum thread with no end.

An interface that talks to the bexio API directly is something I build for a fixed price: you tell me the source system and the workflow, I define the scope on your real documents, the connection runs on your own infrastructure without a subscription with a third party, with retries on errors and a log that shows what was transferred. For HubSpot the connection already exists: bexio ↔ HubSpot turns a won deal into a quote or invoice with line items and reports the payment status back. For everything else: Contact, with the source system and what is done by hand today.

All guides