# Decide one proposed customer request Source: https://docs.lastaccountingcompany.com/api-reference/accounting/decide-one-proposed-customer-request /openapi.yaml post /accounting/requests/review LAC-only, interactive humans only. `approved` publishes the exact wording as the customer-facing ask, bound by FK to its append-only decision row. `held` keeps the ask internal and `waived` closes it. `revision` must equal the proposal hash from the queue read; a stale hash refuses with 409. Retries reuse the same `submission_id`. # Download an account-by-account general ledger Source: https://docs.lastaccountingcompany.com/api-reference/accounting/download-an-account-by-account-general-ledger /openapi.yaml get /lens/general-ledger.csv Streams every active posted journal line in the selected inclusive month range, ordered by account, date and entry. Reversed originals and their posted reversal twins are both excluded, matching the canonical ledger basis. Each row includes account identity, debit, credit and the reconciled running balance. Accounts present in the canonical ledger with no movements in the selected range have one opening-balance row, including zero balances. The trailing row_kind column distinguishes journal_entry from opening_balance; the existing first 20 columns retain their order. Opening-balance rows have zero debit and credit and blank journal identity, entry date, period, line number, source and VAT code. Their explicit scope_from and scope_through still name the selected range. Opening and closing balances use the same fiscal-opening snapshot basis as `/accounting/gl`; journal facts use the same posted drilldown semantics as `/accounting/journal-entries`. The whole file is built in one repeatable-read snapshot and never creates a chat message or wakes Björn. Explicit month bounds must be served exactly; the export refuses a range outside available books rather than using the interactive ledger pager's clamped range. # Drill from a customer-visible GL account to journal entries Source: https://docs.lastaccountingcompany.com/api-reference/accounting/drill-from-a-customer-visible-gl-account-to-journal-entries /openapi.yaml get /lens/journal-entries Customer-authorized version of the Accounting journal window. Analytics uses the account plus period bounds when an account row opens. # Get one journal entry fully opened Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-one-journal-entry-fully-opened /openapi.yaml get /accounting/journal-entries/{id} Lines with VAT, footed totals, evidence references, linked bank rows, and the entry's own audit facts. # Get the context view Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-context-view /openapi.yaml get /accounting/context LAC-only Active Context, current accountant-owned Open Questions, and their resolved Question History. Customer-owned questions are reviewed in Accounting Requests instead. Björn receives Active Context and all current Open Questions in each session. Question History stays outside the runtime prompt. Every question includes an immutable tenant-local `display_code`, such as `DT1`; its UUID remains the canonical key. Each question may carry `package`, the agent's prepared decision package: `recommendation` (leads), `cause`, `missing`, `options` as `[{option, outcome}]`, and `evidence` as revision-pinned `[{uri, revision, inspect}]` canonical resource references that were validated against the tenant snapshot when the question was raised. Questions raised before the package contract have no `package` field. # Get the customer-request review queue Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-customer-request-review-queue /openapi.yaml get /accounting/requests LAC-only. Proposed customer questions and documentless evidence asks, followed by evidence gaps with no draft, plus recent named-human decisions. Each row carries a `kind` discriminator and a `revision` content hash a decision must bind to. # Get the customer-visible general ledger Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-customer-visible-general-ledger /openapi.yaml get /lens/general-ledger Customer-authorized version of the Accounting GL read model. Returns account opening, debit, credit and closing balances for one month or an inclusive month range. This is the Analytics General ledger tab. # Get the explorer table catalog Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-explorer-table-catalog /openapi.yaml get /accounting/explorer/catalog The allowlisted tables with live row counts; zero-row tables are omitted. # Get the filings strip Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-filings-strip /openapi.yaml get /accounting/filings Current filing drafts as strip chips: kind, period, honest state (open, due, ready, sent), statutory due date where the rule is known, and whether a preview exists. # Get the monthly, custom-range, or all-time general-ledger view Source: https://docs.lastaccountingcompany.com/api-reference/accounting/get-the-monthly-custom-range-or-all-time-general-ledger-view /openapi.yaml get /accounting/gl Per-account opening, debit, credit, and closing over posted entries only. Monthly periods on/after an active fiscal opening snapshot rebase onto it (snapshot base + later movements), exactly like the statements reads. All time uses the snapshot as its opening and sums every movement from that boundary, or starts from zero when there is no snapshot, so its closing matches the latest monthly view. Monthly periods clamp to [first..latest posted]. Kpis are served when the chart is known (FI): cash_cents is the closing cash balance, while revenue_cents and net_income_cents cover the selected movement range (one month or the all-time boundary through the latest period). books_state explains legitimately partial balances (mirror tenants, running history imports). # List journal entries (keyset window) Source: https://docs.lastaccountingcompany.com/api-reference/accounting/list-journal-entries-keyset-window /openapi.yaml get /accounting/journal-entries Newest first with database-side text search (q over description and entry number), account, period, and amount filters. The account and period filters together are the GL drill-through. The first page carries the filtered whole-journal total. # Open one customer-visible journal entry Source: https://docs.lastaccountingcompany.com/api-reference/accounting/open-one-customer-visible-journal-entry /openapi.yaml get /lens/journal-entries/{id} # Preview one filing draft Source: https://docs.lastaccountingcompany.com/api-reference/accounting/preview-one-filing-draft /openapi.yaml get /accounting/filings/{id}/preview Byte-derived from the draft's own stored payload: an opening balance serves a footed account statement; a VAT return serves the same customer summary the Filings page renders (fails closed on a payload it cannot foot); anything else serves no preview, honestly. # Run one read-only SQL statement Source: https://docs.lastaccountingcompany.com/api-reference/accounting/run-one-read-only-sql-statement /openapi.yaml post /accounting/explorer/query One SELECT or WITH statement, run as the least-privilege lac_explorer database role inside a READ ONLY transaction that is always rolled back, with a statement timeout and row/cell caps. Postgres grants are the confidentiality boundary: secret columns are not granted, so any statement touching them is refused by the database. A Postgres error returns verbatim in the error field. If the role is not provisioned the endpoint fails closed with 503. # Create an API key (admin, interactive session only) Source: https://docs.lastaccountingcompany.com/api-reference/api-keys/create-an-api-key-admin-interactive-session-only /openapi.yaml post /api-keys Mints a new portal API key with scope `read` or `write`. The `api_key` secret (`lac_sk_...`) is returned once and never again — store it securely. Requires an interactive admin session; API-key bearers receive 403. # List API keys (admin, interactive session only) Source: https://docs.lastaccountingcompany.com/api-reference/api-keys/list-api-keys-admin-interactive-session-only /openapi.yaml get /api-keys Lists the company's portal API keys (metadata only — the secret is shown once at creation). Requires an interactive admin session; API-key bearers receive 403. # Revoke an API key (admin, interactive session only) Source: https://docs.lastaccountingcompany.com/api-reference/api-keys/revoke-an-api-key-admin-interactive-session-only /openapi.yaml delete /api-keys/{key_id} Revokes a portal API key. Revoked keys are refused immediately. Requires an interactive admin session; API-key bearers receive 403. # Download an account-detailed financial report Source: https://docs.lastaccountingcompany.com/api-reference/books/download-an-account-detailed-financial-report /openapi.yaml get /statements/pdf Streams an account-detailed Finnish statement PDF built live from the same posted-ledger statement read as the portal. The default `bundle` is the Settings/Filings fiscal-YTD "Tilikohtainen tuloslaskelma ja tase" artifact. Analytics sends `income` or `balance` plus its exact served `range`, so the download contains only the active tab: P&L over that range or balance sheet as of its end. Downloads never create a chat message or wake Björn. # Drill into statement lines by account Source: https://docs.lastaccountingcompany.com/api-reference/books/drill-into-statement-lines-by-account /openapi.yaml get /statements/drill Returns the underlying detail behind statement lines for the given GL account codes. `account_codes` is a comma-joined list (e.g. `3000,3010`). Returns JSON `null` when there is nothing to drill into. # Get financial statements Source: https://docs.lastaccountingcompany.com/api-reference/books/get-financial-statements /openapi.yaml get /statements Returns statement read models (income statement, balance sheet, and — where available — cash flow via `statement=cashflow`) for the selected range. Returns JSON `null` when no statement data exists for the selection. # Get ledger analytics Source: https://docs.lastaccountingcompany.com/api-reference/books/get-ledger-analytics /openapi.yaml get /analytics Returns aggregated ledger analytics (trends and signed journal-line expense-account breakdowns) for the selected range, suitable for charting. Amounts are integer cents. # Get the audit history of one exact Books row Source: https://docs.lastaccountingcompany.com/api-reference/books/get-the-audit-history-of-one-exact-books-row /openapi.yaml get /rows/{row_id}/history Returns changes recorded for the canonical resource selected in the Books UI. The path `row_id` is display context only; resource URI and revision own identity. This is an audit read, not a revert surface. # Get the Books or VAT sheet Source: https://docs.lastaccountingcompany.com/api-reference/books/get-the-books-or-vat-sheet /openapi.yaml get /sheet Returns the spreadsheet-style read model over the canonical general ledger: summary cards, column definitions, and rows for the selected tab and range. Amounts inside rows are integer cents. Paginate with `limit`/`offset` (limit 0 = unpaginated, max 200 per page). # Get the customer Transactions timeline Source: https://docs.lastaccountingcompany.com/api-reference/books/get-the-customer-transactions-timeline /openapi.yaml get /activity Returns one server-paged view over settled money movements — history through yesterday (Europe/Helsinki), never today or the future — and, for mirror service, authority-covered financial-account movements outside the current footed import. Full-service books rows are actual bank/card movements only: ledger-only journals (invoices, payroll) are accounting, not movements, and live on their own surfaces. This is an orientation view, not a general-ledger API: movements do not enter GL, VAT, Home metrics, Analytics, close, or filing figures. Use `/sheet?tab=books` or MCP `get_books` for canonical accounting rows. `version=2` is required; the v1 presentation is deleted. Full-service page 0 carries `available_sources` (typed keys: `conn:` per connection, else the transport token) for the `source` filter. # Record an answer about one transaction row Source: https://docs.lastaccountingcompany.com/api-reference/books/record-an-answer-about-one-transaction-row /openapi.yaml post /books/declarations Records what you say about one bank-transaction row: that no receipt exists, that the payment was private, how it splits, or that it belongs in a different place in the books. The declaration is evidence for Björn, never a posting and never an edit: he reads it, acts with his own judgment, and closes it — so the row reads "Reviewing" until he does. Declarations attach to bank-transaction rows only. Journal-entry rows (`je:…`), payslip rows and split constituent rows (`…#L2`) are refused. One open declaration exists per row: a second answer replaces it in place and returns the same declaration id. Requires a write-scoped key. # Get the accounting agent's status Source: https://docs.lastaccountingcompany.com/api-reference/company/get-the-accounting-agents-status /openapi.yaml get /status Returns the current status of Björn, the accounting agent, for this company (e.g. idle/working and progress notes). # Get the authenticated identity Source: https://docs.lastaccountingcompany.com/api-reference/company/get-the-authenticated-identity /openapi.yaml get /me Returns the authenticated principal and the companies it can access. For an API key this is the single pinned company. # Get the company profile Source: https://docs.lastaccountingcompany.com/api-reference/company/get-the-company-profile /openapi.yaml get /company Returns the company's registered details and accounting configuration: fiscal year start month, VAT period length in months, company form, and statement format. `editable` indicates whether the caller could change settings (always false for API keys). # Get the portal overview dashboard Source: https://docs.lastaccountingcompany.com/api-reference/company/get-the-portal-overview-dashboard /openapi.yaml get /overview One-call summary of the company's current state: the active period, headline metrics, items needing attention, filing readiness, connection health, import status, and document intake. # List accessible companies Source: https://docs.lastaccountingcompany.com/api-reference/company/list-accessible-companies /openapi.yaml get /customers Lists the companies (customers) the bearer can act on. API keys always see exactly one. # Update the customer-facing name or company settings Source: https://docs.lastaccountingcompany.com/api-reference/company/update-the-customer-facing-name-or-company-settings /openapi.yaml post /company/settings Changes the customer-facing company name, fiscal year start month, and/or VAT period length. An operator may change `display_name` alone; fiscal/VAT and other statutory settings require an interactive admin or existing broad-approver session. API keys receive 403. `display_name` is the optional trading name used as the primary seller name on outgoing invoices; the legal name and Business ID remain on every issued invoice. `vat_period_valid_from` must be a period-aligned `YYYY-MM-DD` date. # Authorize or upgrade a Fiest restaurant connection Source: https://docs.lastaccountingcompany.com/api-reference/connections/authorize-or-upgrade-a-fiest-restaurant-connection /openapi.yaml post /fiest-connections/oauth/start Starts restaurant-bound PKCE consent. include_orders requests the additional fiest.orders.read scope approved for the Fiest client. Omitting it preserves accounting-only consent. Reauthorizing the same restaurant updates its existing connection after verifying the legal entity. Refreshing an existing token never widens its granted scopes. # Confirm or retract a service-connection step Source: https://docs.lastaccountingcompany.com/api-reference/connections/confirm-or-retract-a-service-connection-step /openapi.yaml post /service-connections/confirmations Confirms (or retracts, via `action: retract`) a pending step in a service-connection setup. Accepted asynchronously. Requires a write-scoped key. # Connect an Adyen merchant account Source: https://docs.lastaccountingcompany.com/api-reference/connections/connect-an-adyen-merchant-account /openapi.yaml post /adyen-connections/api-key Connects one Adyen merchant account with the API key of a Report user that has the Merchant Report Download role. LAC stores a well-formed key server side first, then checks it with Adyen and returns the result as `credential_check`. A key Adyen refuses, or one LAC could not check, is kept on a connection that needs attention: it carries Adyen's own message and claims no merchant account and imports nothing until a recheck verifies it, so fixing the setting in Adyen and calling `revalidateAdyenConnection` is enough; the key is not pasted again. Only a verified key claims the merchant account, and one merchant account belongs to one company. A 202 does not mean the connection is healthy; read `credential_check` and the connection's `status`. Requires a write-scoped key. # Connect PayPal with the company's own PayPal app Source: https://docs.lastaccountingcompany.com/api-reference/connections/connect-paypal-with-the-companys-own-paypal-app /openapi.yaml post /paypal-connections/api-key Connects PayPal with the Client ID and Secret of a Live app the company created in the PayPal Developer Dashboard with its business account, with Transaction search turned on. LAC stores well-formed credentials server side first, then checks them with PayPal and returns the result as `credential_check`. A verified app claims the PayPal account PayPal names for it, and one PayPal account belongs to one company. Credentials PayPal refuses, or that LAC could not check, are kept on a connection that needs attention: it carries PayPal's reason, claims no PayPal account and imports nothing until a recheck verifies it, so fixing the app's setting in PayPal and calling `revalidatePayPalConnection` is enough. A 202 does not mean the connection is healthy; read `credential_check` and the connection's `status`. LAC only reads with the app; the app's own PayPal features decide what else its credentials could do. Requires a write-scoped key. # List a connected Gmail inbox's own labels Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-a-connected-gmail-inboxs-own-labels /openapi.yaml get /inbox-connections/{connection_id}/labels Reads the user-created labels of one connected Gmail inbox through its bound read-only grant, so the customer can choose one as the capture selection. Gmail system categories are not offered. The grant is exchanged once per call and never returned. # List Adyen settlement connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-adyen-settlement-connections /openapi.yaml get /adyen-connections Lists the company's read-only Adyen connections, one per merchant account, with feed health. The feed reads Adyen's Settlement details report for every closed payable batch. # List bank connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-bank-connections /openapi.yaml get /bank-connections Lists the company's bank connections with setup metadata. Establishing a new bank connection uses a browser-interactive consent flow available only in the portal UI. # List Fennoa connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-fennoa-connections /openapi.yaml get /fennoa-connections Lists the company's Fennoa connections with setup metadata. # List Fiest connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-fiest-connections /openapi.yaml get /fiest-connections Lists the company's read-only Fiest restaurant connections and sync health. Establishing or reconnecting a connection uses an interactive OAuth flow in the portal UI. # List Google Sheets connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-google-sheets-connections /openapi.yaml get /gsheet-connections Lists the company's Google Sheets connections with setup metadata. Establishing one uses a browser-interactive OAuth flow available only in the portal UI. # List inbox (email) connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-inbox-email-connections /openapi.yaml get /inbox-connections Lists the company's inbox connections (e.g. Gmail) with setup metadata. Establishing one uses a browser-interactive OAuth flow available only in the portal UI. # List PayPal settlement connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-paypal-settlement-connections /openapi.yaml get /paypal-connections Lists the company's PayPal connections and their feed health: those made with the company's own PayPal app (`auth_type` `paypal_rest_app`, which carry `credential_check` and `recheck_available`) and those made with PayPal partner consent. `setup.available` says whether partner consent can start; `setup.api_key.available` says whether `connectPayPal` accepts an app's credentials. # List Procountor connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-procountor-connections /openapi.yaml get /procountor-connections Lists the company's Procountor connections with setup metadata. # List Stripe connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-stripe-connections /openapi.yaml get /stripe-connections Lists the company's Stripe connections with setup metadata. # List Vipps MobilePay settlement connections Source: https://docs.lastaccountingcompany.com/api-reference/connections/list-vipps-mobilepay-settlement-connections /openapi.yaml get /vipps-mobilepay-connections Lists read-only accounting-partner grants and feed health. # Recheck a stored Adyen key Source: https://docs.lastaccountingcompany.com/api-reference/connections/recheck-a-stored-adyen-key /openapi.yaml post /adyen-connections/{connection_id}/revalidate Checks the stored key of an Adyen connection with Adyen again, after the setting Adyen named has been fixed. On success the connection is connected, a connection that was waiting for verification claims its merchant account, and an import is queued. A refusal is saved on the connection with Adyen's newest message before it is returned. Requires a write-scoped key. # Recheck a stored PayPal app Source: https://docs.lastaccountingcompany.com/api-reference/connections/recheck-a-stored-paypal-app /openapi.yaml post /paypal-connections/{connection_id}/revalidate Checks the stored credentials of a PayPal connection made with the company's own app with PayPal again, after the setting PayPal named has been fixed. On success the connection is connected, a connection that was waiting for verification claims the PayPal account PayPal names for the app, and an import is queued. An app that now opens a different PayPal account from the one its connection claims is refused. A refusal is saved on the connection with PayPal's newest reason before it is returned. Connections made with partner consent are not rechecked here. Requires a write-scoped key. # Request a service connection change Source: https://docs.lastaccountingcompany.com/api-reference/connections/request-a-service-connection-change /openapi.yaml post /service-connections/requests Files an intent about a service connection (e.g. asking LAC to set one up or change it). Accepted asynchronously and dispatched as an event. Requires a write-scoped key. # Start PayPal partner consent Source: https://docs.lastaccountingcompany.com/api-reference/connections/start-paypal-partner-consent /openapi.yaml post /paypal-connections/oauth/start The alternative to `connectPayPal`, and it depends on PayPal approving LAC as a partner: until then it answers 503. Creates one short-lived consent session and returns the PayPal URL that a company admin must open. The callback completes the connection only after PayPal confirms the required read permissions. Requires a write-scoped key. # The records inside one group Source: https://docs.lastaccountingcompany.com/api-reference/connections/the-records-inside-one-group /openapi.yaml get /connections/{connection_id}/data/objects Lists the single records inside one month and one kind of record. Each row carries its date, its name, its amount, and whether it is in your books. Where the source system states named values inside a record, they are listed as facts. The stored source payload is never returned. # Trigger a Fennoa sync Source: https://docs.lastaccountingcompany.com/api-reference/connections/trigger-a-fennoa-sync /openapi.yaml post /fennoa-connections/{connection_id}/sync Pulls data from the Fennoa connection, optionally constrained to a date window or a full backfill. Requires a write-scoped key. # Trigger a Fiest sync Source: https://docs.lastaccountingcompany.com/api-reference/connections/trigger-a-fiest-sync /openapi.yaml post /fiest-connections/{connection_id}/sync Queues a read-only pull for an existing Fiest restaurant connection. Requires a write-scoped key. # Trigger a Procountor sync Source: https://docs.lastaccountingcompany.com/api-reference/connections/trigger-a-procountor-sync /openapi.yaml post /procountor-connections/{connection_id}/sync Pulls data from the Procountor connection, optionally constrained to a date window or a full backfill. Requires a write-scoped key. # Trigger a Stripe sync Source: https://docs.lastaccountingcompany.com/api-reference/connections/trigger-a-stripe-sync /openapi.yaml post /stripe-connections/{connection_id}/sync Pulls data from the Stripe connection, optionally constrained to a date window or a full backfill. Requires a write-scoped key. # Update a Gmail inbox connection Source: https://docs.lastaccountingcompany.com/api-reference/connections/update-a-gmail-inbox-connection /openapi.yaml patch /inbox-connections/{connection_id} Changes the customer-owned facts of one connected Gmail inbox: its display label, a context note, and the capture selection that decides what LAC keeps from the mailbox as accounting evidence. A Google grant alone selects nothing (`capture_status: selection_required`); the selection is made here or carried with the OAuth start, and the server stamps who chose it and when. Requires a write-scoped key or a signed-in company admin. # Verify and activate a Vipps MobilePay accounting grant Source: https://docs.lastaccountingcompany.com/api-reference/connections/verify-and-activate-a-vipps-mobilepay-accounting-grant /openapi.yaml post /vipps-mobilepay-connections/activate Verifies that the company's Business ID has shared at least one ledger with Last Accounting Company, then activates the read-only settlement feed. The company admin grants access in Vipps MobilePay first. Requires a write-scoped key. # What one connection delivered Source: https://docs.lastaccountingcompany.com/api-reference/connections/what-one-connection-delivered /openapi.yaml get /connections/{connection_id}/data Groups everything one connected source delivered by month and by kind of record, and states how much of each group is bound to a journal entry in your books. Months are newest first, up to 36 months. Records that the source sent without a date group under a null month. # List dimension axes, values, and source coverage Source: https://docs.lastaccountingcompany.com/api-reference/dimensions/list-dimension-axes-values-and-source-coverage /openapi.yaml get /dimensions # Attach evidence to one exact Books row Source: https://docs.lastaccountingcompany.com/api-reference/documents/attach-evidence-to-one-exact-books-row /openapi.yaml post /sheet/attachments Stores the original bytes, creates a canonical document association, and wakes Björn only after that association commits. Requires an interactive admin/operator/existing approver (or explicitly confirmed LAC staff write); API keys and connector OAuth tokens are read-only here. `resource_uri` and `resource_revision` are required; derived payslip rows remain read-only until they have a standalone resource owner. # Delete an uploaded file Source: https://docs.lastaccountingcompany.com/api-reference/documents/delete-an-uploaded-file /openapi.yaml delete /uploads/{filename} Deletes one uploaded file. Requires a write-scoped key. # Detach a portal upload from one exact Books row Source: https://docs.lastaccountingcompany.com/api-reference/documents/detach-a-portal-upload-from-one-exact-books-row /openapi.yaml delete /sheet/attachments/{filename} Removes only the row association created by a portal upload; it never deletes the canonical document or ledger evidence. Requires an interactive admin/operator/existing approver (or explicitly confirmed LAC staff write); API keys and connector OAuth tokens are read-only here. `resource_uri` and `resource_revision` are required; derived payslip rows are read-only. # Download evidence from one exact Books row Source: https://docs.lastaccountingcompany.com/api-reference/documents/download-evidence-from-one-exact-books-row /openapi.yaml get /sheet/attachments/{filename} # Download one uploaded file Source: https://docs.lastaccountingcompany.com/api-reference/documents/download-one-uploaded-file /openapi.yaml get /uploads/{filename} Returns the raw bytes of one uploaded file. # Export all uploads as a zip Source: https://docs.lastaccountingcompany.com/api-reference/documents/export-all-uploads-as-a-zip /openapi.yaml get /uploads/export Downloads every uploaded document as a single zip archive. # Get per-file ingest progress Source: https://docs.lastaccountingcompany.com/api-reference/documents/get-per-file-ingest-progress /openapi.yaml get /ingest-status Reports ingest progress for uploaded files — whether each document has been parsed and booked yet. # List evidence attached to one exact Books row Source: https://docs.lastaccountingcompany.com/api-reference/documents/list-evidence-attached-to-one-exact-books-row /openapi.yaml get /sheet/attachments Lists documents linked to the canonical resource snapshot selected in `/sheet` or `/activity`. `row_id` is display context only; the resource URI and revision own identity. The sole unnamed exception is a derived payslip row, whose `je:...:payslip:...` row id is already composed from canonical journal and payslip ids. # List uploaded files Source: https://docs.lastaccountingcompany.com/api-reference/documents/list-uploaded-files /openapi.yaml get /uploads Lists uploaded documents with their metadata. Filter by `kind` (e.g. `receipt`, `invoice`, `contract`). # Render an uploaded JSON invoice as PDF Source: https://docs.lastaccountingcompany.com/api-reference/documents/render-an-uploaded-json-invoice-as-pdf /openapi.yaml get /uploads/{filename}/invoice.pdf Same compiler and promise as the row-attachment preview: a complete invoice PDF or a refusal naming the missing fact. # Render retained image evidence as JPEG Source: https://docs.lastaccountingcompany.com/api-reference/documents/render-retained-image-evidence-as-jpeg /openapi.yaml get /sheet/attachments/{filename}/preview.jpg # Render retained invoice evidence as PDF Source: https://docs.lastaccountingcompany.com/api-reference/documents/render-retained-invoice-evidence-as-pdf /openapi.yaml get /sheet/attachments/{filename}/invoice.pdf Compiles a retained JSON invoice (LAC canonical invoice or a Procountor invoice payload) into a complete invoice PDF: parties, priced rows, the payee IBAN and creditor reference. A payable invoice that does not state those facts, or whose rows do not add up to its totals, is refused with 422 and the missing fact named, never printed incomplete. # Update an uploaded file's metadata Source: https://docs.lastaccountingcompany.com/api-reference/documents/update-an-uploaded-files-metadata /openapi.yaml patch /uploads/{filename} Renames the file's display name and/or attaches a context note for the accounting agent. Requires a write-scoped key. # Upload documents Source: https://docs.lastaccountingcompany.com/api-reference/documents/upload-documents /openapi.yaml post /uploads Uploads receipts, purchase invoices, contracts, or bank statements for ingestion into the books. Multipart form; repeat the `files` part for multiple files (the singular part name `file` is also accepted). Limits: 20 files and 25 MB per request. Requires a write-scoped key. # Read an exact expense claim and its payment state Source: https://docs.lastaccountingcompany.com/api-reference/expenses/read-an-exact-expense-claim-and-its-payment-state /openapi.yaml get /expenses/{claim_id} Interactive admin, approver or claimant session required. A claimant can read only their own claims and receives payment state and timestamps without the company payment batch or transport fields. Uses the same canonical claim and settlement reader as the expense list, independently of its250-record limit. Missing, wrong-company and other-claimant IDs return404. Approval or release does not imply bank settlement. # Download an output package file Source: https://docs.lastaccountingcompany.com/api-reference/filings/download-an-output-package-file /openapi.yaml get /outputs/{output_id}/files/{role} Downloads one file of an output package by role: `excel`, `pdf`, `json`, or `instructions`. Returns raw file bytes with the appropriate content type. # Download one filing archive document Source: https://docs.lastaccountingcompany.com/api-reference/filings/download-one-filing-archive-document /openapi.yaml get /filings/history/document Serves one document named by a record's `documents[].key`. Three kinds exist: a `retained_artifact` is a generated file LAC retained, published by its package manifest's typed `customer_visible` decision; a `submitted_copy` is a readable copy rendered from the exact submitted record, verified against the digest the authority acknowledged; and a `report_rendering` is a summary of a sent Incomes Register report, rendered from the report data retained with LAC's own transmission. It restates what LAC sent and carries no authority-acknowledged digest. Neither rendered kind is the authority's own original document, and both say so. Authorization is resolved again here from the owning filing, so an identity that may not list a payroll filing cannot download one whatever the record key says. # Get one output package Source: https://docs.lastaccountingcompany.com/api-reference/filings/get-one-output-package /openapi.yaml get /outputs/{output_id} Returns a single output package with its metadata and file roles. # Get the filing archive Source: https://docs.lastaccountingcompany.com/api-reference/filings/get-the-filing-archive /openapi.yaml get /filings/history Every filing the company has on record, newest event first: returns LAC transmitted, returns filed in an authority's own service and recorded from their receipt, and returns read back from the authority as already filed. Bounded and paged independently of the review period in `GET /filings`, which only covers the current and previous VAT period. Read authority is company membership plus the payroll role, not the current filing authority: a company whose books moved to its own accountant keeps the record of what LAC filed for it. Incomes Register filings need the admin or approver role and `payroll_scope` says whether they are included. A `200` always means the canonical read succeeded, so an empty `records` list means the company has no filings; a failed read is `503`. Optional enrichments degrade independently through `documents_status` and `confirmations_status`. # Get the filing state Source: https://docs.lastaccountingcompany.com/api-reference/filings/get-the-filing-state /openapi.yaml get /filings Returns the filing state for a period (default `this_month`): the resolved period, the VAT preview, filing drafts, filed returns, produced output packages, the latest review request, and the standing authorization state. Amounts are integer cents. # List output packages Source: https://docs.lastaccountingcompany.com/api-reference/filings/list-output-packages /openapi.yaml get /outputs Lists produced output packages (e.g. VAT return drafts, close reports) with their available file roles. # Read the next assigned VAT return and its exact draft Source: https://docs.lastaccountingcompany.com/api-reference/filings/read-the-next-assigned-vat-return-and-its-exact-draft /openapi.yaml get /filings/upcoming Active full customers with LAC books and an assigned VAT responsibility see the earliest assigned unfiled obligation, retained after its deadline until its exact production filing completes. Cadence, takeover, statutory due dates and completed production returns are canonical. Preview reads saved statutory amounts, current supporting entries and readiness. Unprepared periods show a live books draft. Reads never approve, file or request agent work. Approval uses the named-human filing.approve_and_file operation and its signed preview. # Request a filing review Source: https://docs.lastaccountingcompany.com/api-reference/filings/request-a-filing-review /openapi.yaml post /filings/review-requests Asks the accounting agent to review the books and prepare filings for the given range (default `this_month`). Accepted asynchronously — the work is dispatched as an event. Requires a write-scoped key. # Set filing authorization Source: https://docs.lastaccountingcompany.com/api-reference/filings/set-filing-authorization /openapi.yaml post /filings/authorization Grants or revokes LAC's standing authorization to submit filings on the company's behalf. Requires a write-scoped key. # Download an import run's raw package Source: https://docs.lastaccountingcompany.com/api-reference/imports/download-an-import-runs-raw-package /openapi.yaml get /import-runs/{run_id}/raw-package Downloads the raw source package that was imported, as file bytes. # Get an import run Source: https://docs.lastaccountingcompany.com/api-reference/imports/get-an-import-run /openapi.yaml get /imports/{run_id} Returns one import run with its artifacts. # List import runs Source: https://docs.lastaccountingcompany.com/api-reference/imports/list-import-runs /openapi.yaml get /imports Lists historical import runs (e.g. books migrated from a previous accounting system) with their statuses. # API reference Source: https://docs.lastaccountingcompany.com/api-reference/index Conventions, authentication, and boundaries for the LAC customer REST API. The LAC portal API, endpoint by endpoint. Every endpoint is documented from the machine-readable source of truth, [openapi.yaml](https://docs.lastaccountingcompany.com/openapi.yaml) — browse them in the sidebar. New here? Start with [getting started](/). ## Conventions **Base URL**: `https://api.app.lastaccountingcompany.com/portal` * **Auth**: `Authorization: Bearer lac_sk_...` on every request. Keys are created in the portal (Settings → API access) and carry a `read` or `write` scope. All `GET` endpoints need `read` and all mutations need `write` — except payroll, where **every** endpoint (reads included) is **not for API keys**; those and a few other endpoints return `403` because they need an interactive admin or approver in the portal. * **JSON** in and out, `snake_case` fields. * **Amounts** are integer cents. **Rates** are basis points (`2550` = 25.5%). **Periods** are `YYYY-MM`. * **Ranges**: `YYYY-MM` | `YYYY-Qn` | `YYYY` | `all` | `this_month` | `last_6_months`. * **`customer_id`** is an optional parameter everywhere — API keys are pinned to one company, so you can omit it. * **Errors**: non-2xx status with a body of `{"error": "...", "detail": "..."}` (`401` missing/invalid token, `403` insufficient scope or role, `404` not found, `422` validation failure). ## Limits * Document uploads: at most **20 files** and **25 MB** per request. * Sheet pagination: `limit` is capped at **200** rows per page. ## Not for API keys Some endpoint families serve the portal UI and require an interactive admin or approver session (Firebase token); API keys receive `403`: * **Payroll** — every payroll endpoint, reads included. * **Company settings** — `POST /company/settings`. * **Invoice approval decisions** — `POST /invoices/{invoice_id}/approve` and `/reject`. * **API key management** — `GET/POST /api-keys`, `DELETE /api-keys/{key_id}`. A key can never mint or revoke keys. API keys are company credentials, not personal ones — they keep working if the person who created them leaves. Revoke or rotate keys in Settings → API access when an admin departs. # Approve a draft invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/approve-a-draft-invoice /openapi.yaml post /invoices/{invoice_id}/approve Records an approver's decision to let a draft be issued, and pins it to the invoice exactly as written: change any part of the invoice afterwards and the approval stops applying, so it has to be approved again. One approval issues one invoice. **Not available to API keys.** Approving is the human gate on issuing an invoice, so it requires an interactive person with the `sales_invoice.approve` capability. The creator and requester cannot decide the request. API keys may ask for approval (`POST /invoices/{invoice_id}/request-approval`) and read the state, and the same asymmetry holds over MCP. # Approve a purchase invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/approve-a-purchase-invoice /openapi.yaml post /purchase-bills/{bill_id}/approve Accepts or returns the current purchase review revision. Accounting-only coding does not invalidate a decision. Accepted approval requires delivery verification on the same revision only when the company uses Verify and approve. Requires `purchase_bill.approve`. A return needs a reason. # Ask Björn to prefill a draft from a document Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/ask-björn-to-prefill-a-draft-from-a-document /openapi.yaml post /invoices/{invoice_id}/prefill Uploads one contract or old invoice against an invoice draft. Björn reads it and fills only the draft fields that are still empty — nothing you typed is overwritten, and nothing is sent. Multipart form with one `files` part. Requires a write-scoped key. # Ask for approval of a draft invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/ask-for-approval-of-a-draft-invoice /openapi.yaml post /invoices/{invoice_id}/request-approval For a company whose `invoice_approval_policy` is `required`, puts a draft in front of its approvers and emails them. The draft's `approval_status` becomes `awaiting`, and it cannot be sent or finalized until somebody approves it. Refused with 409 when the company does not require approval (nothing is waiting for) or when the draft is already approved. Requires a write-scoped key. # Attach a missing original to an imported purchase invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/attach-a-missing-original-to-an-imported-purchase-invoice /openapi.yaml post /purchase-bills/{bill_id}/original Repairs a legacy purchase invoice that predates retained evidence. The exact bytes are retained and bound to the bill before the upload event is published. The new evidence changes the review/payment revision, so prior decisions and frozen payments cannot be reused. # Confirm delivery for a purchase invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/confirm-delivery-for-a-purchase-invoice /openapi.yaml post /purchase-bills/{bill_id}/verify Records whether the goods or services on the current purchase review revision were received. The review revision covers commercial, source, supplier, and payment facts but excludes later accounting coding. Requires an interactive person with `purchase_bill.verify`. A return needs a reason. Repeating the same idempotency key and decision is safe. Available only when the company uses delivery confirmation and approval. # Create a partner seller profile Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/create-a-partner-seller-profile /openapi.yaml post /seller-profiles Creates a partner profile. A write-scoped API/OAuth credential or an interactive operator can create a draft. Only an interactive company admin can create an active profile. Activation requires a signed mandate reference, KYC reference, bookkeeping-copy email, complete seller address, valid partner IBAN, a business ID different from the tenant, and an IBAN that the tenant does not own. # Create or update a recurring invoice template Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/create-or-update-a-recurring-invoice-template /openapi.yaml post /invoice-recurring Creates a recurring invoice template (or updates one via `template_id`). `cadence_months` is the integer count of steps between issues and `cadence_unit` says what it counts — weeks (1–52) or months (1–24, the default); `draft` carries the same shape as the invoice-draft input (integer cents, basis points, decimal-string quantities). Requires a write-scoped key. # Create or update an invoice customer Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/create-or-update-an-invoice-customer /openapi.yaml post /invoice-customers Upserts a party in the invoicing counterparty register. Include `id` to update an existing party. Requires a write-scoped key. # Create or update an invoice draft Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/create-or-update-an-invoice-draft /openapi.yaml post /invoices Creates a sales-invoice draft (or updates an existing one via `draft_id`). Set `seller_profile_id` to issue for an active partner seller. The partner becomes the legal seller and payee, and the sale does not post to this company's ledger. Monetary fields are integer cents; VAT rates are basis points (25.5% = 2550); line quantities are decimal strings. Delivery channel is one of `maventa_einvoice` (sent over the e-invoice network) or `pdf_download` (finalized as a PDF you deliver yourself). Requires a write-scoped key. # Credit and replace an issued invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/credit-and-replace-an-issued-invoice /openapi.yaml post /invoices/{invoice_id}/credit-note Creates a separately numbered full credit note and an unsent editable replacement draft. A queued e-invoice with no provider attempt is cancelled before transmission: its queue evidence becomes terminal and its credit note stays internal. A finalized PDF credit is not transmitted. An accepted e-invoice credit uses the original Maventa connection. The original and credit note remain in history. Supported for own-name invoices before any earlier credit. Replay-safe per original invoice. Requires a write-scoped key. # Delete an invoice draft Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/delete-an-invoice-draft /openapi.yaml delete /invoices/{invoice_id} Permanently deletes an unnumbered sales-invoice draft. Issued invoices and credit notes are retained and cannot use this route. Requires a write-scoped key. # Download the invoice as Finvoice XML Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/download-the-invoice-as-finvoice-xml /openapi.yaml get /invoices/{invoice_id}/finvoice Returns the invoice rendered as a Finvoice XML document. # Download the invoice as PDF Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/download-the-invoice-as-pdf /openapi.yaml get /invoices/{invoice_id}/pdf Returns the exact issued PDF retained as accounting evidence. LAC verifies the stored bytes against their SHA-256 before returning them. `ETag` and `X-Content-SHA256` contain that hash. A true draft is refused with 409; edit it, then send or finalize it first. # Download the original purchase invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/download-the-original-purchase-invoice /openapi.yaml get /purchase-bills/{bill_id}/original # Draft the next invoice from a template Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/draft-the-next-invoice-from-a-template /openapi.yaml post /invoice-recurring/{template_id}/draft-next Materializes the template's next occurrence as an invoice draft, optionally overriding the issue date. Requires a write-scoped key. # Finalize a PDF invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/finalize-a-pdf-invoice /openapi.yaml post /invoices/{invoice_id}/finalize Issues a `pdf_download` draft without transmitting it: allocates the real invoice number, stores the invoice, books the sale when LAC keeps the ledger, and stamps the payment reference. The invoice then enters receivables and `GET /invoices/{invoice_id}/pdf` returns the finished invoice. Delivering it to the buyer is the company's own step — finalizing sends nothing. The call is idempotent: finalizing an already-finalized draft returns the same invoice without allocating a second number, and a refusal allocates none. Drafts on the e-invoice channel are refused with 409 — send those instead. A company whose incumbent accounting firm still keeps its books cannot finalize at all: that refusal is also a 409, and `capabilities.can_finalize_pdf` on `GET /invoices` states it in advance. Requires a write-scoped key. # Get an invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/get-an-invoice /openapi.yaml get /invoices/{invoice_id} Returns the full detail of one invoice or draft, amounts in integer cents. # List invoice customers Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/list-invoice-customers /openapi.yaml get /invoice-customers Lists the invoicing counterparty register — the parties you invoice, with their e-invoice addresses and per-party defaults. # List partner seller profiles Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/list-partner-seller-profiles /openapi.yaml get /seller-profiles Lists the partner companies this tenant may invoice for. Use an active profile's `id` as `seller_profile_id` on a draft. The response includes bank and evidence references, so it requires a write-scoped key. # List recurring invoice templates Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/list-recurring-invoice-templates /openapi.yaml get /invoice-recurring Lists recurring invoice templates with their cadence and next issue date. # List sales invoices Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/list-sales-invoices /openapi.yaml get /invoices Lists the company's sales invoices and drafts with their statuses. # Open a purchase invoice as PDF Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/open-a-purchase-invoice-as-pdf /openapi.yaml get /purchase-bills/{bill_id}/pdf Returns a human-readable purchase invoice PDF. A retained provider PDF is returned unchanged when available. Otherwise the retained Finvoice is rendered through LAC's canonical invoice layout; the canonical bill is the final fallback, so raw XML is never required for review. # Open purchase invoice evidence Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/open-purchase-invoice-evidence /openapi.yaml get /purchase-bills/{bill_id}/evidence/{document_id} # Read the current original review and accounting calculation Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/read-the-current-original-review-and-accounting-calculation /openapi.yaml get /purchase-bills/{bill_id}/original-review Returns the bill, exact selected original, bill-specific review, current journal calculation and posting history from one read-only snapshot. Customer purchase-invoice roles may inspect it; staff may inspect it within the selected customer workspace. Role eligibility describes actions available after explicit staff confirmation. It grants no write authority. Review and journal posting use the canonical operation plane with their own preview, execute and status requests. Neither action constitutes customer payment approval or bank settlement. # Read the exact current bill correction form Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/read-the-exact-current-bill-correction-form /openapi.yaml get /purchase-bills/entry Read-only current bill facts, canonical revision, active expense categories and registry tax choices for an interactive company admin/operator or selected staff actor. Correction uses purchase_bill.record with its own exact preview, execution and receipt. Customer creation, posting, approval and payment are not granted by this form. Posted and settled bills remain visible with a correction refusal. No input is saved by this read. # Request a payment reminder Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/request-a-payment-reminder /openapi.yaml post /invoices/{invoice_id}/reminder Requests a payment reminder for an unpaid invoice. Accepted asynchronously. Pass `idempotency_key` to make retries safe. Requires a write-scoped key. # Retry an ambiguous partner invoice copy Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/retry-an-ambiguous-partner-invoice-copy /openapi.yaml post /invoices/{invoice_id}/retry-partner-copy Sends a new bookkeeping PDF copy only after the caller verified that the partner did not receive the uncertain earlier attempt. The required reason, actor, time, numbered attempt and new email-provider key are stored before sending. Only `partner_copy_status=ambiguous` is accepted. Requires a write-scoped key. # Retry sending an invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/retry-sending-an-invoice /openapi.yaml post /invoices/{invoice_id}/retry-send Retries delivery of an invoice whose previous send attempt failed. Safe pre-acceptance failures (delivery_status `send_retryable`) retry as-is. Provider-terminal failures (`failed`, `send_failed`) require a non-empty `reason` recorded in the audit trail — correct the recipient's e-invoice address and operator first; the resend creates a new e-invoice and the failed one stays on record. `send_ambiguous` sends are refused (409) until the outcome is verified with the operator. Requires a write-scoped key. # Search e-invoice recipients Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/search-e-invoice-recipients /openapi.yaml get /invoice-receivers Searches the active Maventa directory by recipient name, Finnish business ID, or FI VAT ID. Copy the returned OVT/e-invoice address and operator to the invoice customer. No receiver record is created. This is a live provider read for Finnish recipients. # Send a draft invoice back Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/send-a-draft-invoice-back /openapi.yaml post /invoices/{invoice_id}/reject Records an approver's decision not to let a draft be issued. `reason` is required: the person who wrote the invoice sees it and can change the invoice and ask again. The draft stays editable and no approval is written, so it simply cannot be issued. **Not available to API keys**, for the same reason as `POST /invoices/{invoice_id}/approve`. # Send an e-invoice Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/send-an-e-invoice /openapi.yaml post /invoices/{invoice_id}/send Issues a `maventa_einvoice` draft and transmits it over the e-invoice network: allocates the invoice number, stores the invoice, books the sale when LAC keeps the ledger, and queues the Finvoice send. For a partner-profile draft, the tenant's Maventa connection is only the material-handler transport: the partner stays the Finvoice seller and payment beneficiary, receives a bookkeeping PDF copy, and the invoice has no tenant ledger effect. The e-invoice network is the only buyer-delivery channel LAC transmits on. A partner-profile send also emails its seller a bookkeeping copy. Drafts on any other channel are refused with 409; `pdf_download` drafts are issued through `POST /invoices/{invoice_id}/finalize` instead. Requires a write-scoped key. # Update a partner seller profile Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/update-a-partner-seller-profile /openapi.yaml patch /seller-profiles/{profile_id} Partially updates one profile. A write-scoped API/OAuth credential or an interactive operator can update a draft. Only an interactive company admin can activate a draft, pause an active profile, or change any active profile. The admin must review the mandate, KYC, bookkeeping-copy email, address, and partner payment account before activation. # Update a recurring template's status or schedule Source: https://docs.lastaccountingcompany.com/api-reference/invoicing/update-a-recurring-templates-status-or-schedule /openapi.yaml patch /invoice-recurring/{template_id} Partially updates a recurring invoice template — rename it, pause/resume/ archive it, or change its cadence and next issue date. Requires a write-scoped key. # Get data coverage per real source Source: https://docs.lastaccountingcompany.com/api-reference/lens/get-data-coverage-per-real-source /openapi.yaml get /lens/data-coverage One entry per real source: identity (institution, never the pipe), live state, the scheduled/on-demand mode, last sync or last use, the covered window, declared gaps, and landed row counts (commerce rows counted by their active generation's source label). Real customers never receive test-environment connections. document_blockers contains only fixed, redacted codes and counts; provider messages, filenames, and document contents are never returned. # Get how one row was booked Source: https://docs.lastaccountingcompany.com/api-reference/lens/get-how-one-row-was-booked /openapi.yaml get /lens/booking The exact stable journal lines behind one transactions-window row (account, name, debit, credit, VAT, dimensions, footed totals) plus its evidence documents. Document bytes are served by the existing attachment and upload endpoints; this read returns references only. The server-authored resource URI and revision own identity; `row_id` is display context. Omit the resource pair only for a derived payslip row. # Get the add-source catalog Source: https://docs.lastaccountingcompany.com/api-reference/lens/get-the-add-source-catalog /openapi.yaml get /lens/connections-catalog What is connected (resolved identities) and the full addable-source tile set, with brand keys matching the shipped brand assets and the honest connect path (one_click or assisted) per tile. # Get the transactions window Source: https://docs.lastaccountingcompany.com/api-reference/lens/get-the-transactions-window /openapi.yaml get /lens/transactions One keyset-paged window over the full transaction row universe: bank rows, ledger-only entries (sales summaries, imported history, manual entries), and payslip rows. needs_receipt means an OPEN customer ask (missing, requested, or inadequate) — evidence already in hand and under review does not count. Status, date range, open-periods scope, and the dimension filter all run in the database; the first (un-cursored) page carries whole-history totals and, under status=needs_receipt, the this-week/older buckets. # Download one retained file referenced by chat Source: https://docs.lastaccountingcompany.com/api-reference/messages/download-one-retained-file-referenced-by-chat /openapi.yaml get /chat-artifacts/{document_id} Returns retained bytes only when the exact document and SHA-256 are referenced by a visible human chat message or committed on a terminal Björn receipt. A document row, hidden transport, unauthorized internal message, or another tenant's reference is never sufficient authority. # List chat messages Source: https://docs.lastaccountingcompany.com/api-reference/messages/list-chat-messages /openapi.yaml get /messages Returns one tenant-scoped conversation with Björn. The customer channel is available to company members and LAC; internal requires LAC staff. # Send a message to the accounting agent Source: https://docs.lastaccountingcompany.com/api-reference/messages/send-a-message-to-the-accounting-agent /openapi.yaml post /messages Posts to one Björn conversation. Customer is shared with company members; internal requires LAC staff. The returned `event_id` identifies the durable dispatch. Requires a write-scoped key. # Confirm the current source inventory Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/confirm-the-current-source-inventory /openapi.yaml post /onboarding/journey/source-confirmation Appends a confirmation bound to the fingerprint of the current source set. # Get the saved company verification submission Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/get-the-saved-company-verification-submission /openapi.yaml get /onboarding/kyc Returns uploaded document metadata and the customer's answers. Upload and submission are intake facts; LAC reviews the evidence separately. A missing extracted expiry date does not mean a document has expired. Original identity documents and internal screening results are not included. # Get the saved onboarding journey Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/get-the-saved-onboarding-journey /openapi.yaml get /onboarding/journey Returns canonical answers, sources, opening statements, the first missing step, and the current platform-access decision. Completion is derived from facts; no mutable step counter exists. # Get the workspace release decision Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/get-the-workspace-release-decision /openapi.yaml get /platform-access Returns the tenant-scoped platform-access decision without loading the full onboarding read model. Product clients use this as their boot gate. # Replace the source inventory Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/replace-the-source-inventory /openapi.yaml put /onboarding/journey/sources Reconciles the complete current source set. Accounting systems, payroll, and e-invoicing are separate answers and are not source kinds. Any change invalidates the prior source confirmation by fingerprint. # Save one onboarding answer Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/save-one-onboarding-answer /openapi.yaml put /onboarding/journey/answers/{key} Idempotently saves or skips one supported answer and retains earlier versions. # Submit documents and continue onboarding Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/submit-documents-and-continue-onboarding /openapi.yaml post /onboarding/kyc/submit Records customer intake while LAC verification remains pending. Requires a trade register extract and the passports matching the declared ownership. A first business description also supplies the business_activity profile answer, without replacing a current answer or explicit skip. Identical retries preserve the submission timestamp; changed verification answers start a new review cycle. Submission does not grant platform access. # Upload an onboarding statement Source: https://docs.lastaccountingcompany.com/api-reference/onboarding/upload-an-onboarding-statement /openapi.yaml post /onboarding/journey/statements/{kind} Atomically records the uploaded document and its typed balance-sheet or income-statement fact before Björn receives the document event. The reporting period is extracted asynchronously from the retained file and is never required from the caller. # Configure the company paying account and accept current Open Payments terms Source: https://docs.lastaccountingcompany.com/api-reference/payments/configure-the-company-paying-account-and-accept-current-open-payments-terms /openapi.yaml patch /payment-settings Customer-admin only. The IBAN is validated against the selected bank, that bank must prove live Open Payments SEPA readiness, and the current terms acceptance is recorded atomically with the paying account. # Everything the company can pay, is paying, or has paid Source: https://docs.lastaccountingcompany.com/api-reference/payments/everything-the-company-can-pay-is-paying-or-has-paid /openapi.yaml get /payments The one Payments view. Ready rows are the same locked readiness contracts prepare resolves, read at their current revision: reviewed purchase invoices with a valid IBAN and reference, approved payroll runs with their net salaries and Vero obligation, and approved reimbursements. Sources held by a live batch appear under that batch, never in the queue. Waiting rows name why an item is not payable yet. Batches are every live batch (not cancelled, not settled) plus the newest 50 batches settled within the last 90 days, newest first. Operators see purchase invoices only. # Get one exact contextual payment source and its active batch Source: https://docs.lastaccountingcompany.com/api-reference/payments/get-one-exact-contextual-payment-source-and-its-active-batch /openapi.yaml get /payment-sources/{kind}/{source_id} Source-scoped and non-enumerable. Payroll and reimbursement privacy is enforced before any batch amount, recipient, or IBAN is returned. # Get the native Open Payments setup and supported Finnish banks Source: https://docs.lastaccountingcompany.com/api-reference/payments/get-the-native-open-payments-setup-and-supported-finnish-banks /openapi.yaml get /payment-settings # Grant or revoke explicit payment release authority Source: https://docs.lastaccountingcompany.com/api-reference/payments/grant-or-revoke-explicit-payment-release-authority /openapi.yaml patch /payment-settings/release-authority # List explicit named-member payment release authority Source: https://docs.lastaccountingcompany.com/api-reference/payments/list-explicit-named-member-payment-release-authority /openapi.yaml get /payment-settings/release-authority Admin-only. No role, including admin, implies this capability. # Move the paying account's Nordea Business connection forward Source: https://docs.lastaccountingcompany.com/api-reference/payments/move-the-paying-accounts-nordea-business-connection-forward /openapi.yaml post /payment-settings/bank-connection Open Payments reaches a Nordea Business account only after the company has applied for Corporate Access Lite inside Nordea Business and Nordea has activated it. A signed-in company admin declares the application (`application_submitted`). A company admin or LAC staff asks Open Payments about the paying account now (`observe`): the provider lists the company's accounts with their statement-enrichment time, LAC records the observation, and current evidence about the current paying account (listed, enabled, a statement enrichment dated after the declaration and at most 14 days old) activates the connection with a machine-verifiable evidence reference; evidence from before the current declaration never activates, so a reset connection cannot re-activate from old statements; LAC also runs this read once a day on a settings read while the application is pending. A signed-in LAC staff member, under the staff customer-write confirmation headers, may record Nordea's activation from the customer's forwarded activation letter (`active`): the letter is one of the customer's retained uploads (`evidence_document_id` with its `evidence_sha256`, a PDF or an image under an approved archive prefix), `letter_account_iban` is the payment account it names and must be the paying account, and `agreement_id` is the bank's agreement identifier printed on it. The recorded evidence names the document and its digest; a typed note (`evidence_ref`) is refused. The same record is reachable for agents as the operation `payments.bank_connection.activate@1`. Only an active connection lets the database derive `delivery_enabled`; every release still proves live provider readiness. `expected_row_version` pins the paying account version the caller saw. A changed paying IBAN returns the connection to `not_started`. # Open the exact retained Open Payments terms document Source: https://docs.lastaccountingcompany.com/api-reference/payments/open-the-exact-retained-open-payments-terms-document /openapi.yaml get /payment-settings/terms Customer-admin only. Serves the immutable GCS object generation whose SHA-256 and identity are recorded with the administrator's acceptance. # Poll an already submitted direct payment Source: https://docs.lastaccountingcompany.com/api-reference/payments/poll-an-already-submitted-direct-payment /openapi.yaml post /payment-batches/{batch_id}/poll Persists an explicitly authorized recovery intent before read-only provider I/O. # Read one exact payment batch including older settled history Source: https://docs.lastaccountingcompany.com/api-reference/payments/read-one-exact-payment-batch-including-older-settled-history /openapi.yaml get /payment-batches/{batch_id} Requires access to every source in the batch. Operators can inspect purchase payments; payroll and reimbursements require an admin or approver. Missing, cancelled and forbidden-source records return 404. Release and recovery capabilities retain their named-member authority. # Release one exact immutable source-bound payment batch Source: https://docs.lastaccountingcompany.com/api-reference/payments/release-one-exact-immutable-source-bound-payment-batch /openapi.yaml post /payment-batches/{batch_id}/release Requires explicit payment_batch.release plus authority to review every source. The server revalidates the source revision and effective global transport before atomically recording the first irreversible marker. # Resolve one ambiguous direct submission from bank evidence Source: https://docs.lastaccountingcompany.com/api-reference/payments/resolve-one-ambiguous-direct-submission-from-bank-evidence /openapi.yaml post /payment-batches/{batch_id}/resolve Persists an explicitly authorized recovery intent before provider recovery I/O. # Start hosted Open Payments company verification Source: https://docs.lastaccountingcompany.com/api-reference/payments/start-hosted-open-payments-company-verification /openapi.yaml post /payment-settings/verification Customer-admin only. Returns one short-lived, HTTPS Open Payments URL whenever provider verification is not yet Valid: first start, a closed or abandoned hosted tab (`started`), a start whose hosted link never reached LAC (`unconfirmed`), or an expired link (`retry`). Open Payments issues a fresh hosted link on every create, so restarting is always safe. Each start records an append-only cycle boundary before the provider call; exactly one restart exists per prior attempt. The URL is never persisted. Replaying the same `idempotency_key` returns the already-recorded opened, definite-failure, or ambiguous result without another provider call. A new hosted flow requires a new key. # Add an employee Source: https://docs.lastaccountingcompany.com/api-reference/payroll/add-an-employee /openapi.yaml post /payroll/employees NOT available to API keys — requires an interactive admin or existing approver session. Adds an employee to payroll. Salary and rate fields are integer cents; withholding/pension rates are basis points (10000 = 100%). # Approve a payroll run Source: https://docs.lastaccountingcompany.com/api-reference/payroll/approve-a-payroll-run /openapi.yaml post /payroll/approve NOT available to API keys — requires an interactive admin or existing approver session. Approves a drafted payroll run for payment and reporting. API keys (even write-scoped ones) receive 403. # Confirm an imported bank payment against an approved payroll Source: https://docs.lastaccountingcompany.com/api-reference/payroll/confirm-an-imported-bank-payment-against-an-approved-payroll /openapi.yaml post /payroll/payment-confirm Interactive admin or approver only. Revalidates the exact review revision against current payroll, bank and cash-account facts, then records the existing payment in Books. It does not initiate a transfer. An active payment batch retains settlement ownership. The same exact live bank confirmation can be retried after a lost response without another posting. Historical adoption, external payer evidence and loan setoff use registered accounting operations with their separate authority gates. # Correct an approved payroll run's payday before payment Source: https://docs.lastaccountingcompany.com/api-reference/payroll/correct-an-approved-payroll-runs-payday-before-payment /openapi.yaml post /payroll/payment-date Interactive admin or approver only. Rebuilds the approved run and its unapproved Incomes Register draft at the true payday, preserving the figures and append-only ledger evidence. Fails closed after payment, reporting, or other downstream authorisation, and when the new payday changes the payment month. # Download a sent Incomes Register report Source: https://docs.lastaccountingcompany.com/api-reference/payroll/download-a-sent-incomes-register-report /openapi.yaml get /payroll/report/pdf Renders one sent Incomes Register report (income report or employer's separate report) as a PDF from the stored report facts and its production delivery receipt. Available only after the report was sent. # Download an approved payslip Source: https://docs.lastaccountingcompany.com/api-reference/payroll/download-an-approved-payslip /openapi.yaml get /payroll/payslip/pdf NOT available to API keys — requires an interactive admin or existing approver session. Returns a PDF only after the payroll run is approved and its payroll voucher is posted. # Download an employee's finalized payroll files Source: https://docs.lastaccountingcompany.com/api-reference/payroll/download-an-employees-finalized-payroll-files /openapi.yaml get /payroll/export NOT available to API keys — requires an interactive admin or existing approver session. Returns one ZIP with every finalized, posted payslip for the employee plus exact payroll-summary and earning-line CSV files. Personal tax identifiers and bank details are excluded. # Download the employer calculation of an approved payroll Source: https://docs.lastaccountingcompany.com/api-reference/payroll/download-the-employer-calculation-of-an-approved-payroll /openapi.yaml get /payroll/employer-calculation/pdf NOT available to API keys — requires an interactive admin or existing approver session. The employer's side of one payroll run — every pay item, every employer cost with its rate, and the total employment cost — as a PDF. Available only after the payroll run is approved and its payroll voucher is posted. # Draft a payroll run Source: https://docs.lastaccountingcompany.com/api-reference/payroll/draft-a-payroll-run /openapi.yaml post /payroll/draft NOT available to API keys — requires an interactive admin or existing approver session. Computes a draft payroll run for the period from current employees, tax cards, and employer settings. Drafting does not pay anyone — a separate approval is required. Pass `idempotency_key` to make retries safe. # Fetch an employee's wage tax card from Vero Source: https://docs.lastaccountingcompany.com/api-reference/payroll/fetch-an-employees-wage-tax-card-from-vero /openapi.yaml post /payroll/employees/tax-card/fetch NOT available to API keys — requires an interactive admin or existing approver session. Fetches the wage tax card for one actual or future payday, applies normalized authority facts through the audited payroll primitive, and returns the refreshed workspace for the payday's month. The server selects the Vero environment and reads the employee identity from tenant-scoped payroll state; neither can be supplied in this request. # Get an employee's payslip Source: https://docs.lastaccountingcompany.com/api-reference/payroll/get-an-employees-payslip /openapi.yaml get /payroll/payslip NOT available to API keys — requires an interactive admin or existing approver session. Returns one employee's payslip for a period (optionally a specific run). Amounts are integer cents. # Get the payroll workspace Source: https://docs.lastaccountingcompany.com/api-reference/payroll/get-the-payroll-workspace /openapi.yaml get /payroll NOT available to API keys — requires an interactive admin or existing approver session. Returns the payroll workspace for a period (`YYYY-MM`, default current): employees, employer settings, draft/approved runs. Amounts are integer cents; rates are basis points. An optional run_id pins the workspace to that exact persisted run in the selected period and company. Missing or replaced runs return 404; they never fall back to the latest run. # Update an employee Source: https://docs.lastaccountingcompany.com/api-reference/payroll/update-an-employee /openapi.yaml patch /payroll/employees NOT available to API keys — requires an interactive admin or existing approver session. Partially updates an employee identified by `employee_id` or `employee_key`. Same units as creation: integer cents and basis points. # Update an employee's tax card Source: https://docs.lastaccountingcompany.com/api-reference/payroll/update-an-employees-tax-card /openapi.yaml patch /payroll/employees/tax-card NOT available to API keys — requires an interactive admin or existing approver session. Updates the withholding tax-card values for one employee: base and additional withholding rates in basis points, income ceiling in integer cents, effective-from date, and prior year-to-date gross in cents. # Update employer payroll settings Source: https://docs.lastaccountingcompany.com/api-reference/payroll/update-employer-payroll-settings /openapi.yaml patch /payroll/settings NOT available to API keys — requires an interactive admin or existing approver session. Updates employer-level payroll rates — pension, side costs, holiday accrual — all in basis points, effective from a given date. # Bind a verified Shopify store to one LAC tenant Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/bind-a-verified-shopify-store-to-one-lac-tenant /openapi.yaml post /shopify-connections/oauth/start Validates the actor-bound install ticket, establishes a tenant-and-shop single-use state, and returns the installed App Home URL that completes App Bridge token exchange. Requires a mutating portal role. # Exchange an App Bridge JWT for offline read access Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/exchange-an-app-bridge-jwt-for-offline-read-access /openapi.yaml post /shopify/app/complete Verifies the Shopify session and the LAC tenant-bound single-use state, exchanges the JWT server-side for an expiring offline token, stores it in the credential broker, and queues the first read-only import. # Load the embedded Shopify App Home script Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/load-the-embedded-shopify-app-home-script /openapi.yaml get /shopify/app.js # Receive a mandatory Shopify privacy webhook Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/receive-a-mandatory-shopify-privacy-webhook /openapi.yaml post /shopify/privacy/webhooks Verifies Shopify's HMAC over the untouched request bytes, routes the shop to its canonical tenant when possible, and durably queues the privacy request. During the last custom-app migration, the exact shop-bound legacy secret and the public-app secret are both accepted. # Render the embedded Shopify App Home Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/render-the-embedded-shopify-app-home /openapi.yaml get /shopify/app Public frame entrypoint loaded by Shopify Admin. App Bridge obtains a signed session token before any store or connection state is returned. # Resolve the store's App Bridge connection state Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/resolve-the-stores-app-bridge-connection-state /openapi.yaml post /shopify/app/session Verifies Shopify's short-lived session JWT. Returns either the existing connection state or a short-lived, signed handoff URL into the LAC portal. # Start installation from the permanent public app listing Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/start-installation-from-the-permanent-public-app-listing /openapi.yaml post /shopify-connections/install/start Returns only the deployment-owned apps.shopify.com listing. The merchant chooses the store in Shopify; customer-supplied shop domains and expiring custom-app installation URLs are rejected. A short-lived, actor-bound install intent preserves the selected LAC company across the Shopify round trip without putting tenant identity in the public listing URL. # Verify Shopify's signed App Home handoff Source: https://docs.lastaccountingcompany.com/api-reference/shopify-app/verify-shopifys-signed-app-home-handoff /openapi.yaml post /shopify-connections/install/verify Validates the short-lived App Home ticket and binds a new install ticket to the authenticated LAC actor. If the install began from one company's LAC connector screen, required_customer_id returns that signed intent so the UI can continue without asking for the same company again. # List work log entries Source: https://docs.lastaccountingcompany.com/api-reference/work-log/list-work-log-entries /openapi.yaml get /worklog Returns non-voided work log entries, newest first (capped at 1000). The claimant role sees only its own entries. # Record hours worked Source: https://docs.lastaccountingcompany.com/api-reference/work-log/record-hours-worked /openapi.yaml post /worklog Appends one work log entry. The entry is attributed to the authenticated caller and cannot be edited afterwards — void it and add a new one to correct a mistake. `submission_key` makes the call idempotent: replaying the same key with the same facts returns the existing entry. Requires a write-scoped key. # Void a work log entry Source: https://docs.lastaccountingcompany.com/api-reference/work-log/void-a-work-log-entry /openapi.yaml post /worklog/{entry_id}/void Removes an entry from the log by voiding it (the row is kept for audit). Authors void their own entries; admins can void any. Idempotent. Requires a write-scoped key. # Invoice for a partner Source: https://docs.lastaccountingcompany.com/guides/partner-invoices Create and send an invoice where a partner company is the legal seller and payee. Use a seller profile when your company produces an invoice in a partner's name and for the partner's account. The partner is the legal seller. Payment goes to the partner. The sale does not enter your ledger. ## Before the first invoice Prepare the partner through REST, MCP, or **Invoicing → Partners**. A company admin must then review and activate it in **Invoicing → Partners**. Activation requires: * registered legal name, Finnish business ID, and postal address; * the partner's own IBAN and bookkeeping-copy email; * signed mandate reference and KYC reference. A write-scoped REST or MCP credential can create and update the draft. It cannot approve its own evidence, activate the partner, or change an active partner. The same validation and audit rules apply to every route. For example, REST can prepare the draft in one call: ```bash theme={null} curl https://api.app.lastaccountingcompany.com/portal/seller-profiles \ -H "Authorization: Bearer $LAC_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "legal_name": "", "business_id": "", "street_address": "", "postal_code": "", "city": "", "country_code": "FI", "iban": "", "contact_email": "", "mandate_evidence_ref": "", "kyc_evidence_ref": "" }' ``` Add or correct draft fields with `PATCH /portal/seller-profiles/{profile_id}`. The company admin then verifies that LAC holds the evidence and selects **Start using this partner** in the portal. ## 1. Get the seller profile Use a write-scoped key because the result contains bank and evidence references. ```bash theme={null} curl https://api.app.lastaccountingcompany.com/portal/seller-profiles \ -H "Authorization: Bearer $LAC_API_KEY" ``` Select a profile whose `status` is `active`. Copy its `id` to the draft's `seller_profile_id`. ## 2. Resolve the buyer's e-invoice route Search by the buyer's name, Finnish business ID, or FI VAT ID. LAC asks Maventa for the current OVT/e-invoice address and operator; you do not create a receiver record. ```bash theme={null} curl --get https://api.app.lastaccountingcompany.com/portal/invoice-receivers \ -H "Authorization: Bearer $LAC_API_KEY" \ --data-urlencode "query=" ``` Copy the returned `einvoice_address` and `operator` to the draft's `customer`. ## 3. Create the draft ```bash theme={null} curl https://api.app.lastaccountingcompany.com/portal/invoices \ -H "Authorization: Bearer $LAC_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "seller_profile_id": "selp_...", "delivery_channel": "maventa_einvoice", "issue_date": "", "terms_days": 14, "customer": { "name": "", "business_id": "", "country_code": "FI", "einvoice_address": "", "einvoice_operator": "" }, "lines": [{ "description": "Consulting services", "quantity": "1", "unit_price_cents": 100000, "vat_rate_basis_points": 2550, "net_cents": 100000, "vat_cents": 25500, "gross_cents": 125500 }], "net_cents": 100000, "vat_cents": 25500, "gross_cents": 125500 }' ``` Set the VAT treatment from the underlying sale. The example rate shows the input shape only. Read the returned draft with `GET /portal/invoices/{draft_id}`. Confirm `seller_profile_id`, partner legal name, business ID, and IBAN before issue. ### Consumer buyers and PDF delivery For a consumer, use the customer-directory `id` returned by LAC when updating an existing buyer. A Business ID and e-invoice route are not required for the PDF channel. ```json theme={null} { "seller_profile_id": "selp_...", "delivery_channel": "pdf_download", "customer": { "name": "", "email": "", "country_code": "FI" } } ``` Finalize that draft with `POST /portal/invoices/{draft_id}/finalize`. The response includes `pdf_document_id`, `pdf_sha256`, `pdf_size_bytes`, and `pdf_available=true`. Download the exact retained bytes from `GET /portal/invoices/{invoice_id}/pdf`; its `ETag` and `X-Content-SHA256` headers equal `pdf_sha256`. LAC keeps that immutable PDF as accounting evidence. You can attach the downloaded PDF to your own email, or host it behind your own authenticated link and send that link by text message. Finalizing does not send anything to the consumer. A consumer e-invoice still requires the consumer to have activated e-invoicing with their bank and supplied the corresponding receiving route. The PDF flow does not require that subscription. ## 4. Send ```bash theme={null} curl -X POST https://api.app.lastaccountingcompany.com/portal/invoices/invd_.../send \ -H "Authorization: Bearer $LAC_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` If invoice approval is required, call `/request-approval` first and wait for a person to approve it in the portal. The send has these fixed effects: * the Finvoice seller, postal address, business ID, VAT identity, invoice series, and payment IBAN come from the partner profile; * the tenant's Maventa address is the technical material-handler route, not the legal seller; * the partner receives a PDF copy for its own books; * `posts_ledger=false`: no tenant journal, output VAT, receivable, aging, or overdue item is created. ## MCP Use `create_seller_profile` and `update_seller_profile` to prepare the draft partner. A company admin activates it in the portal after checking the evidence. Then use `list_seller_profiles`, `search_invoice_receivers`, `create_invoice_draft`, `get_invoice`, and `send_invoice`. MCP uses the same draft and customer fields as REST, but it does not expose the seller-profile status field. For recovery, use `retry_invoice_send` only after a safe failure. Use `retry_partner_invoice_copy` only after you verified that the partner did not receive an ambiguous earlier copy. LAC refuses ambiguous e-invoice sends until the outcome is checked in Maventa. # Enable read permissions Source: https://docs.lastaccountingcompany.com/guides/read-permissions Give LAC complete read-only access to your existing accounting and bank data in one pass. Choose your system below. Give Last Accounting Company every available **read** or **view** permission, then paste the credentials in LAC. Read-only means no create, edit, approve, pay, delete, or invalidate access. LAC stores credentials securely and never shows them again. If the provider refuses access, LAC keeps the saved credentials and shows **Check again**, so you only need to fix the setting at the provider. Paste a new key only if the key itself is wrong. The Fennoa key has no separate scope screen. Access belongs to the API user that owns the key. A Fennoa administrator or the current accounting firm opens **Users → Create new API user**. Choose **Yleinen API-käyttäjä** (General API user) and name it **Last Accounting Company**. [Open Fennoa's API-user guide](https://tietopankki.fennoa.com/tuotantoon-siirtyminen) If Fennoa shows a bulk read/view choice, use it. Otherwise, enable every permission labelled read or view. Leave every create, change, approve, payment, and delete permission off. Fennoa does not publish one universal read-only preset. Check the wording before you save. Copy and paste the **API username** and **API key**. | Area | Available reads | Used today | Grant | | - | -: | -: | - | | Accounting | 8 | 7 | All read/view rights | | Sales invoices | 6 | 5 | All read/view rights | | Purchase invoices | 8 | 8 | All read/view rights | | Customers | 3 | 1 | All read/view rights | | Dimensions | 3 | 2 | All read/view rights | | **Total** | **28** | **23** | **All read/view rights** | **Used today** * Accounting: `GET /accounting_api/get/ledger/{start}/{end}`, `/accounting_api/get/accounts`, `/accounting_api/get/vatcodes`, `/accounting_api/get/periods`, `/accounting_api/get/opening_balances/{period_id}`, `/accounting_api/get/locking_periods`, `/accounting_api/get/budgets` * Sales: `GET /sales_api/`, `/sales_api/{id}`, `/sales_api/get/payments/{start}/{end}`, `/sales_api/get/pdf/{id}`, `/sales_api/get/delivery_errors` * Purchases: `GET /purchases_api/get/list`, `/purchases_api/{id}`, `/purchases_api/get/approval_queue`, `/purchases_api/get/finvoice/{id}`, `/purchases_api/get/attachment/{id}/{attachment_id}`, `/purchases_api/get/tags/{id}`, `/purchases_api/get/unbooked`, `/purchases_api/get/suppliers` * Customers: `GET /customer_api/` * Dimensions: `GET /dimension_api/`, `/dimension_api/get/types` **Available for later** * `GET /accounting_api/get/account_balance` * `GET /sales_api/get/invoice_no/{invoice_no}` * `GET /customer_api/{id}` * `GET /customer_api/get/customer_no/{customer_no}` * `GET /dimension_api/{id}` Sources: [accounting](https://tietopankki.fennoa.com/api-accounting), [sales](https://tietopankki.fennoa.com/api-sales-invoices), [purchases](https://tietopankki.fennoa.com/api-purchases), [customers](https://tietopankki.fennoa.com/api-customers), and [dimensions](https://tietopankki.fennoa.com/api-dimensions). A Procountor API key has no permission picker. It inherits the rights of the user for whom it was created. Use a dedicated user so access stays read-only and easy to revoke. A company administrator opens **Management → Users and user rights** and creates a user named **Last Accounting Company**. [Open Procountor's user-rights guide](https://help.procountor.fi/en/articles/532516-users-and-user-rights) Use **Management / Auditor** as the starting role. Set every available permission to **Viewing rights**. Set **Only allow API M2M login** to **Yes**. Remove personal-invoice and dimension-only limitations. Leave any right that only offers write-capable **All rights** at **No access**. In particular, do not grant payment, salary payment, approval, import, or editing authority. Sign in as a company administrator. Open **Basics → API client keys → New API key**. Select the dedicated LAC user and paste the **LAC client ID** shown on the connection screen. Create the key and paste it in LAC. [Open Procountor's API-key guide](https://dev.procountor.com/m2m-authentication/) Procountor's public API currently contains 101 `GET` operations and three read-only report operations that use `POST`. Product, role, country, and two-factor rules can limit some operations for an M2M user. | API area | Available | Used today | | - | -: | -: | | Attachments | 2 | 1 | | Bank accounts | 2 | 0 | | Bank statements | 1 | 1 | | Business partners | 9 | 2 | | Chart of accounts | 1 | 1 | | Company | 9 | 1 | | Currencies | 4 | 0 | | Dimensions | 2 | 1 | | Employees | 11 | 0 | | Factoring contracts | 2 | 0 | | Fiscal years | 1 | 1 | | Health status | 1 | 0 | | Integrations | 2 | 0 | | Invoices | 12 | 3 | | Journal | 1 | 0 | | Ledger receipts | 2 | 2 | | Multi-factor authentication | 1 | 0 | | Payments | 6 | 0 | | Payrolls | 10 | 0 | | Persons | 5 | 0 | | Products | 6 | 0 | | Reference payments | 1 | 1 | | Reports | 3 | 1 | | SIE file | 2 | 0 | | Session information | 1 | 0 | | Users | 3 | 0 | | VAT | 3 | 1 | | Webhooks | 1 | 0 | | **Total** | **104** | **16** | **Used today** `GET /company`, `GET /fiscalyears`, `GET /coa`, `GET /dimensions`, `GET /vats/default`, `GET /businesspartners`, `GET /businesspartners/{id}`, `GET /ledgerreceipts`, `GET /ledgerreceipts/{receiptId}`, `GET /invoices`, `GET /invoices/{invoiceId}`, `POST /reports/ledgeraccounts`, `GET /bankstatements`, `GET /referencepayments`, `GET /attachments/{attachmentId}`, `GET /invoices/{invoiceId}/image`. **All available read operations** * Attachments: `GET /attachments`, `GET /attachments/{attachmentId}` * Bank accounts: `GET /bankaccounts`, `GET /bankaccounts/{id}` * Bank statements: `GET /bankstatements` * Business partners: `GET /businesspartners`, `/businesspartners/groups`, `/businesspartners/groups/{id}`, `/businesspartners/personaldetails`, `/businesspartners/{id}`, `/businesspartners/{id}/defaults/accounts`, `/businesspartners/{id}/defaults/dimensions`, `/businesspartners/{id}/defaults/dimensions/{dimensionId}`, `/businesspartners/{id}/defaults/products` * Chart of accounts: `GET /coa` * Company: `GET /company`, `/company/deliveryterms`, `/company/einvoiceaddresses`, `/company/expenses/collectionpenal/settings`, `/company/invoicecirculation/settings`, `/company/invoicecirculation/verifierlists`, `/company/invoicecirculation/verifierlists/{id}`, `/company/invoicetemplates`, `/company/usagesettings` * Currencies: `GET /currencies`, `/currencies/company`, `/currencies/exchangerate`, `/currencies/latest` * Dimensions: `GET /dimensions`, `GET /dimensions/{dimensionId}` * Employees: `GET /payrolls/employees`, `/payrolls/employees/{id}/holidaypay`, `/payrolls/employees/{id}/salarybase`, `/payrolls/employees/{id}/salaryinfo`, `/payrolls/employees/{id}/salaryinfo/employments`, `/payrolls/employees/{id}/salaryinfo/employments/{employmentId}`, `/payrolls/employees/{id}/salaryinfo/laborunionmemberships`, `/payrolls/employees/{id}/salaryinfo/laborunionmemberships/{laborUnionMembershipId}`, `/payrolls/employees/{id}/salaryinfo/taxcards`, `/payrolls/employees/{id}/salaryinfo/taxcards/{taxCardId}`, `/payrolls/employees/{id}/workinghourreduction` * Factoring contracts: `GET /factoringcontracts`, `GET /se/factoringcontracts` * Fiscal years: `GET /fiscalyears` * Health status: `GET /status` * Integrations: `GET /integrations/{integrationId}/customers`, `GET /integrations/{requestId}` * Invoices: `GET /invoices`, `/invoices/personalapprovals`, `/invoices/personalverifications`, `/invoices/transactions`, `/invoices/{invoiceId}`, `/invoices/{invoiceId}/comments`, `/invoices/{invoiceId}/comments/taggableusers`, `/invoices/{invoiceId}/comments/{commentId}`, `/invoices/{invoiceId}/image`, `/invoices/{invoiceId}/paymentevents`, `/invoices/{invoiceId}/paymentevents/{paymentEventId}`, `/invoices/{invoiceId}/transactions` * Journal: `GET /journals` * Ledger receipts: `GET /ledgerreceipts`, `GET /ledgerreceipts/{receiptId}` * Multi-factor authentication: `GET /mfatransactionresult/{transactionIdentifier}` * Payments: `GET /payments`, `/payments/directsalarypayments`, `/payments/directsalarypayments/{paymentListId}`, `/payments/errormessages`, `/payments/paymentevents`, `/payments/{paymentId}` * Payrolls: `GET /payrolls/laborunionsettings`, `/payrolls/salariesbasicinfo`, `/payrolls/salarylists`, `/payrolls/salarylists/{id}`, `/payrolls/salaryperiods`, `/payrolls/salaryperiods/{id}`, `/payrolls/salaryslips`, `/payrolls/salaryslips/{id}`, `/payrolls/salaryslips/{id}/accounting`, `/payrolls/salarytypes` * Persons: `GET /persons`, `/persons/{id}`, `/persons/{id}/defaults/dimensions`, `/persons/{id}/defaults/dimensions/{dimensionId}`, `/persons/{id}/defaults/products` * Products: `GET /products`, `/products/groups`, `/products/groups/{groupId}`, `/products/{productId}`, `/products/{productId}/defaults/dimensions`, `/products/{productId}/defaults/dimensions/{dimensionId}` * Reference payments: `GET /referencepayments` * Reports: `POST /reports/accounting`, `POST /reports/generalledger/{id}`, `POST /reports/ledgeraccounts` * SIE file: `GET /sie/availability`, `GET /sie/file` * Session information: `GET /sessioninfo` * Users: `GET /users`, `/users/profiles/{userId}`, `/users/rights` * VAT: `GET /vats/country`, `/vats/default`, `/vats/settings` * Webhooks: `GET /webhooks` Source: [Procountor API reference](https://dev.procountor.com/api-reference/), version 26.08. Netvisor grants access to a custom integration, not to a generic key scope. The connection screen shows the LAC integration key that identifies the correct resource list. Open **Company menu → Software API identifiers**. Create a dedicated identifier named **Last Accounting Company**. Then open **Company menu → API resource permissions → Custom integrations** and add LAC with the **LAC integration key** shown on the connection screen. [Open Netvisor's resource-permissions guide](https://support.netvisor.fi/en/articles/766836-rights-of-api-resources) First scan the resource actions shown inside the LAC integration. * If every action is read or export, turn on **Integration allowed**. This is Netvisor's clean bulk option. * If you see any import, add, create, edit, update, approve, pay, delete, or invalidate action, leave **Integration allowed** off. Enable only the 22 read/export resources listed below. If the LAC panel is missing one of the 22 resources, stop and message us. LAC must correct the registered integration bundle with Netvisor; you should not need to troubleshoot our setup. Paste the **API identifier** and **API key**. LAC already knows your company Business ID. | Area | Requested | Used today | | - | -: | -: | | Sales invoices and payments | 5 | 2 | | Purchase invoices and payments | 6 | 2 | | Accounting and dimensions | 11 | 6 | | **Total** | **22** | **10** | **Used today** `accountlist.nv`, `accountingperiodlist.nv`, `getaccountdimensionlist.nv`, `accountingledger.nv`, `accountbalance.nv`, `getvoucherattachments.nv`, `salesinvoicelist.nv`, `getsalesinvoice.nv`, `purchaseinvoicelist.nv`, `getpurchaseinvoice.nv`. **Complete requested bundle** * Sales invoices and payments: `salesinvoicelist.nv`, `getsalesinvoice.nv`, `deletedsalesinvoices.nv`, `salespaymentlist.nv`, `deletedsalespayments.nv` * Purchase invoices and payments: `purchaseinvoicelist.nv`, `getpurchaseinvoice.nv`, `getattachments.nv`, `deletedpurchaseinvoices.nv`, `paymentlist.nv`, `deletedpurchasepayments.nv` * Accounting and dimensions: `accountingledger.nv`, `deletedvouchers.nv`, `accountlist.nv`, `accountingperiodlist.nv`, `vouchertypelist.nv`, `dimensionlist.nv`, `accountbalance.nv`, `getbankaccounts.nv`, `getvoucherattachments.nv`, `getaccountdimensionlist.nv`, `financialobligationstatus.nv` The extra reads are limited to accounting completeness: source deletion detection, bank-account identity, invoice payment links, purchase evidence, voucher/dimension interpretation, and Netvisor's obligation and ledger-reconciliation status. “Deleted…” resources only read deletion history; they do not delete data. Several of Netvisor's deletion reads expose only a seven-day history, so LAC must poll them without gaps. Payroll, user administration, customer/vendor masters, orders, products, warehouse data, imports, approvals, payment initiation, and every source mutation are excluded. If one of the 22 resources is missing from the LAC panel, message us: only Netvisor partner support can add it to the registered integration bundle. Sources: Netvisor's [accounting](https://support.netvisor.fi/en/articles/766886-accounting-and-dimensions-in-general), [sales](https://support.netvisor.fi/en/articles/766852-sales-invoices-orders-and-payments-in-general), and [purchase](https://support.netvisor.fi/en/articles/766853-purchase-invoices-orders-payments-and-vendors-in-general) resource guides; its [deleted-voucher guide](https://support.netvisor.fi/en/articles/766891-get-deleted-vouchers-deletedvouchers-nv) documents the seven-day deletion-history constraint. Wise puts the access choice directly on the token. You do not need to choose individual API routes. Sign in to the correct Wise Business profile on the web. Open **Your account → Connect and manage apps → API tokens**. Wise does not offer token creation in the mobile app. [Open Wise's API-token guide](https://wise.com/help/articles/2958107/getting-started-with-the-api) Choose **Add new token**, name it **Last Accounting Company**, and set the access level to **Read only**. Complete two-step verification. Wise shows the token only once. Copy it and paste the **API token** in LAC before you close the dialog. Wise does not ask you to grant routes one by one. The **Read only** access level is the full safe choice. LAC currently uses: * `GET /v2/profiles` * `GET /v4/profiles/{profile_id}/balances` * `GET /v1/profiles/{profile_id}/balance-statements/{balance_id}/statement.json` * `GET /v1/transfers` Wise can limit statement access by account country and token product. LAC shows any missing statement months after the first sync. Adyen grants access through roles on an API credential. A **Report user** with one report-download role can read settlement reports and can do nothing else: it cannot take payments, refund, or change settings. A Customer Area user with **Merchant admin** or **Manage API credentials** opens **Developers → API credentials → Create new credential** and chooses **Report user**. Under **Roles** (or **Permissions**), keep only **Merchant Report Download role**, and limit **Accounts** to the merchant account you connect. Leave **Allowed IP range** empty: LAC's report reads do not come from a fixed address. [Open Adyen's API-credential guide](https://docs.adyen.com/development-resources/api-credentials) Switch to the merchant account and open **Reports → Settlement details → Manage report → Automatic**. Turn it on **At batch close**, for **Current account**, as **CSV**, without report encryption. A report for several accounts or in another format has a file name or layout LAC cannot read. LAC reads one report per closed payout batch; if a batch has no report, generate it under **Manual → Single batch**. [Open Adyen's Settlement details guide](https://docs.adyen.com/reporting/settlement-reconciliation/transaction-level/settlement-details-report) Generate the Report user's **API key**, copy it, and **save** the credential: Adyen shows the key only once. Paste it in LAC with the **merchant account** code exactly as Customer Area shows it. One connection reads one merchant account. LAC downloads each closed batch's Settlement details report and nothing else: * `GET https://ca-live.adyen.com/reports/download/MerchantAccount/{merchant_account}/settlement_detail_report_batch_{n}.csv` Each report is checked before it is used: a closed batch nets to zero, so its payments, refunds, chargebacks, fees and carried balances must add up exactly to its payout. Adyen keeps generated reports for two years. To read older batches, generate their reports again in Customer Area (**Manual → Single batch**). PayPal has no read-only key. You create an app in your own PayPal business account, and the features you turn on for that app decide what its credentials can do. LAC only reads with them, so turn on only what LAC reads and leave the payment features you don't use off. Sign in to the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/) with your PayPal business account. Switch to **Live**, open **Apps & Credentials**, and choose **Create App**. Name it **Last Accounting Company**. Under the app's **Features**, keep **Transaction search** on, and **Disputes** if PayPal offers it. Leave payment features you don't use off: LAC never uses them. PayPal can take a few hours to apply a feature change. If you pasted the credentials before turning the feature on, select **Check again** on the PayPal connection once it has applied; a connected app is checked again on every sync. Copy the app's **Client ID** and **Secret** and paste both in LAC. LAC checks them with PayPal and reads the PayPal account the app belongs to. One PayPal account belongs to one company. LAC asks PayPal for a token with the app's credentials, then only reads: * `GET /v1/reporting/transactions`: transactions and fees, up to three years back * `GET /v1/reporting/balances`: balances by currency * `GET /v1/customer/disputes`: refunds and disputes, when **Disputes** is on for the app If **Transaction search** is off, PayPal tells LAC in the token itself, and the connection shows what to turn on. Without **Disputes**, LAC reads everything else. # Grant LAC the Suomi.fi mandate Source: https://docs.lastaccountingcompany.com/guides/suomi-fi-mandate Step-by-step with screenshots: authorise Last Accounting Company to handle your company's tax matters (and payroll reporting) via Suomi.fi e-Authorizations. For LAC to handle your company's taxes, payroll, and the reads that make both verifiable, your company grants Suomi.fi mandates to our filing entity. Grant the **full list below in one wizard pass** — it takes about five minutes, selecting everything at once means you never have to come back for a missing authorisation, and nothing is ever filed without a human review on our side. The Suomi.fi interface is shown in Finnish below; the flow is identical in the English UI. ## What you need * The right to grant mandates for your company — typically you're the CEO, or hold a registered right to represent the company alone. * Finnish online banking credentials, mobile certificate, or a certificate card for identification. ## Steps Go to [suomi.fi/e-authorizations](https://www.suomi.fi/e-authorizations) (Finnish: [suomi.fi/valtuudet](https://www.suomi.fi/valtuudet)), press **Identify yourself**, sign in, and choose to act on behalf of your company. You land on **Yrityksen valtuudet** (Company mandates). Press **Anna tai pyydä valtuuksia** → **Anna valtuuksia** (Grant mandates). Suomi.fi company mandates page (Yrityksen valtuudet) with the granted-mandates list and the grant-or-request button Step 1/7 asks for the mandate type. Pick **Asiointivaltuus** (mandate for transactions) — you're authorising an accounting firm to act on the company's behalf. Suomi.fi grant-mandates step 1 of 7: mandate type selection with Asiointivaltuus selected Step 2/7 (**Osapuolet**, parties): under *Lisää valtuutetut*, search by business ID and add: * **Name:** Bloom Systems Oy (operating as Last Accounting Company) * **Business ID (Y-tunnus):** 3616618-4 Suomi.fi grant-mandates step 2 of 7: Bloom Systems Oy 3616618-4 added as the authorised party Step 3/7 (**Valtuusasiat**): search and tick **every theme below** (the English title is followed by the exact Finnish title shown when your Suomi.fi interface is in Finnish). If the wizard is in Finnish, search using a distinctive word copied verbatim from the Finnish line instead of translating the English title yourself: 1. **Maintaining information on unemployment insurance contributions**
Työttömyysvakuutusmaksutietojen ylläpito — unemployment-insurance contributions and training compensations. 2. **Management of electronic messages**
Sähköisten viestien hallinnointi — authority message settings, reading, and sending messages for your company. 3. **Managing of tax affairs**
Veroasioiden hoito — VAT returns, tax-account reads, and the other Vero work LAC prepares for you. 4. **Ordering and retrieving records related to the payer’s earnings payment data**
Maksajan palkkatietoihin liittyvien aineistojen tilaaminen ja noutaminen — the official machine-readable record of payroll data filed for you. 5. **Processing of log, interface and report data related to income data**
Tulotietoihin liittyvien loki-, rajapinta- ja ilmoitustietojen käsittely 6. **Processing salary information**
Palkkatietojen käsittely 7. **Processing TyEL insurance and payment information**
TyEL-vakuutus- ja -maksutietojen käsittely 8. **Processing TyEL insurance, payment and earnings information**
TyEL-vakuutus-, maksu- ja ansiotietojen käsittely 9. **Reporting earnings payment data**
Palkkatietojen ilmoittaminen — payroll reporting to the Incomes Register. 10. **Reporting, updating, and retrieving tax information via the interface**
Verotukseen liittyvien tietojen ilmoittaminen, päivittäminen ja hakeminen rajapinnan kautta 11. **Submitting an interface application related to taxation, income and credit information and ordering certificates**
Verotukseen, tulotietoihin ja luottotietoihin liittyvän rajapintahakemuksen tekeminen ja varmenteiden tilaaminen The full list lets LAC resolve tax, payroll, pension, unemployment-insurance, message, and records matters for you without another Suomi.fi visit later. Every mandate is read or filing authority only — money never moves without you, and filings always pass a human review at LAC. Suomi.fi grant-mandates step 3 of 7: mandate theme search with Palkkatietojen ilmoittaminen selected
Step 4/7 (**Valitut valtuusasiat**) lists what you picked — check all eleven themes are there. Leave the *valtuuden tarkenne* (mandate specifier) toggle off. Suomi.fi grant-mandates step 4 of 7: selected mandate themes review Step 5/7 (**Valtuuden vahvistajat**): if you can represent the company alone, Suomi.fi says so — just continue. (If your trade register entry requires shared representation, Suomi.fi routes you to co-confirmation here.) Suomi.fi grant-mandates step 5 of 7: mandate confirmers, confirmable alone Step 6/7 (**Voimassaolo**): set the validity period. We suggest the maximum, 25 years — you can revoke the mandate at any time. Suomi.fi grant-mandates step 6 of 7: validity period start and end dates Step 7/7 (**Yhteenveto ja vahvistus**): check the summary — assignee Bloom Systems Oy 3616618-4, your themes, the validity — and press **Vahvista** (Confirm). Suomi.fi grant-mandates step 7 of 7: summary and confirmation with selected mandate themes listed Suomi.fi confirmation page after granting the mandates The grants now show under **Annetut valtuudet** (Granted mandates). Back in the [LAC portal](https://app.lastaccountingcompany.com), press **I have granted these mandates** on the Suomi.fi onboarding step. We verify the mandate with the authorities before anything is filed. Suomi.fi company mandates page showing Bloom Systems Oy with granted mandates
## Revoking You stay in control: the mandate can be revoked at any time in Suomi.fi e-Authorizations under **Annetut valtuudet** (Granted mandates). If you revoke it, LAC can no longer file on your behalf and we'll reach out about next steps. ## Trouble? If Suomi.fi says you can't grant mandates alone (for example the trade register lists shared representation), Suomi.fi offers a **mandate application** flow, or another representative can co-confirm at step 5. Message us in the portal chat and we'll walk it through with you. # Getting started Source: https://docs.lastaccountingcompany.com/index What the LAC customer API covers, how to get an API key, and your first requests. Everything a customer can do in the LAC portal at [app.lastaccountingcompany.com](https://app.lastaccountingcompany.com) is available programmatically: read the general ledger, pull VAT positions and financial statements, upload documents, draft and send invoices, check your connections — and talk to Björn, the AI accountant who keeps your books. One [REST API](/api-reference), and the same capabilities as an [MCP server](/mcp-server) for AI agents. ## What the API is LAC runs your company's accounting as a service. The API is a window into that service — the same one the portal uses. It is read-heavy by design: your books are produced by LAC, and the API lets you read them in full and feed evidence and instructions back in. * **Books & GL** — canonical general-ledger rows, paginated, by month, quarter, or year. * **VAT** — per-period VAT view, previews, drafts, and filed returns. * **Financial statements** — income statement, balance sheet, and cash flow, with drill-down to the transactions behind any line. * **Documents** — upload receipts, invoices, and contracts as evidence; track ingest state. * **Björn** — message the AI accountant and read the conversation. * **Filings** — review requests, standing filing authorization, published output packages. * **Invoicing** — draft, send, credit, and remind; manage billing customers and recurring templates. * **Payroll** — stays in the portal: payroll data and actions require an interactive admin/approver in the portal UI and are not available to API keys. * **Connections** — health and syncs for bank, Stripe, Procountor, Fennoa, inbox, and Sheets connections. ## Get an API key API keys are created in the portal: **Settings → API access**. Only company admins can create them. Each key: * starts with `lac_sk_` and is **shown once** at creation — store it immediately; * is pinned to one company, so you never pass a company identifier (accounts with multiple businesses mint one key per business); * carries one scope, `read` or `write`; * can be revoked at any time from the same settings page. ### Scopes | Scope | What it allows | | - | - | | `read` | Read-only access to everything: books, VAT, statements, analytics, documents, messages, filings, invoices, connections, imports. | | `write` | Everything `read` allows, plus operator-level actions: upload documents, message Björn, draft and send invoices, request filing reviews, trigger connection syncs. | Even a `write` key can **never** touch payroll (payroll stays in the portal), change company settings, grant portal access, or manage API keys. Those require an interactive admin or approver signed in to the portal. ## Quickstart Authenticate every request with your key as a bearer token. Fetch your company overview: ```bash theme={null} curl -H "Authorization: Bearer lac_sk_..." \ https://api.app.lastaccountingcompany.com/portal/overview ``` Read June's general ledger: ```bash theme={null} curl -H "Authorization: Bearer lac_sk_..." \ "https://api.app.lastaccountingcompany.com/portal/sheet?tab=books&range=2026-06" ``` Ask Björn a question: ```bash theme={null} curl -X POST \ -H "Authorization: Bearer lac_sk_..." \ -H "Content-Type: application/json" \ -d '{"text": "Which purchases are still missing receipts for June?"}' \ https://api.app.lastaccountingcompany.com/portal/messages ``` From here, the [API reference](/api-reference) covers every endpoint, and the [MCP page](/mcp-server) connects the same capabilities to Claude, Cursor, VS Code, or your own agents. ### Base URL `https://api.app.lastaccountingcompany.com/portal` ### Conventions * JSON in and out, `snake_case` field names. * Amounts are **integer cents**; rates are **basis points** (`2550` = 25.5%, the Finnish standard VAT rate). * Periods are `YYYY-MM`; ranges accept `YYYY-MM`, `YYYY-Qn`, `YYYY`, `all`, `this_month`, or `last_6_months`. * Errors return a non-2xx status with `{"error": "...", "detail": "..."}`. * `customer_id` is optional everywhere — API keys are pinned to one company. ## Keep your keys safe * **Store keys in environment variables or a secret manager** — never in source code, config files under version control, or client-side code. * **Use `read` scope unless you need writes.** Analysis, dashboards, and reporting agents should run on read-only keys. * **Revoke on suspicion.** Any admin can revoke a key instantly in Settings → API access; issue a new one afterwards. * **API keys are company credentials, not personal ones** — they keep working if the person who created them leaves. Revoke or rotate keys in Settings → API access when an admin departs. * **Every action is tenant-isolated and audited.** A key can only ever see and touch its own company, and every request is attributed to the key that made it. # MCP server Source: https://docs.lastaccountingcompany.com/mcp-server Connect Claude, ChatGPT, Cursor, VS Code, or your own agents to your company's books over MCP. Give any MCP-capable AI client direct, tenant-isolated access to your company's books. The LAC MCP server exposes the same capabilities as the [REST API](/api-reference) — books, VAT, statements, dimensions, documents, invoicing, and Björn — as typed tools. | | | | - | - | | **Endpoint** | `https://api.app.lastaccountingcompany.com/mcp` | | **Transport** | Streamable HTTP, stateless (MCP spec `2025-11-25`) | | **Auth** | OAuth (hosted clients) or a portal API key as a bearer token: `Authorization: Bearer lac_sk_...` | ## Authentication Two ways in: * **OAuth** — for hosted clients like claude.ai and ChatGPT. Add the endpoint URL in your assistant's connector settings; it walks you through signing in with your normal LAC portal account (Google) and authorizing. On the authorize page you pick **which business the connection is for** — accounts with access to multiple businesses choose one business per connection — and on the consent screen that follows, the access level (read only, or read and write). OAuth connections act with **operator** access: they can read the books and statements, upload documents, draft and send invoices, and message Björn — never approve payroll, change company settings, or manage access or keys, no matter your own portal role. * **Portal API key** — for clients that send custom headers (Claude Code, Cursor, VS Code, the OpenAI Responses API, anything speaking streamable HTTP). Create one in **Settings → API access** (see [getting started](/)) and send it as a bearer token. Like OAuth connections, keys are minted per business. The tools you see follow the key's scope: **read-scope keys see only the read tools**; write-scope keys see the full tool set. ## Connect a client ### Claude (web and Desktop) On Team or Enterprise, an owner first adds the LAC connector in organization settings; each member then connects it personally. Open **Customize → Connectors**, add or select the LAC connector, and enter: ``` https://api.app.lastaccountingcompany.com/mcp ``` Claude opens the LAC sign-in. Sign in with your normal Google portal account, choose the business, and choose **Read and write** for the full MCP tool set. Disconnecting the connector in Claude ends its access. ### ChatGPT (web) In ChatGPT: **Settings → Connectors** (requires developer mode / a plan with custom connectors) → add the same URL. ChatGPT runs the same OAuth sign-in. ### Claude Code ```bash theme={null} claude mcp add --transport http lac \ https://api.app.lastaccountingcompany.com/mcp \ --header "Authorization: Bearer lac_sk_..." ``` Then ask, for example: "What's our VAT position for June?" ### Cursor Add to `~/.cursor/mcp.json` (or the project's `.cursor/mcp.json`): ```json theme={null} { "mcpServers": { "lac": { "url": "https://api.app.lastaccountingcompany.com/mcp", "headers": { "Authorization": "Bearer lac_sk_..." } } } } ``` ### VS Code Add to `.vscode/mcp.json` in your workspace: ```json theme={null} { "servers": { "lac": { "type": "http", "url": "https://api.app.lastaccountingcompany.com/mcp", "headers": { "Authorization": "Bearer lac_sk_..." } } } } ``` ### OpenAI API (Responses) ```python theme={null} response = client.responses.create( model="gpt-5", tools=[{ "type": "mcp", "server_label": "lac", "server_url": "https://api.app.lastaccountingcompany.com/mcp", "authorization": "lac_sk_...", "require_approval": "always" }], input="Which invoices are overdue, and by how much?" ) ``` ### Generic JSON For any client that takes a standard MCP server config: ```json theme={null} { "mcpServers": { "lac": { "type": "streamable-http", "url": "https://api.app.lastaccountingcompany.com/mcp", "headers": { "Authorization": "Bearer lac_sk_..." } } } } ``` The server is stateless — no session setup, safe to retry. ## Tool reference Read tools are available to every key. Write tools appear only for write-scoped keys and OAuth connections. ### Read tools (all keys) | Category | Tool | Description | | - | - | - | | Company | `get_company_profile` | Company profile: name, business ID (Y-tunnus), VAT period cadence. | | Company | `get_overview` | Dashboard in one call: key metrics, attention items, books readiness. | | Company | `get_agent_status` | Björn's live status and document-ingest progress. | | Books | `get_books` | General-ledger rows, paginated; range accepts `YYYY-MM`, `YYYY-Qn`, `YYYY`, or `this_month`. | | Books | `get_vat` | The VAT view for a period. | | Statements | `get_financial_statements` | Income statement, balance sheet, or cash-flow statement as a nested tree of lines. | | Statements | `drill_statement_line` | The transactions behind one or more account codes on a statement line. | | Statements | `get_analytics` | Time series over the books for a range. | | Dimensions | `list_dimensions` | Project, cost-centre, department, and local reporting axes with source ownership and coverage. | | Documents | `list_documents` | Uploaded evidence and the ingest state of each document. | | Messaging | `list_messages` | The conversation history with Björn; `limit` returns the most recent N messages (default 50). | | Filings | `get_filings` | VAT preview, drafts, filed returns, and the standing authorization state. | | Filings | `list_output_packages` | Published VAT, financial-statement, and CIT output packages. | | Invoicing | `list_invoices` | Sales invoices with their statuses; `limit` caps each list (default 100). | | Invoicing | `get_invoice` | One invoice in full detail. | | Invoicing | `get_invoice_finvoice` | Issued Finvoice XML as an embedded resource. | | Invoicing | `get_invoice_pdf` | Issued invoice PDF as an embedded resource. Edit and issue drafts first. | | Invoicing | `search_invoice_receivers` | Live Finnish Maventa recipient search by name, Y-tunnus, or FI VAT ID; returns the OVT/address and operator without creating a receiver record. | | Invoicing | `list_invoice_customers` | The billing-customer party book. | | Invoicing | `list_recurring_invoices` | Recurring invoice templates. | | Connections | `list_connections` | Health of bank, settlement-provider, commerce, accounting-system, inbox, and Sheets connections. | | Connections | `get_connection_data` | What one connection delivered per month and per kind of record, and how much of it is in the books. With `kind`, the single records and the named values each one states. | | Imports | `list_imports` | Migration/import runs and their statuses. | ### Write tools (write-scope keys) | Category | Tool | Description | | - | - | - | | Documents | `upload_documents` | Upload base64-encoded files into the document-ingest pipeline. | | Documents | `update_document` | Rename a document or attach a context note for bookkeeping. | | Documents | `delete_document` | Delete an uploaded document. **Destructive.** | | Messaging | `send_message` | Send a message to Björn, the AI accountant. | | Dimensions | `create_dimension_axis` | Create a local reporting axis; provider-managed catalogs remain read-only. | | Dimensions | `create_dimension_value` | Add a value to a local reporting axis. | | Filings | `request_filing_review` | Ask LAC to review a filing period. | | Filings | `set_filing_authorization` | Set or withdraw the standing authorization for LAC to file on the company's behalf. | | Invoicing | `list_seller_profiles` | Partner sellers available to a write credential; pass an active `id` as `seller_profile_id`. | | Invoicing | `create_seller_profile` | Create a draft partner seller profile for an admin to review and activate. | | Invoicing | `update_seller_profile` | Edit a draft partner seller profile; omitted fields stay unchanged. | | Invoicing | `create_invoice_draft` | Create or update a draft. `seller_profile_id` makes the partner the seller and payee; drafting never sends anything. | | Invoicing | `request_invoice_approval` | For a company that requires invoice approval, put a draft in front of its approvers. Approving and rejecting are not available here — they need a person signed in to the portal. | | Invoicing | `send_invoice` | Send a drafted invoice to the customer. **Destructive:** external delivery. | | Invoicing | `finalize_invoice` | Issue a PDF-only draft without transmitting it. **Destructive:** allocates the final number. | | Invoicing | `retry_invoice_send` | Retry a verified-safe e-invoice failure. **Destructive:** external delivery. | | Invoicing | `retry_partner_invoice_copy` | Retry a partner PDF copy after verified non-delivery. **Destructive:** external delivery. | | Invoicing | `delete_invoice_draft` | Delete an unnumbered invoice draft. Issued documents are never deleted. **Destructive:** permanent draft deletion. | | Invoicing | `create_credit_note` | Credit a finalized PDF without transmission, or send a credit for an accepted e-invoice through its original route. Creates an editable replacement draft. Requires a reason; both issued documents remain in history. **Destructive:** accounting correction and possible external delivery. | | Invoicing | `request_payment_reminder` | Request a payment reminder for an open invoice. | | Invoicing | `prefill_invoice_from_document` | Add one source document and ask Björn to fill empty draft fields. | | Invoicing | `upsert_invoice_customer` | Create or update a billing customer in the party book. | | Invoicing | `create_recurring_invoice` | Create or replace a recurring template; each occurrence issues and sends by itself on its date, under the same approval gates. | | Invoicing | `update_recurring_invoice` | Rename, pause, resume, archive, or reschedule a template. | | Invoicing | `draft_next_recurring_invoice` | Materialize the template's next reviewable draft. | | Connections | `trigger_connection_sync` | Trigger a data sync on an existing connection. | | Connections | `request_service_connection` | Ask LAC to set up a service connection, e.g. a Suomi.fi mandate. | | Connections | `start_paypal_connection` | Create a short-lived PayPal partner consent URL for a company admin to approve. This path depends on PayPal approving LAC as a partner and answers 503 until then. The other path, the company's own PayPal app, is connected in the portal: no tool accepts its Client ID or Secret. | | Connections | `activate_vipps_mobilepay_connection` | Verify an existing Vipps MobilePay accounting-partner grant and start its feed. | ## Security * **Use read-only keys for analysis agents.** A key with `read` scope exposes only read tools — the agent cannot send an invoice or delete a document. * **Invoice approval stays human.** A company can require that a draft sales invoice is approved before it goes out. An agent can write the invoice and ask for approval (`request_invoice_approval`), and `get_invoice` shows where it stands, but approving and rejecting are not MCP tools at all: they need an interactive admin or approver session. An agent able to approve its own invoice would not be a gate. While a draft is unapproved, `send_invoice` and `finalize_invoice` refuse it. * **Partner onboarding stays fail-closed.** A write credential can prepare a draft seller profile. It cannot approve its own evidence, activate the profile, or change an active profile. A company admin must review the legal identity, address, partner-owned IBAN, bookkeeping email, signed mandate, and KYC evidence in the portal. The tenant's own identity or IBAN is refused. * **Keep a human in the loop for destructive tools.** Invoice issue, send, retry, credit-note, invoice-draft-delete, and document-delete tools are annotated destructive; configure your client to require confirmation. * **Mind prompt injection when combining servers.** If an agent has the LAC server alongside other MCP servers or web access, content fetched from elsewhere could try to steer it into calling LAC write tools. Prefer read-only keys in mixed-tool setups, and review write actions. * **Revoke instantly.** Keys are revoked in the portal under Settings → API access; a revoked key loses MCP access immediately. OAuth connections end when you disconnect the connector in the client. * **API keys are company credentials, not personal ones** — they keep working if the person who created them leaves. Revoke or rotate keys in Settings → API access when an admin departs. * **Tenant isolation and audit.** Every tool call is scoped to the key's company and audited, like every REST request. ## What's deliberately not exposed Some actions require an interactive admin or approver in the portal and are not available as MCP tools or to API keys at all: * **Payroll entirely (read and write)** — payroll data and actions require an admin/approver in the portal UI. * **Company settings changes.** * **Invoice approval decisions.** * **Partner seller activation and active-profile changes.** * **Member and access management** — inviting people, changing roles. * **API key management** — a key can never mint or revoke keys. This is the same boundary as the REST API: agents can prepare and inform; humans approve.