Loomy Invoices API
v1π Base URL
https://loomy-invoices.loomyloo.app
π€ Invoices (Rechnungen)
GET
/api/list-invoices/
List ALL invoices (not paginated β the frontend paginates).
GET
/api/list-invoices/first-page?pageSize=10
First N invoices (default 10).
GET
/api/list-invoices/list-by-name?name=R2026-001
Exact match on rechnungsnummer.
GET
/api/list-invoices/list-by-email?email=a@b.de
This table has no email column, so this always returns 0 records.
GET
/api/search-invoices?field=rechnungsnummer&value=R2026
Free-text search inside ONE field, case-insensitive. An unknown field returns 400 with the searchable list. Field name ignores case and punctuation.
GET
/api/invoices/next-number
Next free number for the current year (R2026-000X). Call this first before creating.
POST
/api/create-invoices
Create an invoice. Needs rechnungsnummer, jahr, laufende_nummer, kunde. Unknown field names are silently DROPPED.
PUT
/api/update-invoices
Update invoices. Body: { records: [{id, fields}] }. Fields go to Airtable RAW here β one unknown field name fails the WHOLE update.
DELETE
/api/delete-invoices
Delete invoices. Body: { recordIds: ['recId1', 'recId2'] }
POST
/api/invoices/:id/generate-pdf
Render the invoice to PDF and attach it to the record (via FileHub).
POST
/api/invoices/:id/send
Prepares invoice for WhatsApp sending. Returns PDF URL and customer info.
POST
/api/invoices/:id/send-email
Send the invoice by email with the PDF attached.
POST
/api/upload-invoices-logo
Upload the invoice logo (multipart field: file) to FileHub, then store it in the logo attachment as [{url}].
POST
/api/upload-invoices-pdf
Upload a PDF (multipart field: file) to FileHub.
GET
/api/invoices/health
Health check.
π€ Customers (Kunden)
GET
/api/list-customers/
List all customers.
GET
/api/list-customers/first-page?pageSize=10
First N customers (default 10).
GET
/api/list-customers/list-by-name?name=ACME
Exact match on the company name.
GET
/api/list-customers/list-by-email?email=a@b.de
Exact match on email.
POST
/api/create-customers
Create a customer.
PUT
/api/update-customers
Update customer(s). Raw fields β an unknown name fails the update.
DELETE
/api/delete-customers
Delete customer(s).
GET
/api/customers/health
Health check.
π¦ Items (Artikel)
GET
/api/list-items/
List all items.
GET
/api/list-items/first-page?pageSize=10
First N items (default 10).
GET
/api/list-items/list-by-name?name=Beratung
Exact match on bezeichnung.
GET
/api/list-items/list-by-email?email=a@b.de
No email column on this table β always returns 0 records.
GET
/api/search-items?field=bezeichnung&value=Software
Free-text search inside ONE field, case-insensitive.
POST
/api/create-items
Create an item. ust_satz must be the string "7%"/"19%" and kategorie an existing choice β a number or free text is rejected.
PUT
/api/update-items
Update item(s). Raw fields β an unknown name fails the update.
DELETE
/api/delete-items
Delete item(s).
GET
/api/items/health
Health check.
π Invoice Items (Positionen)
GET
/api/list-invoiceitems/
List all invoice line items.
GET
/api/list-invoiceitems/first-page?pageSize=10
First N line items (default 10).
GET
/api/list-invoiceitems/list-by-name?name=...
Exact match on beschreibung.
GET
/api/list-invoiceitems/list-by-email?email=a@b.de
No email field on this table β always returns 0 records.
POST
/api/create-invoiceitems
Create line item(s). rechnung is a TEXT field, not a link β send the invoice id as a string, never an array. ust_satz must be "0%"/"7%"/"19%" and einheit one of StΓΌck/Std./Tag/Pauschale.
PUT
/api/update-invoiceitems
Update line item(s). Raw fields β an unknown name fails the update.
DELETE
/api/delete-invoiceitems
Delete line item(s).
GET
/api/invoice items/health
Health check. NOTE: this path genuinely contains a space, from the table name β encode it as %20.
π° Payments
GET
/api/list-payments/
List all payments.
GET
/api/list-payments/first-page?pageSize=10
First N payments (default 10).
GET
/api/list-payments/list-by-name?name=...
Exact match on the table's name field.
GET
/api/list-payments/list-by-email?email=a@b.de
No email field on this table β always returns 0 records.
POST
/api/create-payments
Record a payment for an invoice.
PUT
/api/update-payments
Update payment(s). Raw fields.
DELETE
/api/delete-payments
Delete payment(s).
GET
/api/payments/health
Health check.
π’ Company Profile
GET
/api/list-companyprofile/
Get company profile(s).
GET
/api/list-companyprofile/first-page?pageSize=10
First N profiles (default 10).
GET
/api/list-companyprofile/list-by-name?name=...
Exact match on firmenname.
GET
/api/list-companyprofile/list-by-email?email=a@b.de
Exact match on email.
POST
/api/create-companyprofile
Create a profile.
PUT
/api/update-companyprofile
Update profile(s). The logo goes in the logo attachment field as [{url}] β FileHub first.
DELETE
/api/delete-companyprofile
Delete profile(s).
POST
/api/upload-companyprofile-logo
Upload a company logo (multipart field: file) to FileHub. Returns { url, attachment }.
POST
/api/upload-company profile-logo
Same handler as above, legacy path with a space. Prefer the no-space alias.
GET
/api/company profile/health
Health check. The path contains a space, from the table name.
π Invoice Texts
Not currently reachable. proxies/invoiceTexts.proxy.js exists but is never registered in
server.js, so every route below returns 404 in production. Register the proxy to make them live.
GET
/api/list-invoicetexts/
List text templates.
POST
/api/create-invoicetexts
Create a template.
PUT
/api/update-invoicetexts
Update template(s).
DELETE
/api/delete-invoicetexts
Delete template(s).
π’ Numbering / Locks
GET
/api/list-numberinglocks/
List numbering locks per year.
GET
/api/list-numberinglocks/first-page?pageSize=10
First N locks (default 10).
GET
/api/list-numberinglocks/list-by-name?name=...
Exact match on the table's name field.
GET
/api/list-numberinglocks/list-by-email?email=a@b.de
No email field β always returns 0 records.
POST
/api/create-numberinglocks
Create a lock record.
PUT
/api/update-numberinglocks
Update lock (e.g. advance letzte_nummer).
DELETE
/api/delete-numberinglocks
Delete lock(s).
GET
/api/numbering / locks/health
Health check. The path contains spaces, from the table name.
π·οΈ Category
GET
/api/list-category/
List all categories. This list feeds the Kategorie dropdowns in the app.
GET
/api/list-category/first-page?pageSize=10
First N categories (default 10).
GET
/api/list-category/list-by-name?name=Software
Exact match on Name.
GET
/api/list-category/list-by-email?email=a@b.de
No email field β always returns 0 records.
GET
/api/search-category?field=name&value=Sof
Free-text search inside Name, case-insensitive.
POST
/api/create-category
Create a category. Body: { "Name": "..." }. Creates one from the app's "β Neue Kategorie..." option.
PUT
/api/update-category
Update categor(y/ies).
DELETE
/api/delete-category
Delete categor(y/ies).
GET
/api/category/health
Health check.
π§ͺ Agent Quick Recipes
1. Create a complete invoice
GET /api/invoices/next-number POST /api/create-invoices (use the number) POST /api/create-invoiceitems (link to new invoice ID) POST /api/invoices/:id/send (get PDF URL) send_message(MEDIA:pdf_url) (send to WhatsApp)
2. Check what numbers exist this year
GET /api/list-invoices/ # Filter: jahr == 2026, read laufende_nummer
3. Send existing invoice
POST /api/invoices/recInvoiceId/send # Response contains pdf_url β forward it