Lexware Office
Connect your workspace to Lexware Office with an API key: orboto checks it against your Lexware profile, keeps it in the credential vault, receives signed events about invoices, payments and contacts, and turns billable time into a draft invoice.
Added in v0.221.2 The Lexware Office connection links your orboto workspace to your Lexware Office account. orboto does not write invoices itself; it hands structured time data to the invoicing tool you already use. Lexware Office is that tool here. Each workspace has one Lexware connection.
The connection does four things:
- it stores your Lexware API key in the credential vault, encrypted, and never shows it again;
- it checks the key against your Lexware profile and shows which Lexware organisation it belongs to;
- it subscribes to Lexware events for invoice status, payments, contacts and a revoked key, so orboto learns about changes in Lexware without asking every few minutes;
- it bills time: a customer's time for a period or a milestone becomes one draft invoice in Lexware (see Billing runs).
What it does and what it does not do
Added in v0.221.2 Lexware Office stays your system for invoices and bookkeeping. orboto adds the time data and keeps track of what happens to it.
| orboto does | orboto does not |
|---|---|
| Turn a customer's billable time of a period or a milestone into one draft invoice in Lexware | Finalize an invoice. The draft stays a draft until you finish it in Lexware, which also assigns the invoice number and sends it |
| Map customers to Lexware contacts, and create a contact in Lexware when none exists | Handle payments. orboto never records, books or requests a payment; it only reads the payment state Lexware reports back |
| Show the state of each invoice (draft, open, partly paid, paid, voided, deleted) and of the time entries on it | Export to DATEV. Lexware does the bookkeeping side; the DATEV export of a project in orboto is a separate function and unaffected |
| Lock billed time against edits and unlock it when the invoice is voided or deleted | Write quotations, order confirmations, credit notes, vouchers or articles in Lexware |
| Keep the API key encrypted in the credential vault and log every call to Lexware | Send time entry notes to Lexware, or read invoices that did not come from a billing run |
Invoices are issued in EUR. The tax treatment is the 19 %, 7 % or 0 % (tax-free) setting of the connection; other Lexware tax types are not offered.
Set up in five steps
- Create a Lexware API key (Lexware Office XL, see Before you start).
- Connect the key in orboto and check that the readiness panel is green.
- Map each customer to its Lexware contact.
- Give every project or customer an hourly rate and set the tax rate of the connection.
- Run a billing run: preview, create the draft, finish it in Lexware.
Where Lexware appears in orboto
Added in v0.230.5 Lexware appears in orboto only once the connection is set up and enabled. Until then the customer page has no Lexware contact or Lexware billing runs card, no New billing run button and no hint to connect, and the ticket's Time tab and the timesheet have no invoice badges and no invoice column. This is the same for every role.
Administrators set the connection up under Admin → Integrations → Lexware Office. In your own browser the cards and badges appear at once. Everyone else sees them on their next page change, at the latest a minute after you connected; a page that stays open keeps what it showed until then. They disappear again while the connection is disabled or after Lexware revoked the key; the billing runs and the locked time entries are kept and show again once the connection works.
Before you start
- You need the system administration permission in orboto.
- Lexware's Public API is available from the Lexware Office XL plan; Lexware states this on its Public API page ("Die Public API steht aktuell ab der Lexware Office Version XL zur Verfügung"). The API key is created by a user of your Lexware account at Add-ons → Public API (Lexware: Get an API Key) and belongs to that user. For a first try, use a Lexware test account; orboto marks the connection as such.
- Lexware charges nothing extra for the Public API (Lexware FAQ). When Lexware's key dialog lets you choose what the key may access, allow contacts, invoices, payments and event subscriptions: these are the resources orboto uses, listed under Data flow. A call Lexware refuses for missing access shows as a rejected key on the connection page.
- Lexware calls your instance for every event, so the instance must be reachable from the internet over HTTPS. Self-hosted: set
API_PUBLIC_URLto the public address of your API; the connection page warns you when Lexware cannot reach the address orboto would give it.
Connect
- In Lexware Office open Add-ons → Public API and create an API key. Copy it.
- In orboto open Admin → Integrations → Lexware Office, paste the key, tick This is a Lexware test account if it is one, and choose Connect.
- orboto asks Lexware for your profile with the key. If Lexware refuses the key, nothing is stored and you see why. If it accepts it, the page shows your company name, organisation id and tax type.
- orboto registers the event subscriptions in Lexware. The panel lists them with their state; all six should read Registered.
From a terminal, the key goes in on standard input only, never as an argument:
orboto lexware connect --key-stdin --test-account < lexware-key.txt
orboto lexware statusWhat the webhook does
Lexware sends an event to https://<your instance>/inbound/lexware/<connection id> whenever one of these happens:
| Event | Meaning |
|---|---|
invoice.status.changed | An invoice changed its status in Lexware (for example from draft to open, or to paid); orboto updates the billing run. |
invoice.deleted | An invoice was deleted in Lexware; its billing run is marked deleted and the time is free to bill again. |
payment.changed | A payment on an invoice, credit note or voucher changed; for an invoice of a billing run orboto reads the payment and marks the run paid or partly paid. Payments on anything else are logged as ignored. |
contact.changed | A contact changed in Lexware; orboto re-reads a contact mapped to a customer. |
contact.deleted | A contact was deleted in Lexware; a customer mapped to it is flagged. |
token.revoked | The API key was revoked in Lexware. |
Every event is checked before orboto keeps it:
- Signature. Lexware signs each event (
X-Lxo-Signature, RSA-SHA512). orboto verifies it with Lexware's published public key. An unsigned or wrongly signed event is refused. - Organisation. An event for a different Lexware organisation than the connected one is refused.
- Replay. The same event body delivered twice is refused the second time.
orboto answers Lexware at once and processes the event in the background. Refused events show up in the connection's call log with the reason, never with their content.
A revoked key disables the connection: the readiness panel turns red on Key validity and names the fix. Create a new key in Lexware and choose Replace API key; orboto checks that it belongs to the same organisation, enables the connection again and registers the subscriptions anew (Lexware deletes all subscriptions of a revoked key).
Contacts
Added in v0.221.2 Each orboto customer can be mapped to one Lexware contact, and each Lexware contact to one customer. The mapping is what each invoice is addressed to.
Open the customer (Customers → customer → Overview). The Lexware contact card below the customer details offers three ways in:
- Proposed match. orboto searches your Lexware contacts with the customer role by the customer's name. A contact whose name is the same, ignoring upper and lower case, is proposed; Link this contact maps it.
- Pick from the list. Search by another name (at least three characters, a Lexware rule) and choose Link next to the right contact. A contact already mapped to another customer is shown but cannot be picked.
- Create in Lexware. orboto creates a company contact with the customer role, the customer's name and, if it can read it, the billing address. Write the billing address with one part per line, postcode and city on one line, and the country on the last line when it is not Germany. If orboto cannot read the address, Lexware gets the name only and the card tells you; add the address in Lexware.
Once mapped, the card shows the Lexware customer number, the name in Lexware, how the mapping was made and when orboto last synced it. From there:
| Action | Card | Command line |
|---|---|---|
| Send the customer name and billing address to Lexware | Send name and address to Lexware | orboto lexware contact "<customer>" --push |
| Read the contact again | Refresh from Lexware | orboto lexware contact "<customer>" --refresh |
| Map a different contact | Choose another contact | orboto lexware contact "<customer>" --link <contact id> |
| Remove the mapping (the contact stays in Lexware) | Unlink | orboto lexware contact "<customer>" --unlink |
orboto lexware contact "<customer>" on its own shows the mapping, or the proposal and the list; the customer is its name or id.
Changes on both sides. When someone edits the contact in Lexware, orboto picks up the new name and customer number from the event. If you send name and address after such an edit and before orboto has seen it, Lexware refuses the write because orboto's copy is out of date. orboto then takes Lexware's current version and asks you to try again; the second attempt goes through. A contact deleted in Lexware marks the mapping as broken: the card shows it in red with the list again, and the readiness panel shows Customer contacts until you link another contact or create one.
Viewing the card needs the customer read permission, changing the mapping the customer edit permission. The card and the commands need an enabled Lexware connection. Linking, creating, sending and unlinking are written to the audit log of the customer. Agents use GET, PUT and DELETE on /customers/<id>/lexware-contact; the in-app chat does not change Lexware contacts, because every write lands in your bookkeeping.
Billing runs
Added in v0.221.2 A billing run turns a customer's billable time into one draft invoice in Lexware. orboto prepares the lines; you check, finish and send the invoice in Lexware, which also gives it its number. orboto never finalizes an invoice.
Before the first run:
- the customer is mapped to a Lexware contact (see Contacts); the invoice goes to that contact;
- every project of the customer has an hourly rate, or the customer has a default hourly rate. The project rate wins; a project with neither is named in the preview and blocks the run until you set one;
- the tax rate is set on the connection: 19 % (default), 7 %, or 0 % for a tax-free invoice. Change it on Admin → Integrations → Lexware Office or with
orboto lexware set --tax-rate 0.
Open the customer (Customers → customer → Overview) and choose New billing run on the Lexware billing runs card.
- Choose what to bill. Either a period (from and to, both days included) or a milestone of one of the customer's projects. orboto takes every time entry on the customer's projects in that selection that is not on an invoice yet.
- Choose the lines. One line per ticket adds up the hours of each ticket and lists the days worked. One line per person and day gives each person's day its own line and lists the tickets.
- Preview. You see each line with hours (up to four decimals), unit "Stunde", rate and net amount, then net, tax and gross, the service period and the number of entries. Nothing is written yet.
- Create draft invoice. orboto creates the draft in Lexware with the service period from the first to the last day worked and shows the link Open in Lexware.
An example: 1.5 and 0.75 hours on one ticket and 20 minutes on another, at 95 EUR per hour, give the lines 2.25 h = 213.75 EUR and 0.3333 h = 31.66 EUR; net 245.41 EUR, 19 % tax 46.63 EUR, gross 292.04 EUR. Lexware calculates the final totals from the same lines.
Billed time is locked. Every entry on the invoice carries the invoice reference: the entry can no longer be edited or deleted, and no further run picks it up again. Running the same selection again while the invoice is still a draft gives you the existing run instead of a second invoice.
The status comes back. The card lists every run with its status: Draft, Open, Partly paid, Paid, Voided or Deleted, and next to the gross amount what has been paid (with the date of the last payment) and what is still open. orboto updates it from the invoice and payment events; Refresh status asks Lexware right away. When you record a payment in Lexware, or Lexware assigns a bank transaction to the invoice, the run turns Partly paid or Paid. A cash discount (Skonto) counts as paid. When you void or delete the invoice in Lexware, its time entries are unlocked and can go on a new run.
Each time entry shows its invoice. On the ticket's Time tab and on the timesheet, a billed entry carries a badge that links to the invoice in Lexware: Invoiced (draft or open invoice), Partly paid or Paid. An entry whose invoice was voided or deleted shows Invoice voided or Invoice deleted until a new run bills it again.
Invoiced and paid for a period. Below the runs, the card sums up what the customer was invoiced (net and gross), what has been paid and what is still open. Pick a period to count only the runs whose service period overlaps it; without one it counts every run. Voided and deleted invoices are left out of the totals and shown as a count.
From a terminal:
orboto lexware billing-run preview --customer "Acme GmbH" --from 2026-10-01 --to 2026-10-31
orboto lexware billing-run create --customer "Acme GmbH" --milestone ORB-M3 --group day
orboto lexware billing-run list --customer "Acme GmbH"
orboto lexware billing-run summary --customer "Acme GmbH" --from 2026-10-01 --to 2026-12-31list prints one line per run with status, gross, paid, open, the date of the last payment and the link into Lexware; --json prints the raw answer. summary prints the invoiced, paid and open totals.
Previewing and creating need the customer edit permission, the list and the totals the customer read permission; the admin page lists the runs of all customers. Each new run, each status change and each payment change is written to the customer's audit log. The DATEV export of a project is unaffected and still contains all time. Agents use POST /customers/<id>/lexware-billing-runs/preview, POST /customers/<id>/lexware-billing-runs, GET /customers/<id>/lexware-billing-runs and GET /customers/<id>/lexware-billing-runs/summary; a time entry from GET /tickets/<id>/time-entries carries invoiceState and invoiceUrl. The in-app chat does not create invoices, because every run writes into your bookkeeping.
Data flow
Added in v0.221.2 orboto talks to Lexware over HTTPS at api.lexware.io with your API key, and Lexware talks to orboto through the signed event address. Nothing else leaves your instance.
From orboto to Lexware
| When | What is sent |
|---|---|
| Connect, Test connection | A read of your Lexware profile (organisation, company name, tax type) |
| Register and remove subscriptions | The six event types and the address of your instance's receiver |
| Contacts | A search of your customer contacts by name; on Create or Send name and address: the customer name and billing address; reads of single contacts |
| Billing run | One draft invoice: the contact, the lines (ticket key and title, or person and day; hours; unit "Stunde"; net rate), the tax setting and the service period. Time entry notes and ticket descriptions are not sent |
| Status | Reads of the invoice and its payments |
From Lexware to orboto
| What | Used for |
|---|---|
| The six events of What the webhook does | Updating billing runs, payment state and contact mappings, and flagging a revoked key |
| Invoice status, amounts paid and open, date of the last payment | The billing run list, the badges on time entries and the totals |
| Contact name and Lexware customer number | The contact card |
Calls to Lexware are limited to two per second per connection. The key never appears in a request log, an audit entry or an API answer. Disconnecting removes the subscriptions in Lexware and deletes the connection with its event and call logs; the invoices and contacts in Lexware stay.
Permissions
Added in v0.221.2 Access to the integration follows the permissions of your orboto roles. Each function checks its own permission, and a missing one answers 403.
| Function | Permission |
|---|---|
| See the connection, its readiness, events, call log and the list of all billing runs | System administration, read |
| Connect, enable or disable, replace the key, change the tax rate, register subscriptions, disconnect | System administration, write |
| See a customer's Lexware contact, its billing runs and the invoiced and paid totals | Customers, read |
| Link, create, send, unlink a contact; preview, create and refresh a billing run | Customers, write |
The API key itself is visible to nobody after it is saved, not even to administrators. Every change to the connection, a contact mapping or a billing run is written to the audit log. The in-app chat offers none of these functions.
Readiness and logs
The Readiness panel shows whether everything is in place: connection enabled, key in the vault, key valid, last profile check passed, subscriptions registered, whether events arrive, and whether a customer's Lexware contact went missing. Each item that needs attention names the fix in the admin page and on the command line.
- Events from Lexware: the latest events with their type, the Lexware resource and what orboto did with them.
- Call log: every call orboto made to Lexware and every event Lexware sent, kept for 30 days, with route, status, duration and a correlation id. It never contains a request body or your key.
orboto keeps to Lexware's limit of two requests per second per connection and retries a call Lexware rejects as too frequent.
Manage the connection
| Action | Admin page | Command line |
|---|---|---|
| Check the key now | Test connection | orboto lexware test |
| Pause or resume | Disable / Enable (removes or registers the subscriptions) | orboto lexware set --enabled=false |
| Test or production account | Mark as test account / Mark as production account | orboto lexware set --test-account=true |
| Tax rate of billing runs | Tax rate of billing runs | orboto lexware set --tax-rate 19 |
| Replace the key | Replace API key | orboto lexware rotate-key --key-stdin < new-key.txt |
| Subscriptions | Register subscriptions / Remove subscriptions | orboto lexware subscribe, orboto lexware unsubscribe |
| Disconnect | Disconnect, then type the confirmation word | orboto lexware disconnect --yes |
Disconnecting removes the subscriptions in Lexware, retires the key in the vault and deletes the connection with its event and call logs. Every change to the connection is written to the audit log.
Agents reach the same functions through the REST API under /admin/integrations/lexware with an account that holds the system administration permission. The in-app chat does not offer them, because connecting needs a secret that must never be typed into a stored conversation.
Support
Added in v0.221.2 Start with the Readiness panel and the call log; they name the fix for most problems. For everything else contact orboto support and include the correlation id from the call log. Never send the API key. Questions about Lexware Office itself, its plans and its Public API go to Lexware: Public API and the API documentation.
Chat bot for Slack, Microsoft Teams and Discord
Connect your instance to Slack, Microsoft Teams or Discord: agent notices land in your channels, and your team starts, claims, closes and asks from the chat.
External AI spend webhook
Report AI spend from your own systems with a signed POST - headers, signature, retries, and how to move an existing sender to the signed format.