Mint a new workspace (tenant) with its KMU chart of accounts. A new workspace starts with a 30-day default Zahlungsfrist (defaultPaymentTermsDays, 0 to 365; null for none).
ParametersnamerequiredlegalFormbaseCurrencyidempotencyKeyfiscalYearStartdefaultPaymentTermsDays
One-call agent setup: parse a short description into a workspace and VAT config.
ParametersnamedescriptionrequiredidempotencyKeyrequired
Set legal form, base currency, or fiscal year start (currency/year lock once the ledger is non-empty).
ParameterslegalFormworkspaceIdrequiredbaseCurrencyfiscalYearStart
Set the VAT method (effektiv/saldo) and accounting timing (soll/ist). CONSEQUENCE: Changes how MWST is worked out for your returns: effective or net tax rate method, agreed or received payments. You can set it back, but the earlier setting is not kept.
ParametersvatMethodrequiredworkspaceIdrequiredvatAccountingrequired
Set the QR-bill creditor: IBAN (a QR-IBAN gives a QRR reference, a plain IBAN gives SCOR), optional name (defaults to the company name) and optional structured address. The IBAN saves without the address; the address is needed before the first QR-bill renders (buildQrBill answers needs_creditor_address until then). A partial address is refused (needs_structured_address). CONSEQUENCE: Changes the account every QR-bill is paid into, including the QR-bills of invoices already open when they are downloaded, sent again or dunned. A customer who already paid is not affected.
ParametersibanqrIbanaddressworkspaceIdrequiredcreditorName
Read the workspace company & fiscal profile.
ParametersworkspaceIdrequired
Update company identity fields (name, legal form, UID, MWST number) and the workspace default Zahlungsfrist (defaultPaymentTermsDays, 0 to 365 days; null clears it). A document whose customer or supplier has no terms of its own falls due that many days after its date. CONSEQUENCE: Changing the MWST number also changes it on the QR-bills of open invoices when they are downloaded or sent again. You can change it back; what customers already received keeps the old number.
ParametersuidnamemwstNolegalFormworkspaceIdrequireddefaultPaymentTermsDays
Create a ledger account.
ParametersnamerequiredtyperequirednumberrequiredworkspaceIdrequiredidempotencyKeyvatCodeDefaultcostCenterAllowed
Rename an account or change its VAT default, its cost-centre flag, or statementIsVoucher ("Beleg = Kontoauszug": the bank statement is the voucher, so a bank line booked to such accounts alone is not counted as missing a Beleg; on by default for 6900 Finanzaufwand). Number and type are frozen.
ParametersnameaccountIdrequiredworkspaceIdrequiredvatCodeDefaultcostCenterAllowedstatementIsVoucher
Archive an account (soft; the account keeps its postings).
ParametersaccountIdrequiredworkspaceIdrequired
Reactivate a soft-archived account (idempotent).
ParametersaccountIdrequiredworkspaceIdrequired
Hard-delete an account that never carried a posting. CONSEQUENCE: Deletes the account from your chart for good; only an account that never carried a booking can go. You can create it again, but not restore it.
ParametersaccountIdrequiredworkspaceIdrequiredidempotencyKey
List accounts, optionally filtered by search text. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParameterssearchsavedViewIdworkspaceIdrequiredincludeArchived
Create a cost centre (Kostenstelle).
ParameterscoderequirednamerequiredworkspaceIdrequiredidempotencyKey
Archive a cost centre (soft).
ParametersworkspaceIdrequiredcostCenterIdrequired
Reactivate a soft-archived cost centre (idempotent).
ParametersworkspaceIdrequiredcostCenterIdrequired
Hard-delete a cost centre that no posted line references. CONSEQUENCE: Deletes the cost centre for good; only one that no booking uses can go. You can create it again, but not restore it.
ParametersworkspaceIdrequiredcostCenterIdrequired
List cost centres. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParameterssavedViewIdworkspaceIdrequiredincludeArchived
Post a balanced double-entry journal entry (business sources only; reversal/close are separate tools). Instead of lines, template { standardId, asks } books a Vorlage (a Buchungsregel of scope manual, list_bank_standards): asks { legIndex: amountMinor } fills its asked legs (gross on a taxed leg), a same leg copies the asked leg it names, the rest leg balances the entry on its own side, and the lines are composed and judged exactly as compose_entry with that template answers them (the entry text defaults to the Vorlage name). Template refusals: rule_not_found, rule_invalid (an account or code the Vorlage names is no longer valid: archived, now a Bankkonto ledger, a code gone; invalidReason says which), wrong_scope (a bank rule), ask_missing, rest_is_zero, rest_changes_side; lines and template together are invalid_input. CONSEQUENCE: Books this in your accounts. If it is wrong, you correct it with a new correcting entry; both stay visible.
ParametersrefdaterequiredlinessourcerequiredentryIdtemplatedescriptionworkspaceIdrequiredidempotencyKeyrequired
Reverse a posted entry by posting its faithful mirror (OR 957a). Refuses `owned_by` on an entry a capability minted with a row of its own (an MWST-Saldierung, an Abgrenzung, a Rückstellung, a payment, a bank-line booking, a vendor bill, an issued invoice or credit note, a depreciation run, an inventory valuation run, and their mirrors): reverse those through the owning verb the refusal names (`vat_settlement_reverse`, `accrual_reverse`, `provision_reverse`, `provision_release_reverse`, `reverse_payment`, `reopen_bank_line`, `void_vendor_bill`, `transition_document` to cancelled, `asset_depreciation_run_reverse`, `inventory_valuation_reverse`) so the row moves with the entry. An entry a bank line holds (booked or matched on it) always refuses `owned_by reopen_bank_line` with that line's `bankTxnId`. CONSEQUENCE: Books a correcting entry that mirrors a posted one; the original stays visible beside it. If the correction was wrong, you correct it the same way.
ParametersdateentryIdrequireddescriptionworkspaceIdrequiredidempotencyKeyrequired
Create or update a draft journal entry (no money effect until posted).
ParametersrefdaterequiredlinesrequiredentryIddescriptionworkspaceIdrequiredidempotencyKeyrequired
Delete a draft journal entry (never a posted one). CONSEQUENCE: Deletes the unposted draft entry for good; nothing was booked. To book it after all, you enter it again.
ParametersentryIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Read a journal entry and its lines. The entry reports its Belegnummer (number, null on a draft). Each line reports the transaction amounts (debit, credit) under its currency, and the amounts the books hold (baseDebit, baseCredit) under baseCurrency, which is the workspace base currency.
ParametersentryIdrequiredworkspaceIdrequired
List journal entries, filtered by date range, account, source, status, or Belegnummer (number: an exact match on the number as shown, or for a plain integer every series' entry with that number). Each entry reports its Belegnummer (number, null on a draft), the currency its total is in (null when the entry has no lines), plus the base-currency total, rate and base currency for a foreign-currency entry, all derived from its posted rows. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParameterstofromnumbersourcestatusaccountsavedViewIdworkspaceIdrequired
Compose a journal entry without booking it. mode "expand" turns lines into the exact post_entry lines: an intent line {account, side, amount, gross, taxCode?, supplyDate?, costCenter?} is expanded with its MWST legs (Vorsteuer, Umsatzsteuer, Bezugsteuer, Einfuhrsteuer, the saldo fold, a refund mirrored), a plain line {account, debit|credit, taxCode?, taxBase?, taxAmount?} passes through, and the answer carries the lines, a caption per taxed line and the verdict post_entry would give (vat_trace_unreconciled, period_locked, unbalanced, ...). mode "decompose" reads a stored entry (entryId) or stored lines back into intent and says whether it roundTrips. A bank line instead: mode "expand" with bankTxnId and target (a book_bank_line target of kind accounts, viaAccountId included, or rule with its asks; a computed leg needs no ask) answers exactly the lines book_bank_line would post for it, the rule expanded on the line (target: the accounts target it expands to, computed amounts filled in), and its refusal as the verdict (rule_not_found, ask_missing, rest_is_zero, legs_do_not_sum, line_not_open, ...). D178: EVERY book_bank_line target previews this way (open_item with documentId or allocations, payment_batch, existing_entry, contact, expense_claims, accounts with fx legs), and a bank line's answer carries booking { targetKind, bookable, blockedBy (the refusal code book_bank_line would give now, else null), verdict, deviationMinor (line minus legs, allocations or claims), remainder, remainderOptions (what remainder may be now), documents [{ documentId, kind, contactId, openMinor, allocatedMinor, writeOffMinor, openAfterMinor }], contact { contactId, name, counterpartyKind, mode, settingMode, overridden, accountNumber }, claims [{ claimId, title, employeeId, status, totalMinor }], fx { currency, foreignMinor, baseMinor, rate, conversionLines }, entries [{ currency, lines }] (every entry the booking would post, with accountNumber and CHF per line), warnings, consequences [{
ParametersdatemoderequiredlinestargetentryIdtemplatebankTxnIdworkspaceIdrequired
Inspect the Belegnummer run of the book without writing anything: the numbering settings in force (ledger.belegnummer_mode, _start, _prefix, _split_voucher), how many posted entries are numbered, unnumbered and adopted, whether a catch-up is owed, every series with its next number, the migrated entries (source import) classified by their ref (plain integers and bexio refs, the highest migrated number, the split vouchers, the duplicates: claims that do not read their old number because different vouchers claim it, with the entry that keeps it, and groups of entries with identical content flagged as a possible double import for a person to check, and the non-numeric refs), and the numbers the next catch-up would assign to the posted entries still without one. Lists are capped at 200 rows, each with its total.
ParametersworkspaceIdrequired
Soft-close a month (reversible guardrail). CONSEQUENCE: Closes the month, so nothing more can be booked into it. You can reopen it unless it has been hard-locked since.
ParametersperiodrequiredworkspaceIdrequiredidempotencyKeyrequired
Reopen a soft-closed month (a hard-sealed month refuses). CONSEQUENCE: Reopens a closed month, so bookings into it are accepted again. You can close it again at any time.
ParametersperiodrequiredworkspaceIdrequiredidempotencyKeyrequired
Hard-close a fiscal year: sweep the P&L into equity and seal the year. Refuses year_already_closed on a sealed year. While an open year_close checklist run exists for the year, a call WITHOUT runId refuses year_close_in_progress (naming yearRunId): the run seals the year from its seal row, which calls close_year WITH its runId. A call with runId runs only for an open year_close run of this workspace for exactly this year whose year_sealed row is unblocked (not_found, run_abandoned, run_not_year_close, run_year_mismatch, prerequisite_open otherwise). CONSEQUENCE: Closes the fiscal year for good: the profit or loss moves into equity and nothing more can be booked into that year. There is no reopening; a mistake found later is corrected in the following year.
ParametersyearrequiredrunIdworkspaceIdrequiredidempotencyKeyrequired
Lock a month or year, soft or hard, with an optional reason. The seal reasons (vat_filed, year_close) are reserved and refused with reserved_lock_reason: a filed MWST period is sealed by vat_mark_filed and a fiscal year by close_year, never by a lock. CONSEQUENCE: Locks the period, so nothing more can be booked into it. A soft lock can be lifted at any time; a hard lock only by someone with the right to unlock.
ParameterskindrequiredperiodrequiredreasonworkspaceIdrequiredidempotencyKeyrequired
Unlock a period (a filing/year seal refuses). CONSEQUENCE: Lifts the period lock, so bookings into it are accepted again; a filed MWST period or a closed year stays sealed. You can lock it again at any time.
ParametersperiodrequiredworkspaceIdrequiredidempotencyKeyrequired
Read the tamper-evident audit trail and its chain-verification status.
ParameterstofromentityKindworkspaceIdrequired
List all period locks for the workspace.
ParametersworkspaceIdrequired
Seed the default Swiss tax-code set (idempotent).
ParametersworkspaceIdrequired
Configure VAT: method, timing, registration, VAT number, and the ESTV Bewilligung (asOf picks the statutory rate era). A filer holding several Saldosteuersätze maps each Tätigkeit to its Ertragskonten with saldoActivities, which is how MWSTV Art. 84 Abs. 3 books the Erträge separately per rate. Changing an approval that already governs posted turnover must say which it is: saldoGrant for a new ESTV Bewilligung from a given day, saldoCorrection to rewrite the open one. A change of method or timing is dated with methodChange: { validFrom }, a 01.01, the start of a Steuerperiode (MWSTG Art. 37 Abs. 4, Art. 39 Abs. 3). The one mid-year exception is MWSTV Art. 81 Abs. 2: Saldo to effektiv (timing may change too, Abs. 5) on the day the ESTV adjusted a Saldosteuersatz of this book, stated with basis: mwstv_81_2 on a day a saldoGrant took effect. Any other mid-year day refuses vat_method_change_not_period_start, naming what is unmet. CONSEQUENCE: Sets your MWST registration, method, timing, VAT number and ESTV approval. Earlier approvals stay on record; one already used for a filed period is not rewritten, you record a new one.
ParametersasOfmethodrequiredtimingrequiredvatNumberregisteredrequiredsaldoGrantsaldoRatesworkspaceIdrequiredmethodChangeidempotencyKeyrequiredsaldoActivitiessaldoCorrection
Read the current VAT configuration, including the Saldosteuersätze in force today, each Tätigkeit with the Ertragskonten mapped to it, and the elected MWSTV Art. 88 Abs. 6 declaration basis.
ParametersworkspaceIdrequired
The Bewilligungsverlauf: every ESTV Saldosteuersatz approval this workspace has recorded, oldest first, with the days each governed and the Tätigkeiten and Ertragskonten it carried. Under Saldo no rate is stamped on a journal line, so this history is the only evidence of what a filed period was computed with.
ParametersworkspaceIdrequired
The MWSTG Art. 37 Abs. 1 Saldo eligibility limits in force today (both halves of the cumulative test, era-scoped, boundary 1.1.2024) beside the measured steuerbarer Umsatz of one calendar year (Ziffer 299, computed by the same path as the Abrechnung). Never a verdict: eligibility turns on EXPECTED turnover (ESTV practice, MWST-Info 12) and on a tax-due half that needs a rate the ESTV has not granted yet, so this read compares and stops.
ParametersyearworkspaceIdrequired
vat_saldo_declaration_basis
Elect, or withdraw, the MWSTV Art. 88 Abs. 6 simplification for one Steuerperiode: `highest_rate` declares the whole taxable turnover at the highest approved Saldosteuersatz on one Ziffer, `per_activity` restores the Abs. 1 split per Tätigkeit. It is voluntary and usually raises the tax due, so the engine never applies it on its own. CONSEQUENCE: Chooses whether this tax year's net-rate turnover is declared at the highest approved rate or split per activity; the first usually raises the tax. You can withdraw it until a period of the year is filed.
ParametersbasisrequiredtaxPeriodrequiredworkspaceIdrequiredidempotencyKeyrequired
List tax codes (active only by default).
ParametersworkspaceIdrequiredincludeArchived
Add or edit a tax code at the single tax enumeration point.
ParameterscoderequiredkindrequiredlabelrateBprequiredformLinerequiredvalidFromworkspaceIdrequiredidempotencyKey
Archive a tax code (never deletes; a posted line always resolves its code).
ParameterscoderequiredworkspaceIdrequired
Reactivate an archived tax code, so it appears again on new documents. The exact mirror of vat_code_deactivate; posted lines never depended on the flag.
ParameterscoderequiredworkspaceIdrequired
Set (or clear) an account's default tax code.
ParameterstaxCodeaccountIdrequiredworkspaceIdrequired
Preview a line VAT (net/tax/gross, ESTV form line, kind, deductibility) without posting.
ParameterstaxCodesupplyDateamountMinorrequiredworkspaceIdrequiredamountIsGross
Compute the MWST-Abrechnung for a period: ESTV form lines with base/tax, the payable or credit, and the drill-down entry ids.
ParametersperiodEndrequiredperiodStartrequiredworkspaceIdrequired
Export the MWST-Abrechnung for a period as an eCH-0217 v2.0.0 XML file for upload to the ESTV ePortal. Produces a file and transmits nothing: there is no ESTV submission API.
ParametersperiodEndrequiredperiodStartrequiredworkspaceIdrequiredtypeOfSubmission
List the statutory reporting periods of a year (quarterly under effektiv, semi-annual under Saldo) and whether each is filed. In a year the method switched under MWSTV Art. 81 Abs. 2 each method lists its periods inside its own era, and the part of a period the switch cut is listed under stubs (computed by dates, not sealed).
ParametersyearworkspaceIdrequired
Record that a VAT period was filed with the ESTV, applying the A03 hard lock (reason vat_filed) to its months in one transaction: a month under a soft or an ordinary hard lock is upgraded to the seal, every month is read back, and the filing refuses filing_seal_not_held (and rolls back) unless each month holds the seal. Only a filing period as vat_periods lists it for that year can be marked: any other label refuses not_a_filing_period, and a label touching a switch-year stub refuses switch_year_stub_not_modelled, sealing nothing. Transmits nothing. CONSEQUENCE: Records that you filed this MWST period with the ESTV and seals its months for good. TILL sends nothing; later corrections go to the ESTV as a correction return.
ParametersperiodrequiredworkspaceIdrequiredidempotencyKeyrequired
Create a customer/vendor contact. paymentTermsDays is its own Zahlungsfrist in days: omit it and its documents fall due after the workspace default (update_company_profile), 0 means due immediately.
ParametersnameemailaddresspartyRolerequiredvatNumberdescriptionworkspaceIdrequiredidempotencyKeydefaultCurrencypaymentTermsDays
Update a contact from a patch. patch.paymentTermsDays null clears its own Zahlungsfrist back to the workspace default; 0 means due immediately.
ParameterspatchrequiredcontactIdrequiredworkspaceIdrequired
Archive a contact (soft).
ParameterscontactIdrequiredworkspaceIdrequired
Reactivate a soft-archived contact (idempotent).
ParameterscontactIdrequiredworkspaceIdrequired
Read a contact.
ParameterscontactIdrequiredworkspaceIdrequired
List contacts, filtered by query or party role. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParametersquerypartyRolesavedViewIdworkspaceIdrequiredincludeArchived
Create an invoicing item (a reusable line default).
ParametersnamerequiredunitcurrencyworkspaceIdrequireddefaultTaxCodeidempotencyKeyrevenueAccountIddefaultUnitPriceMinorrequired
Update an item from a patch.
ParameterspatchrequireditemIdrequiredworkspaceIdrequired
Archive an item (soft).
ParametersitemIdrequiredworkspaceIdrequired
Reactivate a soft-archived item (idempotent).
ParametersitemIdrequiredworkspaceIdrequired
Read an item.
ParametersitemIdrequiredworkspaceIdrequired
List items, filtered by query. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParametersquerysavedViewIdworkspaceIdrequiredincludeArchived
Create a document draft (quote, order, invoice, or credit note) with positions.
ParameterstyperequiredlinesnotesdueDatecurrencycontactIdsupplyDateworkspaceIdrequiredidempotencyKey
Patch a draft document (draft-only; an issued document is immutable and corrected by reversal).
ParameterspatchrequireddocumentIdrequiredworkspaceIdrequiredidempotencyKey
Advance a document (issue, send, accept, decline, confirm, cancel); issuing an invoice posts via the delegate. Accepting a quote is quotes_accept: an expired quote refuses quote_expired, the acceptance is stamped, and the customer link is spent. CONSEQUENCE: Moves the document to its next status: issuing numbers it and books an invoice or credit note, accepting makes a quote binding. A wrong issued invoice is cancelled with a correcting entry or corrected by a credit note.
ParameterstorequireddocumentIdrequiredworkspaceIdrequiredidempotencyKey
Convert an accepted quote to an order or invoice (or a confirmed order to an invoice), linking the source.
ParameterstoTyperequireddocumentIdrequiredworkspaceIdrequiredidempotencyKey
Read a document with its positions and status trail. For an invoice, include 'qr' and/or 'pdf' to attach the Swiss QR-bill payload and the rendered PDF (A11, D14).
ParametersincludedocumentIdrequiredworkspaceIdrequired
List documents, filtered by type, status, contact, credited invoice (A13: the credit notes of invoice X), or date range. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here, so an explicit one always wins.
ParameterstofromtypestatuscontactIdsavedViewIdworkspaceIdrequiredcreditedDocumentId
Issue a draft invoice: assign the gap-free number, post the balanced VAT entry (A10 onIssue delegate), and attach the QR-bill summary. CONSEQUENCE: Issues the document with its number and books it; from then on it can't be edited. You correct it with a credit note or a cancellation, and the original stays on record.
ParametersinvoiceIdrequiredworkspaceIdrequiredidempotencyKey
Send an issued invoice by email (renders + attaches the PDF, transitions to sent). Outbound step is P8-gated: pass confirmed=true or enable the workspace dial. CONSEQUENCE: Sends it to the recipient. Once it is out, it can't be called back; a correction goes out separately.
ParametersemailconfirmedinvoiceIdrequiredworkspaceIdrequiredidempotencyKey
Draft a Gutschrift against an issued invoice: full, selected positions (reduced quantities), or a net amount apportioned over the remaining line nets. Always a draft; issuing is a separate, confirmed step (P8).
ParametersmodelinesreasonamountMinorworkspaceIdrequiredfromInvoiceIdrequiredidempotencyKeyrequired
Issue a drafted Gutschrift: assign the gap-free G-number and post the mirror entry (debit revenue and output VAT, credit 1100 Debitoren) dated today, closing against the invoice per rate class (D67/D71). CONSEQUENCE: Issues the credit note with its number and books it against the invoice; from then on it can't be edited. If it is wrong, you cancel it, which books a correcting entry.
ParametersworkspaceIdrequiredcreditNoteIdrequiredidempotencyKeyrequired
Read the workspace eBill configuration (the eBill-Biller-ID the owner received from a certified network partner at enrollment), or null when none is set. Enrollment happens with the partner, not in TILL.
ParametersworkspaceIdrequired
Record the eBill-Biller-ID after enrolling with a certified network partner (a commercial step outside the product). Validates the SWP billerPid shape (41 followed by 15 digits) and upserts the one config row per workspace; a malformed id returns invalid_biller_pid and persists nothing. Naturally idempotent (asserts an absolute state), so it takes no idempotency key. Posts nothing.
ParametersbillerPidrequiredworkspaceIdrequired
Turn an issued invoice (issued, sent, or partially_paid) into an eBill delivery payload on disk, carrying A11's QR reference unchanged. Files the A11 PDF as an E00 document (entity_kind ebill_delivery, OR 958f retention) and records an ebill_deliveries row (status prepared) with the payload's conformance facts (PDF/A profile, eBill addressing, byte length) recorded, never claimed. Refuses a draft/cancelled/settled invoice (invalid_state) and an invoice with no payment part (needs_qr_bill), writing nothing. Idempotent by outcome: at most one active (non-failed) delivery per invoice, so a re-prepare returns the existing row and its stored artifact regardless of key. Posts nothing.
ParametersinvoiceIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Transmit a prepared delivery through the owner-gated cloud connector (P8: outbound, draft-by-default; pass confirmed=true or enable the workspace dial). Guard order: no connector returns the honest {transmitted:false, reason:'cloud_tier'} and the artifact stays downloadable; then needs_biller_pid; then needs_confirmation; then payload_not_conformant if the payload is not PDF/A-3b, not eBill-addressed, or over 10 MB (nothing non-conformant is ever transmitted). On acknowledgement records the business case and drives the invoice issued->sent (A10) only from issued. Idempotent: a transmitted delivery never resubmits; transmission is at-least-once via a stored correlation id. Posts nothing. CONSEQUENCE: Transmits the invoice as an eBill into the customer's e-banking through the connected eBill service. Once it is out, it can't be called back; a correction goes out separately.
ParametersconfirmeddeliveryIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Track eBill deliveries: one by deliveryId (with its mirrored partner-status event trail), or a filtered list by invoiceId, local status (prepared|submitting|transmitted|failed), mirrored partner status (NWP_PENDING|OPEN|APPROVED|REJECTED|COMPLETED), or created-at range, newest first. Read-only.
ParameterstofromstatusinvoiceIddeliveryIdsavedViewIdworkspaceIdrequiredpartnerStatus
Open or advance a bank channel, EBICS 3.0 (H005) by default or the managed bLink rail with channelKind='managed_blink' (A37). Human only: pass confirm=true (P8); never fired by an automation rule. EBICS, keyed to the bank contract (host, partnerId, userId), never an account: the routed accounts are checked first (camt054_lines_refused; a sandbox or demo workspace is trial_workspace_refused; one live connection per subscriber in the database, live_connection_exists), then HEV (a host without H005 is unsupported_ebics_version), then three RSA 2048 key pairs with self-signed X.509 certificates are generated locally, the electronic-signature private key is dropped at once, the connection and the INI letter (the certificate hashes to sign and post) are filed, and INI and HIA are sent as two legs. The answer is pending_bank_activation, ini_sent (a lost answer: call again with connectionId to resend only the unconfirmed leg), or a refusal in words: init_refused (wrong partner or user ID, H005 not enabled, or already initialised), certificate_refused, key_exchange_refused. With connectionId: resends unconfirmed legs, runs HPB, and without confirmBankKeys returns the bank's key and certificate hashes for the owner to compare with ZKB's published sheet; with confirmBankKeys=true and expectedBankKeyHashes set to exactly that reviewed set it pins them and activates, only if a fresh HPB equals them (else bank_keys_mismatch, nothing pinned). The same reviewed confirm resumes a bank_keys_changed or locally blocked channel. Under till up TILL checks once a day by itself whether the bank has activated the access (bank_channel_status activation.bankReady, D143); the comparison and the confirm stay the human's. Never returns key material; posts nothing. CONSEQUENCE: Opens a channel to your bank: TILL makes the keys and sends the bank its setup, then statements (on the managed rail also payments) flow over it. What the bank got can't be recalled; you can retire or block the channel.
ParametershostscopesbankRefconfirmkeyLengthchannelKindworkspaceIdrequiredconnectionIdidempotencyKeyrequiredconfirmBankKeysrouteBankAccountIdsexpectedBankKeyHashes
Fetch the new day-end camt.053 statements (version 08) over an active EBICS channel, on demand (the Studio's Kontoauszüge abrufen, or when the owner asks) and, under till up, once a day by the scheduler (D142, set_bank_sync_schedule); never by an automation rule. Persists the bank's container and every new statement as documents first, then imports each one through import_camt by its account IBAN, then sends the bank's receipt, so nothing fetched is lost and nothing counts twice. On an EBICS-fed account a statement is imported only as the successor of the newest statement in the books or as the filler of a hole, by number and balances; a copy of one already there is already_imported; others wait (gap_refused, before_feed_start, not_day_end_statement, unsupported_multipage_statement, unmatched_account) and are retried from the stored bytes at every sync, or are refused for good (overlap_refused). A statement whose number skips some but whose balances chain imports with notice statement_number_jump and jump {after, statement, skipped} naming the missing numbers, which the owner imports by hand if they exist. Each call needs a fresh idempotencyKey; dateRange is refused (unsupported_date_range). Answers download_refused (not_granted, busy, too_large, other, with the bank's raw code), untrusted_response, bank_keys_changed or channel_unreachable in words. One fetch per connection at a time: a second call while one runs answers sync_in_progress. With no transport wired it reports needs_bank_transport. Posts nothing. CONSEQUENCE: Fetches new day-end statements from your bank and imports them; each new bank line waits in the bank inbox and nothing is booked. The bank gets its receipt, and an import cannot be taken back.
ParametersdateRangeworkspaceIdrequiredconnectionIdbankAccountIdidempotencyKeyrequired
Hand a generated A18 pain.001 payment batch to a bank channel that uploads payments. The EBICS channel downloads statements only: a batch whose debtor account is routed over EBICS is refused upload_disabled before anything is sent (upload the pain.001 in eBanking and release it there). A batch whose account is routed over the managed bLink rail (A37) is submitted there, P8-gated (confirm=true). With no channel it returns needs_bank_channel and the file path stands. Never marks anything paid (paid comes from the camt debit). Posts nothing. CONSEQUENCE: Submits the payment batch to your bank over the connected channel; TILL can't call it back. It marks nothing as paid: that comes from booking the bank debit or confirming the batch as paid.
ParametersbatchIdrequiredconfirmworkspaceIdrequiredidempotencyKeyrequired
Retire or block an EBICS bank channel (P8-gated: pass confirm=true or enable the approval dial). retire is the local, terminal close: the channel flips to retired, its order history stays readable, and its keys are destroyed. block is local only: TILL stops using the channel at once and sends nothing to the bank (a block at ZKB is the owner's phone call); the reviewed bank-key confirm through bank_channel_connect is the way back. Both idempotent. Posts nothing. CONSEQUENCE: Retiring ends this bank channel and destroys its keys for good; blocking only stops TILL using it. Its order history stays readable, and a retired channel cannot reopen: connecting again makes new keys.
ParametersmoderequiredconfirmworkspaceIdrequiredconnectionIdrequiredidempotencyKeyrequired
Read EBICS channel health: per channel the connection state, the INI and HIA legs, the keystore state, the pending INI letter, per routed account the newest statement in the books (number, year, date, closing balance) and lastNumberJump (the numbers skipped right before the newest statement the channel imported, null once they are in the books or the next statement followed normally), every downloaded statement still waiting with the reason it waits (a gap, before the feed start, an unrouted IBAN, a split statement) and the facts it names, the last sync, whether a fetch is running right now (syncInProgress, syncStartedAt: one fetch per connection at a time, D142), the daily automatic fetch (autoSync: mode, atTime, nextAt, the last automatic attempt, attemptsToday), the short name of the bank (bankName), the daily activation check while ZKB has not activated the access yet (activation: checking, lastCheckAt (the last HPB the bank answered), lastAttemptAt, nextCheckAt, lastOutcome, bankReady; D143), and the recent order log. When activation.bankReady is true the bank has answered and the keys must be compared: tell the human to open the bank accounts screen (/bank-accounts) and compare the bank key hashes with the sheet the bank published, then confirm (bank_channel_connect with confirmBankKeys). That comparison is an act of the human; never confirm the keys yourself. Optionally scoped to one bank account, or the order log filtered by status (a saved view applies its stored status filter; an explicit status wins). Read-only.
ParametersstatussavedViewIdworkspaceIdrequiredbankAccountId
Look up a Swiss bank in TILL's static, in-package EBICS directory for the connect wizard (A36): substring or BIC match over the curated set, returning each bank's names, BIC, the marketing name of its EBICS channel, the segments it offers EBICS to, where to post the signed INI letter, known protocol quirks, and an EXPLICITLY UNVERIFIED fee note (verified:false always). The per-contract host URL and Host ID are null in v1 (the bank issues them on your signed EBICS contract; enter them in the manual fields). Reads static data only: opens NO socket, needs no idempotency key, is never a gate on the ceremony. An empty query returns the whole set; no match returns an empty array, not an error.
ParametersqueryworkspaceIdrequired
Set the daily automatic statement fetch of an EBICS connection (D142): mode 'daily' or 'off' and atTime as a Swiss local time HH:MM (default 07:00; an active connection that never set a mode is fetched daily). Under till up the scheduler then fetches once a day at that time, catches up at start when TILL was closed, and retries a bank that did not answer or was busy hourly, at most three attempts a day; till serve has no scheduler. No automation rule fetches statements: passing a ruleId is refused sync_schedule_parked, and the call also clears a rule pointer an older build stored. Idempotent; banking-write. Posts nothing. CONSEQUENCE: Sets when TILL fetches your bank statements each day, or turns that off. The fetch runs in the name of whoever set it, or the owner's once that person loses the right.
ParametersmodeatTimeruleIdworkspaceIdrequiredconnectionIdrequiredidempotencyKeyrequired
Confirm that nothing is missing in a statement gap of a Bankkonto (A36 §4.7, D150): the day-end statements afterStatementId and beforeStatementId are neighbours in the books, their numbers skip, and the later one opens exactly on the earlier one's closing balance (difference 0), so the skipped numbers are days without bookings or bookings that cancel out. Human only: a person at the button passes confirmed=true and a reason; an agent seat is refused human_only (propose it to the person instead). Refuses gap_has_waiting_statement when a downloaded statement inside the gap does not chain (it proves money the books do not explain), and gap_not_chained when the balances do not chain (the missing statements carry money that is not in the books: import them, such a gap can never be confirmed) and gap_not_found when the gap was filled or the two statements are not neighbours. Appends one confirmation row and its audit entry; changes no statement and posts nothing. A confirmed gap leaves bank_channel_status statementGaps and the attention hub; a statement found later still imports. Idempotent per key; a gap already confirmed answers alreadyConfirmed. CONSEQUENCE: Records that the missing bank statements between two statements hold no money, so the gap stops waiting for you. You can withdraw this, and a statement found later still imports.
ParametersreasonrequiredconfirmedworkspaceIdrequiredbankAccountIdrequiredidempotencyKeyrequiredafterStatementIdrequiredbeforeStatementIdrequired
revoke_statement_gap_confirmation
Withdraw the confirmation that a statement gap holds nothing (A36 §4.7, D150), so the gap is an attention item again. Human only (confirmed=true, a reason; an agent seat is refused human_only). Appends a withdrawal row beside the confirmation, which stays; a gap that is not confirmed answers notConfirmed without a row, and a gap filled since answers gap_not_found. Changes no statement, posts nothing. Idempotent per key. CONSEQUENCE: Withdraws the confirmation that a statement gap holds nothing, so the gap waits for a person again. The confirmation stays on record beside the withdrawal.
ParametersreasonrequiredconfirmedworkspaceIdrequiredbankAccountIdrequiredidempotencyKeyrequiredafterStatementIdrequiredbeforeStatementIdrequired
Record a foreign-currency rate (§H-FX). `rate` is a DECIMAL STRING and is the price of one unit of `baseCurrency` in the workspace base currency, so EUR/CHF 0.9412 means 1 EUR = 0.9412 CHF. `asOf` is the date the rate is valid FOR. `method` names the admissible MWSTV Art. 45 basis (daily | monthly_avg | bank | group). Recording the same rate twice is one row; a different rate under the same date and source is refused, because it may already have priced a posted entry. CONSEQUENCE: Records an exchange rate for its date; foreign-currency entries on that date then use it. The rate stays on record unchanged; an entry it priced wrongly is fixed with a correcting entry.
ParametersasOfrequiredraterequiredmethodsourceprovenanceworkspaceIdrequiredbaseCurrencyrequiredquoteCurrencyidempotencyKeyrequired
List recorded foreign-currency rates, newest validity date first, optionally filtered by currency pair and date range.
ParameterstofromworkspaceIdrequiredbaseCurrencyquoteCurrency
Resolve which rate WOULD convert a currency into the workspace base currency on a date, and report the validity date, source and method of the rate that governs. Answers `needs_fx_rate` when none is admissible, rather than inventing one.
ParametersdatecurrencyrequiredworkspaceIdrequired
Elect the MWSTV Art. 45 conversion basis for a Steuerperiode: `daily` (Tageskurs, Devisenkurs Verkauf), `monthly_avg` (Monatsmittelkurs) or `group` (Konzernumrechnungskurs, group members only). `taxPeriod` is a calendar year (MWSTG Art. 34 Abs. 2) and defaults to the current one. The election carries forward until it is changed. Art. 45 Abs. 5 binds it for at least one Steuerperiode, so it may only be written while that period, and every period after it, still holds no posted foreign-currency entry. `bank` (Abs. 3bis) is not electable: it is the mandated fallback for currencies the ESTV publishes no rate for and stays admissible under every election. CONSEQUENCE: Chooses the exchange-rate basis MWST uses for foreign-currency amounts from this tax year on. You can change it only while that year and later ones hold no posted foreign-currency entry.
ParametersmethodrequiredtaxPeriodworkspaceIdrequired
Report which MWSTV Art. 45 conversion basis governs a Steuerperiode, whether that period is already settled by a posted foreign-currency entry, the earliest period whose basis may still be chosen, and the full election history. Ask by `taxPeriod` (YYYY) or by any `date` inside it.
ParametersdatetaxPeriodworkspaceIdrequired
Report which published rate series MWSTV Art. 45 admits, the endpoint each one lives at, how its validity dates and per-unit quotations work, and the pages that establish it. Call this first: the engine performs NO network I/O, so a caller fetches the endpoint itself and hands the response body to `import_exchange_rates`.
ParametersworkspaceIdrequired
Import a published BAZG rate payload into the rate store as `source='rate_api'`. `payload` is the response body from the endpoint `describe_rate_feed` names, verbatim. The payload identifies its own series; pass `series` to have a mis-paired payload refused rather than mis-dated. Daily rates are stored on each date in the payload's validity window (not on the determination date), monthly averages once on the first of their month, and per-unit quotations (100, 1000, 10000) are scaled. A published rate TILL cannot hold exactly at twelve decimal places is reported rather than rounded; the whole BAZG daily series is within that (its deepest is nine places). CONSEQUENCE: Imports the published BAZG exchange rates into your rate list, each on the dates it is valid for. Imported rates stay unchanged; an entry one priced wrongly is fixed with a correcting entry.
ParametersseriespayloadrequiredcurrenciesworkspaceIdrequiredidempotencyKeyrequired
Revalue every open foreign-currency monetary position (A19 FC bank balances, A16/A17 open FC debtor/creditor items) at the closing rate for `periodEnd` (OR Art. 960a: Bilanzstichtagskurs). Returns each position with its foreign-currency amount, book CHF, closing rate, revalued CHF and the UNREALISED diff, the per-currency subtotals, the net total, and any currency that still needs a rate. A read model: nothing is posted. Negative total is a net unrealised loss.
ParametersperiodEndrequiredworkspaceIdrequired
Post the period-end UNREALISED currency gain/loss as a balanced entry (source `fx`) plus its next-period reversal, atomically. The unrealised difference books to account 6949 against each revalued position, and the entry auto-reverses on the first day of the next period so the REALISED figure at settlement (A14/A18) is never double-counted. Idempotent per `periodEnd`: a re-post with the same key replays, a different key returns `already_posted`, a zero-diff period posts nothing. Refuses `needs_rate` when any open FC position lacks a closing rate, and `period_locked` for a locked target period (A03). CONSEQUENCE: Books the period-end currency gain or loss, with its automatic reversal on the first day of the next period. If it is wrong, you revert the run with correcting entries; the originals stay visible.
ParametersperiodEndrequiredworkspaceIdrequiredidempotencyKeyrequired
Revert a posted FX revaluation run (D129 Q2): books the mirror of the revaluation entry dated the period end (`source` `fx`) plus its own next-day reversal, atomically, so every position and account 6949 net to zero on both dates and nothing is edited. `runId` is the run `post_fx_revaluation` returned. Refuses `not_posted` for a run that posted nothing, `already_reversed`, `later_run_exists` naming the later period end whose run still stands (revert newest first), and `period_locked` for a locked period. Idempotent on `idempotencyKey`. CONSEQUENCE: Reverts the period-end currency revaluation with mirror entries, so every account nets to zero. The original entries stay visible beside them; this revert can't be reverted again.
ParametersrunIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Describe an Abgrenzung (OR Art. 958b) and save it as a DRAFT: `kind` is one of prepaid_expense (Aufwand vorausbezahlt, Dr 1300), accrued_income (Ertrag noch nicht fakturiert, Dr 1300), accrued_expense (Aufwand noch nicht fakturiert, Cr 2300) or deferred_income (Ertrag vorausbezahlt erhalten, Cr 2300); `contraAccount` is the P&L account (number or id, income for the income kinds, expense for the expense kinds); `amountMinor` is integer Rappen; `periodEnd` is the balance-sheet date. Returns the draft with the exact lines the post will write and the reversal lines dated the day after. Nothing is posted.
ParameterskindrequiredcurrencyperiodEndrequiredsourceRefamountMinorrequireddescriptionrequiredworkspaceIdrequiredcostCenterIdcontraAccountrequiredidempotencyKeyrequired
Post a drafted Abgrenzung as an atomic PAIR: the accrual entry dated `periodEnd` (source `accrual`) and its automatic Rückbuchung dated the first day after (a real reversal, linked). A locked reversal date rolls the whole pair back, so the books never carry an accrual without the reversal that backs it out. Idempotent per accrual: the same key replays, a different key on a posted accrual is `already_posted`, a discarded draft is `draft_discarded`. CONSEQUENCE: Books the accrual and its automatic reversal in the next period as one pair. If it is wrong, you revert it with a mirror pair; all four entries stay visible.
ParametersaccrualIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Revert a posted Abgrenzung without editing history: posts the MIRROR pair (the Storno dated `periodEnd`, its own reversal dated the day after), so all four entries net to zero on every account in both periods. Refuses `already_reversed` a second time and `not_posted` on a draft. CONSEQUENCE: Books the mirror pair against a posted accrual, so every account nets to zero; the original pair stays visible. If the reversal was wrong, you create and post the accrual again.
ParametersreasonaccrualIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Retire a drafted Abgrenzung before it posts. The row stays on record as `discarded` with its reason; a posted accrual cannot be discarded (`already_posted`), reverse it instead.
ParametersreasonaccrualIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Read one Abgrenzung: the row, its lines and reversal lines (from the same function the post uses), and the journal entries it has produced (the accrual, its reversal, the Storno pair).
ParametersaccrualIdrequiredworkspaceIdrequired
List Abgrenzungen, newest period first, filtered by periodEnd, status (draft | posted | reversed | discarded) or kind. `totalMinor` sums the drafts and the posted ones. savedViewId applies a saved view (G00).
ParameterskindstatusperiodEndsavedViewIdworkspaceIdrequired
Describe a Rückstellung (OR Art. 960e) and save it as a DRAFT: `reason` is one of the eight statutory ids (Garantie, Ferien und Überzeit, Prozess, Grossreparatur, Sanierung, Restrukturierung, Steuern, Sonstige; `invalid_reason` names the exact ids, and `sonstige` needs a description of at least 10 characters); `provisionAccount` is 2330, 2600 or a liability numbered 23xx/26xx; `expenseAccount` is the P&L account the formation is charged to. Returns the draft with its lines (Dr expense / Cr provision). Nothing is posted.
ParametersreasonrequiredperiodEndrequiredamountMinorrequireddescriptionrequiredworkspaceIdrequiredexpenseAccountrequiredidempotencyKeyrequiredprovisionAccountrequired
Post a drafted Rückstellung as ONE entry (Dr expense / Cr provision, source `provision`) dated `periodEnd`. No automatic reversal: OR 960e Abs. 4 does not release a provision by the calendar. Idempotent per provision; a different key on a posted one is `already_posted`. CONSEQUENCE: Books the provision as one entry; it is not released automatically. You release it later, or correct it with a correcting entry; both stay visible.
ParametersprovisionIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Release part or all of a posted Rückstellung: posts Dr provision / Cr `targetAccount` (the original expense account, or an income account) for `amountMinor` on `date`. Refuses `release_exceeds_balance` above the open balance; the provision reads `released` at zero. Idempotent on `idempotencyKey` for as long as the release that key booked still stands; a key whose release was undone refuses `already_reversed_key` (release again under a new key). A release is undone only with `provision_release_reverse`; the raw `reverse_entry` refuses its entry with `owned_by`. CONSEQUENCE: Books the release of part or all of the provision to the target account. If it is wrong, you undo the release with a correcting entry; both stay visible.
ParametersdaterequiredamountMinorrequiredprovisionIdrequiredworkspaceIdrequiredtargetAccountrequiredidempotencyKeyrequired
Reverse the formation entry of a posted Rückstellung (a real reversing entry, dated `periodEnd` unless `date` names another open day). Refuses `release_blocked` while any release stands unreversed (undo the releases first through `provision_release_reverse`, newest first) and `already_reversed` a second time. This is the ONLY way to reverse the formation: the raw `reverse_entry` refuses it with `owned_by`. CONSEQUENCE: Corrects the provision's original booking with a correcting entry; any releases have to be undone first. The original stays visible; if this was wrong, you create and post the provision again.
ParametersdatereasonprovisionIdrequiredworkspaceIdrequiredidempotencyKeyrequired
provision_release_reverse
Undo one release of a Rückstellung with a real reversing entry (dated the release date unless `date` names another open day), so the open balance and the `posted` / `released` reading follow from the journal again. This is the ONLY way to reverse a release entry: the raw `reverse_entry` refuses it with `owned_by`, and so it refuses the undo itself. Refuses `not_found` and `already_reversed`. Idempotent on `idempotencyKey`. CONSEQUENCE: Undoes one release of the provision with a correcting entry and restores its open balance. The release stays visible; to release again, you book a new release.
ParametersdatereasonreleaseIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Retire a drafted Rückstellung before it posts. The row stays on record as `discarded` with its reason; a posted provision cannot be discarded (`already_posted`), reverse or release it instead.
ParametersreasonprovisionIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Read one Rückstellung: the row, its formation lines, every release with its entry (and the reversal of that entry, when one exists) and the open balance, derived as the formation amount minus the live releases.
ParametersprovisionIdrequiredworkspaceIdrequired
List Rückstellungen, newest period first, each with its open balance, filtered by periodEnd, status (draft | posted | released | reversed | discarded) or reason. `openTotalMinor` sums the open balances. savedViewId applies a saved view (G00).
ParametersreasonstatusperiodEndsavedViewIdworkspaceIdrequired
Propose the Steuerrückstellung for the fiscal year to `periodEnd` the way Kanton Zürich ZStB 27/1 computes it: profit before tax times s/(1+s) at `rateBp` (default 2000 = 20 %, the rate is cantonal and yours to set), minus the instalments already charged to 8900, never below zero. Returns the figures and a ready `provision_create` draft (reason steuern, Dr 8900 / Cr 2330). On an Einzelfirma answers applicable:false. A read: nothing is posted.
ParametersrateBpperiodEndrequiredworkspaceIdrequired
Preview the MWST-Saldierung of one filed period (`period` is the A07 label, `2026-Q3` or `2026-H1`): the booked movement on 2200 (Umsatzsteuer), 1170 and 1171 (Vorsteuer) over the period beside the return's Ziffer 399 and 400 + 405 with the differences, and the exact lines the post would book (Dr 2200 / Cr 2201, Dr 2201 / Cr 1170, Dr 2201 / Cr 1171; under the Saldosteuersatz the flat-rate tax due against 3809). Settlement entries and their reversals are excluded from the read, so a settled period previews as settled, never twice. A read: nothing is posted.
ParametersperiodrequiredworkspaceIdrequired
Book the MWST-Saldierung the preview showed: transfer the filed period's balances on 2200, 1170 and 1171 to 2201 (MWST-Abrechnungskonto), dated the period end, `source='vat_settlement'`, so the three tax accounts read zero and 2201 carries what the ESTV is owed. Admitted inside the filed, hard-locked period under three enforced conditions (no VAT trace, only the tax accounts, never into a year-close seal); the filed return and the Abstimmung are unchanged by it. Refuses `period_not_filed` before the filing, `nothing_to_settle` on an empty period, `already_posted` while a settlement of the period stands, `period_locked` with reason `year_close` on a sealed year. Idempotent on `idempotencyKey` for as long as the settlement that key booked still stands; a key whose settlement was reversed refuses `already_reversed_key` (post again under a new key, which books a new settlement). The correction is `vat_settlement_reverse`. CONSEQUENCE: Moves the filed period's MWST balances from 2200, 1170 and 1171 to 2201; the filed return does not change. If it is wrong, you reverse the settlement and book it again.
ParametersperiodrequiredworkspaceIdrequiredidempotencyKeyrequired
Reverse a posted MWST-Saldierung with a reversing entry dated the period end, so 2200, 1170, 1171 and 2201 net to zero again inside the settled period; the settlement row reads `reversed` and keeps its history, and a later `vat_settlement_post` for the period books a new settlement. This is the ONLY way to reverse a settlement entry: the generic `reverse_entry` refuses it with `owned_by`, because the settlement row must move with the mirror. Refuses `not_found` and `already_reversed`. Idempotent on `idempotencyKey`. CONSEQUENCE: Reverses the MWST settlement with a correcting entry dated the period end; the settlement stays on record as reversed. You can then book a new settlement for the period.
ParametersworkspaceIdrequiredsettlementIdrequiredidempotencyKeyrequired
List the MWST-Saldierungen on record, newest period first, posted and reversed, with the moved figures and the entry ids. `year` (YYYY) narrows to one Steuerperiode. A read.
ParametersyearworkspaceIdrequired
vat_annual_reconciliation
The two annual MWST reconciliations of a calendar year as figures (Art. 128 Abs. 2 and 3 MWSTV, the ESTV's Umsatz- and Vorsteuerabstimmung): the class-3 revenue per the books adjusted for the accruals and disposal proceeds the ledger can name against the sum of Ziffer 200 of the year's returns, and the booked Vorsteuer on 1170 + 1171 against the sum of Ziffer 400 + 405, each with its difference and a status (`match`, `warn`, or `unavailable` naming the periods not yet filed). Under the Saldosteuersatz the Vorsteuer half is not applicable; a workspace with no MWST method answers `applicable: false`. A read.
ParametersyearrequiredworkspaceIdrequired
Preview exactly what a payment would post, without writing anything: the remainder still to allocate, each document's resulting open amount and status, the Skonto VAT split, the Ist-timing paid-portion VAT, the currency conversion with its realised difference, and the journal legs with account numbers and labels. Call this before record_payment so the figures a human sees and the figures the ledger books are the same figures. It takes no intent and can never post.
ParametersdaterequiredfxRatesourcecurrencydirectionrequiredreferenceallocationsamountMinorrequiredworkspaceIdrequiredbankAccountIdrequiredcounterpartyIdonAccountMinor+1 more
Rank the open items a payment might settle, with the reason in words: reference matches, amount and customer match, or amount close. A QR or Creditor Reference whose check digit fails is reported as a typo and never ranked as a match, and a candidate that fits no tier carries no reason at all. This is the same read model the Studio's candidate list renders.
ParameterscurrencydirectionreferenceamountMinorworkspaceIdrequiredcounterpartyId
Record an incoming or outgoing payment and post its balanced entry (bucht eine Zahlung). Allocates across one or several open items with partial amounts, Skonto, and an Ausbuchung of a small residual; any remainder is parked as a Guthaben for its counterparty. Requires intent='post_payment', because money never moves as a side effect. CONSEQUENCE: Records the payment and marks what it settles as paid. If it is wrong, you reverse the payment, which reopens them; both stay visible.
ParametersdaterequiredfxRateintentrequiredsourcecurrencydirectionrequiredreferenceallocationsamountMinorrequiredworkspaceIdrequiredbankAccountIdrequiredcounterpartyId+3 more
Allocate a parked Guthaben to open items. The money was already booked when the payment arrived, so this posts no entry: it records which open items that money settles. Requires intent='allocate_payment'. A wrong allocation is corrected by reversing the whole payment and recording it again. CONSEQUENCE: Applies a payment already on the books to open items and marks them paid; nothing new is booked. A wrong allocation is corrected by reversing the whole payment and recording it again.
ParametersintentrequiredpaymentIdrequiredallocationsrequiredworkspaceIdrequiredidempotencyKeyrequired
Reverse a payment (storniert eine Zahlung): posts a reversing entry and re-opens every document it settled. It never deletes, the original entry stays untouched, and a payment is always reversed as a whole. Requires intent='reverse_payment'. CONSEQUENCE: Reverses the payment with a correcting entry and reopens everything it settled. The original stays visible; if the payment was right after all, you record it again.
ParametersdateintentrequiredpaymentIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Read one payment: its allocations by document number, its Guthaben, its journal entry, and its reversal when it has one.
ParameterspaymentIdrequiredworkspaceIdrequired
List payments, filtered by direction, status, date range, or the document they settled. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here, so an explicit one always wins.
ParameterstofromstatusdirectiondocumentIdsavedViewIdworkspaceIdrequired
Set the residual below which the Studio may offer a one-click Ausbuchung, in Rappen (default CHF 1.00). It governs the offer only: a larger write-off stays recordable when it is stated deliberately. This is a product setting and not a rounding rule. CONSEQUENCE: Sets the leftover amount below which the Studio offers a one-click write-off of an open item. Larger write-offs stay possible when stated deliberately; you can change the amount again.
ParametersworkspaceIdrequiredidempotencyKeyrequiredthresholdMinorrequired
The OP-Liste: every unpaid or partly-paid invoice with its open amount, due date, days overdue and aging bucket, plus every parked customer payment. A parked payment carries its direction: incoming is a Guthaben the customer holds and reads NEGATIVE, outgoing is a refund not yet matched and reads POSITIVE. Reports bucket subtotals in the invoice currency (bucketTotals) and in base currency (baseBucketTotals, the only one that is an amount when several currencies are open), the grand total both ways, and whether the base total reconciles to account 1100 Debitoren as of the same date. Pass asOf to see the receivables exactly as they stood on a past cut-off (payments after it are ignored). Filter by customerId or currency to narrow the table without changing what reconciled means. Reads only.
ParametersasOfcurrencycustomerIdworkspaceIdrequired
What one customer owes: their total open amount, the split across aging buckets in both the invoice currency and base currency, how many days their oldest overdue item has been outstanding, and any parked payment attached to them. onAccountMinor is reported positive for a Guthaben, so it comes out negative when what is parked is an unmatched refund: read the direction on the row rather than the sign of the total. An unknown customer reads as an empty balance rather than an error. Reads only.
ParametersasOfcustomerIdrequiredworkspaceIdrequired
The receivables summary behind the aging bar: the same open items list_open_items itemises, totalled per bucket and per customer, largest debtor first. byBucket is the invoice-currency sum and baseByBucket the base-currency one, which is the figure that ties to baseTotalOpenMinor in a workspace holding more than one currency. Use it to answer "how much is over 90 days overdue and who owes it" in one call. Carries the same reconciliation flag against 1100 Debitoren. Reads only.
ParametersasOfworkspaceIdrequired
The day thresholds the aging buckets cut at, and whether this workspace chose them or is on the shipped default of 30/60/90 days. Also returns the bucket keys those boundaries produce. Reads only.
ParametersworkspaceIdrequired
Redefine where the aging buckets cut, as a strictly increasing list of positive day counts (the default [30, 60, 90] gives 0-30, 31-60, 61-90 and 90+). This changes the VIEW only: the buckets re-partition the same receivables total and can never change it, and the reconciliation to 1100 Debitoren holds for any boundary set. It is a DACH reporting convention, not a statutory figure, and it is not a dunning deadline (A15 owns those). A repeat call under the same idempotencyKey writes nothing.
ParametersworkspaceIdrequiredboundariesDaysrequiredidempotencyKeyrequired
Register a Bankkonto: validates the IBAN (ISO 13616 mod-97), derives whether it is a QR-IBAN (QR-IID 30000 to 31999, receive-only), and links it to an asset account in the chart (ledgerAccountId, e.g. 1020 Bankkonto). Does NOT set an opening balance: that is set_bank_opening_balance. CONSEQUENCE: Registers a bank account with its IBAN and ledger account, so payment runs and bank imports can use it; nothing is booked. You can fix its details until an opening balance is posted, or archive it.
ParametersibanrequirednamerequiredcurrencyworkspaceIdrequiredidempotencyKeyledgerAccountIdrequired
Rename a Bankkonto or correct its details. The IBAN, currency and verknüpftes Konto freeze once the account is referenced by a posted opening balance (account_in_use); the name stays editable for good. CONSEQUENCE: Changes this bank account's IBAN, currency or ledger account; later payment runs and bank bookings use the new details. You can change them back until an opening balance is posted on it.
ParametersibannamecurrencyworkspaceIdrequiredbankAccountIdrequiredidempotencyKeyledgerAccountId
Post a Bankkonto's opening balance as a real balanced journal entry (debit the bank account, credit 9100 Eröffnungsbilanz), in integer Rappen. Explicitly confirmed and idempotent: re-sending the same idempotencyKey returns the original entry and never posts twice. A correction to a posted opening balance is a reversing entry, never a second opening. CONSEQUENCE: Books the bank account's opening balance against 9100 Eröffnungsbilanz, once. A correction is a correcting entry, never a second opening; both stay visible.
ParametersdaterequiredfxRatecurrencyamountMinorrequiredworkspaceIdrequiredbankAccountIdrequiredidempotencyKeyrequired
preview_bank_opening_balance
Show what set_bank_opening_balance WOULD post for a Bankkonto, in the workspace base currency, without posting anything: the base amount, the rate it converted on, and the two legs (the Bankkonto's verknüpftes Konto against 9100 Eröffnungsbilanz). It runs the posting's own arithmetic, so the FIGURE cannot disagree, and it answers the same refusals the posting answers for the state it reads (needs_account for a missing or archived 9100, currency_mismatch, opening_balance_already_set, needs_fx_rate, period_locked). It is not a promise about the posting. It checks no capability, so a caller without the post right gets the full figure here, and at set_bank_opening_balance that caller is refused permission_denied at every amount, including the zero one that books no journal entry; that refusal is not always the FIRST one, because an unknown Bankkonto, an opening balance already set, or (above zero only) a missing 9100 is answered before the capability is consulted, and an idempotencyKey that replays an already-completed call still replays. It also holds no state, so a period locked, a 9100 archived or another actor posting in between still refuses there. Takes no idempotency key and can never post: use it before Buchen, because a posted opening balance is immutable and its only correction is a reversing entry.
ParametersdaterequiredfxRatecurrencyamountMinorrequiredworkspaceIdrequiredbankAccountIdrequired
Archivieren: hide a closed Bankkonto from pickers while keeping it referenceable by historical statements and entries. Never deletes the account.
ParametersworkspaceIdrequiredbankAccountIdrequiredidempotencyKey
Wiederherstellen: put an archived Bankkonto back in the pickers. The inverse of archive_bank_account, and a Bankkonto that is already active stays active (no rejection). Nothing about the account changes: this only clears the archived flag.
ParametersworkspaceIdrequiredbankAccountIdrequiredidempotencyKey
List this workspace's Bankkonten with their IBAN, currency, verknüpftes Konto, QR-IBAN flag and opening balance. Archived accounts are excluded unless includeArchived is true. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParameterssavedViewIdworkspaceIdrequiredincludeArchived
Read one Bankkonto, including whether its IBAN is a QR-IBAN and therefore receive-only (a QR-IBAN may only be credited, never used as a debit account).
ParametersworkspaceIdrequiredbankAccountIdrequired
Saldenbilanz (trial balance): every account's opening balance, its debit and credit movement in the period, and its closing balance, in the workspace base currency and integer Rappen. Figures are debit-positive, exactly as the ledger holds them, and drafts are excluded. Pass compareTo={periodStart,periodEnd} for the prior-period column and its delta. reconciles reports three checks by name (debit equals credit, the closing column ties to an independently queried ledger balance, and every account the ledger moved was rendered); it is evidence about coverage and the period boundaries, not proof that an account sits in the right section. groupBy accepts 'kmu' today and refuses anything else, because account-level custom fields are a G00 capability that does not exist yet.
ParametersgroupBycompareToperiodEndrequiredperiodStartrequiredworkspaceIdrequired
Bilanz (balance sheet) as of a date, grouped into the FIRST LEVEL of OR Art. 959a: Umlaufvermögen and Anlagevermögen on the Aktiven, kurzfristiges Fremdkapital, langfristiges Fremdkapital and Eigenkapital on the Passiven, each section carrying its statutory heading in de/fr/it/en, plus one residual section per side (the "weitere Positionen" of OR Art. 959a Abs. 3) so no account can be dropped. Under each section the accounts are listed individually, ordered by account number. Every line is positive on its own side. The running result IS carried as an Eigenkapital position (OR Art. 959a Abs. 2 Ziff. 3 lit. f and lit. g), which is what makes the statement foot before a year-end close has run. WHAT IT IS NOT: the statutory minimum structure. Twenty-four individual sub-positions are prescribed "einzeln und in der vorgegebenen Reihenfolge" (flüssige Mittel, Forderungen aus Lieferungen und Leistungen, aktive Rechnungsabgrenzungen, and so on) and are not modelled: only the seven groupings above are, with raw account lines under them. The two Absätze that prescribe those 24 are OR Art. 959a Abs. 1 and OR Art. 959a Abs. 2, and A08 reaches the grouping level of each and stops there. On the shipped Kontenrahmen KMU the account numbers happen to ascend in the statutory order, so the output looks right by coincidence; on a renamed or renumbered chart it names none of the required positions and may order them arbitrarily, and no reconciliation flag can see the difference because the statement still foots either way. So do not report this output as OR-conformant, as the minimum structure, or as ready to file. Pass compareTo={asOf:'YYYY-MM-DD'} for the prior-date column. This is the filed statement, so it accepts no alternate grouping.
ParametersasOfrequiredcompareToworkspaceIdrequired
Erfolgsrechnung (income statement) for a period, in the OR Art. 959b Abs. 2 Gesamtkostenverfahren layout: the ten account-backed positions in their prescribed order, each under its statutory wording, plus reingewinnMinor, which is position 11, Jahresgewinn oder Jahresverlust. Unlike the Bilanz this Absatz is a flat list with no sub-level, so all eleven positions are present and in the prescribed order. Two things to say about the eleventh rather than claim: it is the COMPUTED result and not a section of its own, so no account falls into it, and the exported Erfolgsrechnung heads it with the ENACTED wording resolved by sign, Jahresgewinn above zero and Jahresverlust below it, keeping the full Jahresgewinn oder Jahresverlust verbatim at exactly zero. Each single word is the enacted wording with the branch the book did not take dropped, because the oder enumerates the two outcomes a result can have rather than naming one heading. The conventional Treuhand wording Reingewinn oder Reinverlust is not printed. The Bilanz carries the same figure under the same enacted wording as an Eigenkapital position, so the two statements of one Jahresrechnung give one number one name. A RESIDUAL section, `uebrige_positionen`, follows the ten and holds anything that fits none of them, so no account is dropped. It is the "weitere Positionen" of OR Art. 959b Abs. 5, which is a different Absatz and not one of the eleven: it is neither position 11 nor a twelfth prescribed position. Every position is signed as its CONTRIBUTION TO PROFIT (revenue positive, expense negative, and the three positions the statute writes as Aufwand AND Ertrag shown net), so a loss is a negative figure and never an absolute value. This is the verb that answers "wie war der Gewinn in Q2?". Pass compareTo={periodStart,periodEnd} for the prior-period column. The Absatzerfolgsrechnung of OR Art. 959b Abs. 3 is not built, and this is the filed statement, so it accepts no alternate grouping.
ParameterscompareToperiodEndrequiredperiodStartrequiredworkspaceIdrequired
Kontoblatt (general ledger) for ONE account: the opening carry, every posted line in the period in date order with its running balance, and the closing balance. Each line carries the entryId to drill into with get_entry and the entry's Belegnummer (number). Debit-positive like the Saldenbilanz, with naturalSide naming which way the account is expected to lean. Drafts never appear. groupBy accepts 'kmu' today and refuses anything else.
ParametersgroupByaccountIdrequiredperiodEndrequiredperiodStartrequiredworkspaceIdrequired
Render any of the four statements as a LOCAL file and hand back its bytes, base64-encoded: kind one of 'trial', 'balance', 'income', 'ledger', format one of 'csv', 'pdf', plus that statement's own parameters. The CSV is locale-neutral for re-import (integer Rappen, ISO dates, a record_type column carrying the totals) and the PDF is a print artifact with no PDF/A conformance claimed. The model is computed by the same verb the screen calls, so the file and the screen cannot disagree. Nothing is transmitted: e-filing or publishing the artifact is a cloud-tier concern and is not part of this tool.
ParametersasOfkindrequiredformatrequiredgroupByaccountIdcompareToperiodEndperiodStartworkspaceIdrequired
Seed the workspace's opening position as ONE balanced, posted, immutable opening entry (Eröffnungsbilanz), each account carrying exactly one side in integer Rappen. Accounts are named by id or by chart number. If the set does not tie out it is REFUSED with the signed Rappen difference and nothing is written: pass differenceAccount (KMU 9100 Eröffnungsbilanz is the usual one) to book the delta explicitly, because a difference is never plugged silently. asOf defaults to the fiscal-year start. Once the prior year is closed the position is carried from that close and this verb answers carried_forward. An account that already carries a balance on that date is refused with account_already_has_balance, naming what it holds: seeding on top of it would double-count, and a bank opening balance from set_bank_opening_balance is the usual reason. A posted position has no edit path: correct it with a reversing entry (reverse_entry) and a fresh call under a new key, which this verb accepts once the storno has unwound the old position. reference records the Inventar or Beleg the position is traced to, and get_opening_balances reads it back. CONSEQUENCE: Books your opening position as one balanced opening entry for the year. If it is wrong, you correct it with a correcting entry and enter the position again; both stay visible.
ParametersasOflinesrequiredreferencedescriptionworkspaceIdrequiredidempotencyKeyrequireddifferenceAccount
Dry-run already-parsed migration rows into an opening position without writing anything: normalises a signed balance column or a debit/credit pair into integer Rappen, resolves each account number against the chart, and reports the rows the chart does not know (unmapped) alongside the balance check. Takes rows as an array of column-value objects, NOT a CSV string: parsing the export into rows is the caller's step. It refuses the same things import_opening_balances refuses, including an account named twice, so a preview that comes back clean is not followed by a surprise rejection. This reports what the FILE says and whether its own two sides agree; it cannot tell you the file is the right one, so compare the per-account lines against the Beleg. It takes no idempotency key and can never post.
ParametersasOfrowsrequiredformatmappingreferenceworkspaceIdrequireddifferenceAccount
Import already-parsed migration rows as the opening position, posting exactly what preview_opening_import showed. Takes rows as an array of column-value objects, NOT a CSV string: this verb parses no file, and turning an export into rows is the caller's step. Refuses with unmapped_account when any row names an account the chart does not have, because importing the rest would post a position that balances only because a row was dropped. A row with no account at all (what a subtotal or Total line looks like) is refused as invalid_row naming that row, rather than blamed on the mapping. format accepts csv or bexio, which select default column names; mapping overrides them field by field for an export with different headers. Retrying the same idempotencyKey returns the existing entry and never a second opening position. CONSEQUENCE: Books the imported opening position as one balanced entry. If it is wrong, you correct it with a correcting entry; both stay visible.
ParametersasOfrowsrequireddryRunformatmappingreferenceworkspaceIdrequiredidempotencyKeyrequireddifferenceAccount
Read the opening position for a fiscal year: the seeded entry when there is one, or the balance sheet carried from the prior year's close (source=carried_forward, editable=false), or none. Returns each account with its number, name, type and side in Rappen, plus the totals and the reference (the Inventar or Beleg the position is traced to, null when none was given). A position that was reversed reads as source=none, because the ledger no longer holds it. A carried position is derived from the close and is not re-keyable: A03 owns the year-end result posting. If a carried position does not tie out it is REFUSED with carried_position_unbalanced rather than handed on, naming the signed difference and unclosedYears: an unclosed prior year leaves its result on Erfolgsrechnung accounts that a balance sheet does not carry, and every report above this one would be built on the gap.
ParametersyearworkspaceIdrequired
Render exactly what a feedback report would contain, writing nothing. Use it to show a person what would be sent before it is.
ParameterskindlocalemessagerequiredsubjectrequiredclientErrorworkspaceIdrequiredincludeDiagnostics
Write a feedback report to ~/.till/feedback and return a mailto link for it. TILL cannot send: the report is handed to the operator to send from their own mail client. CONSEQUENCE: Writes your feedback report, with diagnostics if you include them, to a file on this machine and returns a mail link for it. TILL sends nothing; once you send it, it cannot be called back.
ParameterskindlocalemessagerequiredsubjectrequiredclientErrorworkspaceIdrequiredidempotencyKeyrequiredincludeDiagnostics
List the feedback reports written on this computer. Every one reads "prepared": TILL hands a report to a mail client and cannot observe whether it was sent.
ParametersworkspaceIdrequired
Read the error-recording preference and every recorded entry: the whole of what TILL has kept about this person, readable at any time with no request to make.
ParametersworkspaceIdrequired
Turn error recording on or off for this computer. Off is the default, and turning it off also deletes what was recorded. Set this only when the person asks for it.
ParameterscapturerequiredworkspaceIdrequired
Delete every recorded error detail. Reports already written are kept.
ParametersworkspaceIdrequired
Report who this session is in a workspace: the actor, the role it holds, and the exact capabilities that role resolves to. The ONE source a client may use to pre-disable a write control. For the governed agent seat it also carries agentDial, the effective approval-dial level per capability (auto executes, ask drafts), so an agent can predict whether a write will post or wait for approval without holding the owner-only get_agent_dial.
ParametersworkspaceIdrequired
List everyone bound to this workspace, pending invites included and labelled as pending (a pending member holds no capability at all).
ParametersworkspaceIdrequired
List every assignable role with its resolved capability bundle and its member count, plus the capability registry itself so a client can render the whole matrix.
ParametersworkspaceIdrequired
Invite someone to this workspace with a role. Writes a pending membership and PREPARES the invite; TILL has no transport and never claims a send, so the token is handed back for the operator to deliver. kind (human, the default, or agent) says what the invitee is: an agent member is the governed seat, its writes draft under the approval dial and its calls land in the trace, on every door including a served one. CONSEQUENCE: Gives a person or an agent access with the chosen role. Whoever redeems the invitation sees the books until you revoke the access; what they saw stays seen.
ParameterskindrolerequiredemailrequireddisplayNameworkspaceIdrequiredidempotencyKeyrequired
Redeem an invite token: bind this session actor to the invited identity and activate the membership. Pre-workspace, because the accepter is not a member yet.
Parameterstokenrequired
Change a member's role. It takes effect on their next call: nothing caches a capability resolution. Demoting the only remaining owner is refused (last_owner). CONSEQUENCE: Changes what this member may see and do, from their next step on. You can change it again at any time.
ParametersrolerequiredmemberIdrequiredworkspaceIdrequired
Remove a member's access to this workspace. The person's identity survives, so re-inviting them restores their history. Revoking the only remaining owner is refused (last_owner). CONSEQUENCE: Removes this member's access from their next step on. What they did stays on record; you can invite them again.
ParametersmemberIdrequiredworkspaceIdrequired
Create a custom role, or reshape one of the three editable built-ins, as a named subset of the capability registry. A name outside the registry is refused (unknown_capability): a role can only ever recombine capabilities that already gate a real verb. CONSEQUENCE: Changes what this role may do, for everyone who holds it. The earlier set of rights is not kept.
ParametersnameroleIdworkspaceIdrequiredcapabilitiesrequiredidempotencyKeyrequired
Soft-flag a custom role so it stops being offered. Never a delete, so historical attributions still resolve, and refused while any member still holds it (role_in_use). CONSEQUENCE: Stops offering this custom role; it is refused while anyone still holds it, and past actions keep their role. You can define a role with the same rights again.
ParametersroleIdrequiredworkspaceIdrequiredidempotencyKeyrequired
Define a typed custom field on any registered entity, or patch an existing one by its key. The key may not shadow a column the entity already has, and once any value is stored the type is frozen (changing it would silently corrupt what is already there). A field defined by the agent actor lands as a draft and is invisible until confirm_field releases it. CONSEQUENCE: Adds or changes a custom field on every record of the chosen kind, for everyone in the workspace. You can archive it later; values already stored are kept.
ParameterskeyrequiredsorttyperequiredoptionsrequiredlabelI18nrequiredentityKindrequiredworkspaceIdrequireddefaultValueidempotencyKey
Release a draft custom field so every screen and every caller can see it: the human half of draft-by-default. Confirming a field that is already live is a successful no-op.
ParametersfieldDefIdrequiredworkspaceIdrequiredidempotencyKey
Archive a custom field so it stops being offered as an input. Never a delete: every value already stored survives and stays readable through list_field_values. Returns how many saved views still name the field, so the caller can warn rather than be surprised later.
ParametersfieldDefIdrequiredworkspaceIdrequiredidempotencyKey
List the custom fields defined on an entity kind, in display order. Archived fields and unconfirmed drafts are excluded unless asked for.
ParametersentityKindrequiredworkspaceIdrequiredincludeDraftsincludeArchived
Set one custom field value on one record, validated against the field type (a money value is an integer Rappen count, a date is ISO-8601, a select value is one of its options). Passing null clears the value. Requires whatever capability editing that entity itself requires, never a G00 capability: a custom field is not a side door.
ParametersvalueentityIdrequiredfieldKeyrequiredentityKindrequiredworkspaceIdrequiredidempotencyKey
Read every custom field value stored on one record, archived fields included and labelled as archived. This is how a retired field's data stays reachable after it stops rendering as an input.
ParametersentityIdrequiredentityKindrequiredworkspaceIdrequired
Save a named filter, sort, column set and layout over an entity list. The view belongs to the calling session unless shared is true, which publishes it to everyone in the workspace and requires manage_saved_views.
ParametersnamerequiredsortlayoutsharedcolumnsfiltersisDefaultentityKindrequiredworkspaceIdrequiredidempotencyKey
Patch a saved view. A personal view may only be changed by the session that owns it; a workspace-shared one, and publishing a personal one, require manage_saved_views.
ParameterspatchrequiredviewIdrequiredworkspaceIdrequiredidempotencyKey
Delete a saved view outright. A true delete rather than an archive, because a view mints no state and holds no history; deleting a shared one requires manage_saved_views.
ParametersviewIdrequiredworkspaceIdrequiredidempotencyKey
List the saved views available for an entity kind: this session's own first, then the workspace-shared ones. Another session's personal views are never returned.
ParametersentityKindrequiredworkspaceIdrequired
Create a document template (invoice, credit_note, quote or dunning_run): footer text per locale, render language (fixed or per contact), an ordered set of OPTIONAL non-legal line-item columns, and an E00 logo file linked via entityKind document_template. Always saved as a NON-default draft: going live is a separate set_default_document_template call a human confirms. Presentation only: the Swiss QR-bill payload, VAT figures and legal content are produced by the document itself and pass through byte-identical under every template.
ParametersnamerequiredfooterI18nfixedLocaleworkspaceIdrequireddocumentKindrequiredlanguageModeidempotencyKeylogoDocumentIdlineItemColumns
Update a template (name, footer, language, optional columns, logo). NEVER changes an already-issued document: issue froze the template content onto the document, so a mailed copy and a later reprint always match; only documents issued after the edit pick it up. CONSEQUENCE: Changes the template for documents issued from now on; documents already issued keep the look they were issued with. You can change it again.
ParameterspatchrequiredtemplateIdrequiredworkspaceIdrequiredidempotencyKey
set_default_document_template
Make a template THE default for its document kind: the prior default clears in the same atomic write (at most one default per kind), and every document of that kind issued afterwards freezes to it. Wide-effect and reviewable: this changes the workspace's outward face. CONSEQUENCE: Makes this template the default for its kind of document, for everything issued from now on; issued documents keep theirs. You can choose another default at any time.
ParameterstemplateIdrequiredworkspaceIdrequireddocumentKindrequiredidempotencyKey
archive_document_template
Soft-archive a template (and clear it as default). NOT destructive: a template frozen onto an already-issued document keeps rendering that document forever; archiving only removes it from the active list and from new defaults.
ParameterstemplateIdrequiredworkspaceIdrequiredidempotencyKey
preview_document_template
Render a template preview as PDF bytes, mutating nothing: against sampleDocumentId, else the most recent real document of the template's kind, else synthetic MUSTER-watermarked sample data that is never a payable document (no fabricated QR code; a missing QR-IBAN surfaces A11's own needs_qr_iban cause).
ParameterstemplateIdrequiredworkspaceIdrequiredsampleDocumentId
List document templates, newest defaults first per kind: id, kind, name, default/archived flags, footer locales, language mode, and the linked logo file id. documentKind narrows to one kind; includeArchived includes archived rows; savedViewId applies a saved view (G00).
ParameterssavedViewIdworkspaceIdrequireddocumentKindincludeArchived
One template with its full configuration: footer text per locale, language mode, fixed locale, optional column order, default/archived flags, and the linked logo file id.
ParameterstemplateIdrequiredworkspaceIdrequired
Speichere den Textbaustein (subject + body) for one document kind (invoice, quote or dunning_run) and locale: the workspace's own outbound message text, with {{variable}} interpolation validated against the kind's registered variable set AT SAVE TIME (an unknown variable is refused with unknown_variable naming the valid set, never a broken mail later). Naturally idempotent: it asserts the absolute state of one (documentKind, locale) slot, and a value-identical re-save writes nothing at all. Sends NOTHING and changes no send behaviour; a missing slot falls back to the built-in default text at preview. CONSEQUENCE: Saves the email text for this kind of document and language; messages sent from now on use it. You can edit it again or reset it to the built-in text.
ParametersbodyrequiredlocalerequiredsubjectrequiredworkspaceIdrequireddocumentKindrequired
Return one Textbaustein slot (documentKind invoice, quote or dunning_run, and locale) to the built-in default text by deleting its saved subject + body; the slot then resolves exactly as one never saved (preview defaulted:true). Naturally idempotent: resetting a slot with no saved text answers ok with unchanged:true and touches nothing. Sends NOTHING, changes no send behaviour and never edits the send log. CONSEQUENCE: Deletes the saved email text for this kind of document and language; messages from now on use the built-in text. To get your text back, it has to be saved again.
ParameterslocalerequiredworkspaceIdrequireddocumentKindrequired
Render the concrete outbound message(s) as a pure read: nothing is sent, nothing is written. documentId (invoice/quote) yields exactly one resolved message; runId (dunning_run) yields one per debtor (narrowable via contactId), each with the recipient, locale, filled variables and attachment list; with neither, the saved or built-in text renders against MUSTER sample values (the editor's preview; locale picks the slot). A recipient without an email carries the owning send verb's own flag (needs_customer_email per A11, needs_email_transport per A15).
ParametersrunIdlocalecontactIddocumentIdworkspaceIdrequireddocumentKindrequired
Das Versand-Protokoll: the cross-document send log, newest first, one row per recipient per send attempt (send_invoice, send_dunning_run, quotes_send), each carrying kind, document/run link, contact, recipient, channel (smtp|cloud_relay|artifact_only), locale, the resolved subject and body that actually left, outcome (sent|degraded|failed|artifact_created) and a degrade reason. Filter by kind, contact, outcome or date range; savedViewId applies a saved view (G00). Also returns texts, the saved Textbausteine slots, so the editor reads its state in the same call. Append-only: no verb can edit or delete a row.
ParameterstofromoutcomecontactIdsavedViewIdworkspaceIdrequireddocumentKind
Define an automation: when this event happens, and this condition holds, call this write verb with this input. The action must name a registered write verb, the trigger must name a registered event, and a rule whose action is the very verb that emits its own trigger is refused outright. A rule created by the agent actor lands DISABLED and a human must enable it. CONSEQUENCE: Creates the automation rule; once enabled, it runs its action in its author's name on every matching event, unattended. You can disable or archive it; what it already did stays done.
ParametersnamerequiredactionrequiredenabledtriggerrequiredconditionworkspaceIdrequiredidempotencyKey
Patch a rule: its name, trigger, condition or action. The patched shape is validated exactly as a new rule is, so an edit can never leave a rule the engine would have refused to create. The change takes effect on the next event; an archived rule refuses. CONSEQUENCE: Changes what the rule reacts to or does, from the next event on; an enabled rule runs the change unattended. You can change it again, but the earlier version is not kept.
ParameterspatchrequiredruleIdrequiredworkspaceIdrequiredidempotencyKey
Let a rule fire again. Requires manage_automations, which is the asymmetry that makes disabling safe to leave open: anyone may stop a rule, only an administrator may start one. An archived rule refuses. CONSEQUENCE: Lets the rule fire again: every matching event then runs its action in its author's name, unattended. You can disable it at any time; what it already did stays done.
ParametersruleIdrequiredworkspaceIdrequired
Stop a rule firing, immediately. Deliberately requires NO capability at all: a stop button that needs a permission is not a stop button, and disabling only ever prevents a write, never causes one.
ParametersruleIdrequiredworkspaceIdrequired
Retire a rule: it stops matching, disappears from the default list, and stops being enable-able. Never a delete, and its run history is untouched, because a firing that happened stays true after the rule that caused it is gone.
ParametersruleIdrequiredworkspaceIdrequired
The tick for schedule triggers: fire every enabled rule whose cadence has come due at asOf, at most ONCE each however far behind it had fallen. Requires manage_automations, because the tick is what makes a schedule rule write unattended. asOf may name a past instant but never a future one: the injected clock decides what is due, not the caller. Safe to call as often as you like: a repeated tick for the same asOf computes the same occurrence key and does nothing. CONSEQUENCE: Runs every enabled automation whose schedule is due, each in its author's name and unattended. What they do can't be undone by TILL; you stop a rule by disabling it.
ParametersasOfworkspaceIdrequired
Finish a run that is stuck in `running`, which is what a process death between the claim and the settle leaves behind. Re-sends the SAME stored input, including the derived idempotency key, so a lost invocation that had in fact committed cannot happen twice. Runs as the actor the firing ran as, so a since-demoted author is refused now exactly as it would be on a fresh firing. Requires manage_automations. A settled run refuses with run_not_stuck. CONSEQUENCE: Finishes an automation run that was cut off, sending its stored step again in the name it ran under. What it does stays done; the same step never runs twice.
ParametersrunIdrequiredworkspaceIdrequiredidempotencyKey
List this workspace automation rules, newest first, archived ones excluded unless asked for. Also returns the CATALOGUE a rule can be built from: every registered trigger event, every write verb that is a legal action, and every condition operator, all read off the live registries so a picker cannot offer something the engine would refuse. savedViewId applies a saved view (G00): its stored filters are merged underneath any filter named explicitly here.
ParameterseventenabledsavedViewIdworkspaceIdrequiredincludeArchived
Read one automation rule: its trigger, its condition, the verb it calls and the input template it calls it with, who authored it (and therefore whose capabilities its firings carry), and when it last fired.
ParametersruleIdrequiredworkspaceIdrequired
The run log, newest first: what fired, when, why, what it actually sent, and what came back. A failed run carries the target verb's own rejection code verbatim, so the reason reads the same way it would on that verb's own screen.
ParameterslimitruleIdstatusworkspaceIdrequired
Read one firing in full, including the resolved action input that was really sent rather than the template it came from.
ParametersrunIdrequiredworkspaceIdrequired
Hard-delete an item that is referenced nowhere (no document line, price-list row, variant, or stock movement). A referenced item is refused with item_referenced and its reference kinds; archive it instead so posted history stays resolvable. CONSEQUENCE: Deletes the item for good; only an item nothing refers to can go. You can create it again, but not restore it.
ParametersitemIdrequiredworkspaceIdrequiredidempotencyKey
Create or edit an item category (two-level tree: the parent of a child must itself be a root). Pass categoryId to edit, omit it to create.
ParametersnamesortparentIdcategoryIdworkspaceIdrequiredidempotencyKey
Delete an item category. Refused (category_in_use) while any item or child category still points at it; reassign or empty it first. CONSEQUENCE: Deletes the item category for good; only one that no item or subcategory points at can go. You can create it again.
ParameterscategoryIdrequiredworkspaceIdrequiredidempotencyKey
List the item categories in the workspace, ordered by sort then name.
ParametersworkspaceIdrequired
Create or edit a price list, scoped to exactly one contact OR one segment (scope_ambiguous otherwise). One scope holds at most one list: a second list for a contact or segment that already has one is refused with scope_taken naming the existing list, so no price is ever resolved by insertion order. Pass priceListId to edit, omit it to create.
ParametersnamesegmentcontactIdpriceListIdworkspaceIdrequiredidempotencyKey
Set a list price for an item from a validFrom date (ISO YYYY-MM-DD; anything else is refused with invalid_input, never coerced). Price history is append-only: this adds a row rather than editing a past one, so a resolve at any date reads a stored integer Rappen amount.
ParametersitemIdrequiredcurrencyvalidFromrequiredpriceMinorrequiredpriceListIdrequiredworkspaceIdrequiredidempotencyKey
List the workspace price lists with their scope (contact or segment).
ParametersworkspaceIdrequired
Read one price list and its price rows (the validFrom history per item).
ParameterspriceListIdrequiredworkspaceIdrequired