Exact Online – Gotchas
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
attachmentsAllreference_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.
Bank Feed Accounts1 gotcha
bankFeedAccountsAddSame as exact-online-nl.
Bank Feed Statements2 gotchas
bankFeedStatementsAllSame as exact-online-nl.
bankFeedStatementsAddSame as exact-online-nl.
Bill Credit Notes2 gotchas
billCreditNotesAllExact 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.
billCreditNotesAddRequires 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.
Bill Payments1 gotcha
billPaymentsAddCreating 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
billsAddline_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
invoicesAddExact 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.
invoicesUpdateTo 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.
Journal Entries2 gotchas
journalEntriesAllLimit 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.
journalEntriesAddA 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
journalsAllUse 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.
journalsAddtype: 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
paymentsAddCreating 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
suppliersAddExact 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
taxRatesAllstatus 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.