Exact Online – Gotchas

Service ID: exact-online

Exact Cloud business software offers accounting and industry software in the cloud for SME's on desktop, laptop, tablet and mobile apps.

⚠️

17 gotchas across 12 resources

These are connector-specific behaviors and limitations to be aware of when integrating.

Attachments1 gotcha

allattachmentsAll

reference_id is the invoice, bill, or journal entry's own unified id — not Exact's internal Document envelope GUID. The connector resolves between the two internally (Exact's FinancialTransactionEntryID, live-verified to equal the unified id for all three reference types), so no manual lookup or pass-through is needed.

file_url is Exact's own document viewer page (https://start.exactonline.{tld}/docs/SysAttachment.aspx?...), not a direct file download link — it requires an active, logged-in Exact browser session and redirects to a login page for an unauthenticated request (live-verified: a plain GET returns a 302 to the Exact login page, not the file). There is no other download-capable URL on this connector's attachment records.

This list has no server-side total count, so pagination metadata never includes a count.

addbankFeedAccountsAdd

Same as exact-online-nl.

allbankFeedStatementsAll

Same as exact-online-nl.

addbankFeedStatementsAdd

Same as exact-online-nl.

allbillCreditNotesAll

Exact Online does not track settlement on a purchase entry, so balance, remaining_credit, date_paid and allocations are never returned. tax_inclusive, account, tax_code, subsidiary, location, department, tracking_categories, custom_fields and row_version are likewise not populated. status reflects Exact's entry status: an open entry reads as authorised, a processed one as paid, and a draft as draft. Any other status Exact may return falls back to authorised.

addbillCreditNotesAdd

Requires a purchase journal code on the connection setting purchase_journal_code; without it Exact rejects the create. Vault presents that setting under the Bills resource, and the same value applies here. Line item total_amount must be a positive amount of at least one cent — Exact derives the document type from the amount sign and rounds to two decimals, so a zero, negative or sub-cent line would record a bill instead of a credit note and is rejected. Exact refuses a duplicate: a credit note whose supplier, reference, date_issued and total all match an existing one is rejected with Already exists, reported as a 500 rather than a conflict. Retrying a create that already succeeded therefore fails instead of producing a second record — vary reference when a repeat is genuinely intended. line_items[].total_amount is always booked as the amount excluding tax and tax_inclusive is ignored, so tax from the line's tax_rate.code is added on top: a line of 100 with a 21% code produces a credit note whose total_amount is 121. This also applies to a tax code Exact presents as tax-inclusive, so sending a gross amount on such a code overstates the credit note by the tax.

addbillPaymentsAdd

Creating a bill payment records the bank transaction but does not automatically reconcile it with the linked bill — the bill's status will not change to paid until the payment is matched manually in Exact Online. A valid bank journal (Type=12) must be supplied via the bank_journal_code connection setting or pass_through[journal_code] per request; without one the API returns 'Invalid journal'.

Bills1 gotcha

addbillsAdd

line_items[].ledger_account is not supported on create — Exact's purchase-invoice line object rejects an unknown GLAccount property outright (400, "The property name 'GLAccount' ... is not valid"), so the connector does not send it: a ledger_account on a create request is silently dropped rather than rejected, and the created bill line will not be coded to that ledger account. Code the expense via line_items[].item instead, or use journal-entries for a GL-coded posting.

Invoices2 gotchas

addinvoicesAdd

Exact Online assigns invoice status automatically (open by default) and ignores the status field on create — invoices are finalized/processed in Exact Online, not via the API. Set VAT via line_items[].tax_rate.code; Exact derives the percentage from the code, so line_items[].tax_rate.rate is ignored on create.

updateinvoicesUpdate

To configure the shipping address for invoices, it is recommended to update the customer resource. If there is a need to change this property, modifying the customer information is advised.

alljournalEntriesAll

Limit parameter for pagination is not supported for this resource.

line_items is only returned by the single-record read (fetch by id). Exact's own $expand=GeneralJournalEntryLines is silently ignored on the list endpoint — the raw list response still returns each line collection as an unexpanded __deferred reference even though the expand parameter is sent — so the list read always returns line_items: [] and line_items[].supplier reflects nothing on all. Fetch the entry by id for line-level data (mirrors the same list-vs-one gap other connectors document for this resource).

Because of that, posted_at on the list read is always derived from the entry's financial period (month precision: the first day of FinancialYear/FinancialPeriod), since Exact's own journal entry header has no date field at all and the day-precision line date is only available on the single-record read. Fetch by id for day-precision posted_at. created_at remains the true API-write timestamp and is not affected on either operation.

memo is mapped from the same JournalDescription field as title — Exact's own header has no separate free-text field, only the journal's own description, so both unified fields carry the same value. updated_by/created_by are not populated on either operation: the header carries Created/Modified timestamps but no who-created/who- modified field (those exist only per line, not on the entry itself).

On the single-record read, line_items[].supplier reflects Exact's line-level Account reference. Exact does not distinguish a customer account from a supplier account at the line level, so a line referencing a customer account is also reflected under supplier rather than customer.

addjournalEntriesAdd

A validation refusal — an unbalanced entry, an unknown or inactive reference (ledger account, journal, VAT code, currency), or a missing required field — returns 422 with the specific reason named. Any other 500 is a genuine unexpected downstream failure, not a refusal the request itself caused.

VAT on a line is selected by tax_rate.code, not tax_rate.rate — the rate is not sent and has no effect. Omitting the code does not mean "no VAT": Exact substitutes the ledger account's own default VAT code, which changes the line's tax amount and can then reject the whole entry as unbalanced with an error naming the balance mismatch rather than VAT. Always send tax_rate.code explicitly rather than relying on a specific ledger account's default.

line_items[].date maps to Exact's per-line Date (a real field, distinct from the header, which has no date field at all — see the list-operation gotcha above). Historical or backdated bookings should set this per line rather than relying on posted_at. line_items[].source_id maps to Exact's per-line Notes, useful for carrying your own reconciliation identifier since description is typically a human-readable label.

Journals2 gotchas

alljournalsAll

Use code as journal_symbol when creating a journal entry. The id is Exact's journal GUID. allow_vat applies to general journals (type general). Select the division with x-apideck-company-id, or the connection's default division. This list has no server-side total count, so pagination metadata never includes a count.

addjournalsAdd

type: bank requires iban — Exact needs a bank account reference to create a bank journal. type: payment_service requires a payment service provider reference that has no equivalent in this unified field set — creating a journal with that type will be rejected by Exact. Use pass_through to supply the required vendor field if you need payment_service, or use sales, sales_credit_note, purchase, purchase_credit_note, cash or general instead. type: other has no Exact equivalent and will be rejected — other is a read-side fallback for values Exact might introduce in the future, not a valid input. clearing_account is the unallocated account a bank journal parks incoming movements in. Bank feed statements posted to a journal without one never reach the reconciliation queue. Exact assigns a default on create; set it explicitly to pin a specific account. Only meaningful on type: bank and type: payment_service.

Payments1 gotcha

addpaymentsAdd

Creating a payment records the bank transaction but does not automatically reconcile it with the linked invoice — the invoice status will not change to paid until the payment is matched manually in Exact Online. A valid bank journal (Type=12) must be supplied via the bank_journal_code connection setting or pass_through[journal_code] per request; without one the API returns 'Invalid journal'.

Suppliers1 gotcha

addsuppliersAdd

Exact does not enforce uniqueness on the supplier name — posting the same display_name/ company_name twice creates two separate suppliers, both with a 201. This connector passes the name through as sent rather than matching on write; the caller owns de-duplication (for example, checking suppliers.list for an existing name, or storing the returned id and reusing it) before creating a supplier that may already exist.

Tax Rates1 gotcha

alltaxRatesAll

status is derived from Exact's IsBlocked flag (false -> active, true -> inactive). Live-verified against a real division: the raw VATCode object has no Active-equivalent field of its own, only IsBlocked. Exact has no third state, so archived is never returned.