# QuickBooks Desktop — Accounting API: gotchas

> Canonical URL: https://developers.apideck.com/apis/accounting/quickbooks-desktop/gotchas

## GET /accounting/tax-rates

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## GET /accounting/bills

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/bills

Bill expense lines map from `line_items[]` (`ledger_account` → expense account, `total_amount`, `description`). Lines cannot be changed after creation; see the update operation.

## PATCH /accounting/bills/{id}

QuickBooks Desktop cannot modify bill line items: `line_items` sent on update are ignored and the response still returns the bill `id`. Only header fields change — `supplier`, `bill_date`, `due_date`, `bill_number`, `terms`, `notes`. `currency`, `currency_rate` and `tracking_categories` are also ignored on update. Delete and recreate the bill to change its lines.

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`. Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it; read the record back before retrying.

## GET /accounting/invoices

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/invoices

On create, QuickBooks Desktop only honors `customer`, `invoice_date`, `number`, `reference` (memo), and `line_items`. Header fields such as `due_date`, `terms`, `po_number`, `customer_memo`, billing/shipping address, currency, and tracking category are ignored at create time — set them with a follow-up update. Each line item must include an `item` (QBD rejects invoices whose lines have no item). On update, line items cannot be modified — only header fields (customer, dates, ref number, memo) change; resend line edits by voiding and recreating.

`number` is limited to 11 characters; a longer value is rejected ("RefNumber is too long", error 3070). Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the invoice; list invoices by `number` before retrying.

## PATCH /accounting/invoices/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/ledger-accounts

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## PATCH /accounting/ledger-accounts/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/invoice-items

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/invoice-items

A service item needs its posting account by name: send `income_account.name` (the QuickBooks account name). An account `id` alone is not resolved, and QuickBooks rejects the item without a posting account ("A posting account must be specified", error 3180).

Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the item. List items to find it before retrying.

## PATCH /accounting/invoice-items/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/credit-notes

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/credit-notes

Credit-note lines cannot be changed after creation; see the update operation.

## PATCH /accounting/credit-notes/{id}

QuickBooks Desktop cannot modify credit-note line items, the AR account or the tracking category: `line_items` sent on update are ignored and the response still returns the credit note `id`. Only `customer`, `date_issued`, `number` and `note` change. Delete and recreate the credit note to change its lines.

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`. Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it; read the record back before retrying.

## GET /accounting/customers

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/customers

`currency` is written only when multi-currency is turned on in the company file. On a single-currency file QuickBooks rejects a create that carries `currency` (error 3250, "This feature is not enabled"), so leave `currency` out unless the file uses multi-currency.

Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the customer. List customers to find it before retrying.

## PATCH /accounting/customers/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/suppliers

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/suppliers

On create, QuickBooks Desktop stores `display_name` (or `company_name` when it is missing), `company_name`, `first_name`, `last_name`, the `billing` address (the first address when none is typed `billing`), the `primary` and `fax` phone numbers and the `primary` email. An `other` or `secondary` phone number is not stored on create.

Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the supplier; a re-sent create is rejected because the name is already in use (error 3100). Read suppliers by `filter[display_name]` before retrying.

## PATCH /accounting/suppliers/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/payments

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/payments

QuickBooks Desktop applies a payment to invoices via `allocations[]` — each `allocations[].id` is the target invoice's transaction id and `allocations[].amount` the amount applied. Without `allocations`, the payment is created unapplied. On update, QBD cannot change the applied invoices, payment method, or deposit/AR account — only customer, `transaction_date`, `reference`, `total_amount`, and `note` are updatable; recreate the payment to change allocations.

## PATCH /accounting/payments/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/journal-entries

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/journal-entries

Each line needs its account by name: send `line_items[].ledger_account.name` (the QuickBooks account name); an account `id` alone is not resolved and the entry is rejected. Only the date part of `posted_at` is stored.

Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the entry. List journal entries before retrying.

## PATCH /accounting/journal-entries/{id}

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`.

Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it. Read the record back before retrying.

## GET /accounting/purchase-orders

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## POST /accounting/purchase-orders

Purchase-order lines cannot be changed after creation; see the update operation. Per-line `customer` is not supported on QuickBooks Desktop purchase-order lines.

`po_number` is limited to 11 characters; a longer value is rejected ("RefNumber is too long", error 3070). Writes are applied on the Web Connector's next run, so a create can return a `504` timeout after 28 seconds while QuickBooks still creates the purchase order; list purchase orders by `po_number` before retrying.

## PATCH /accounting/purchase-orders/{id}

QuickBooks Desktop cannot modify purchase-order line items: `line_items` sent on update are ignored and the response still returns the purchase order `id`. Only header fields change — `supplier`, `issued_date`, `po_number`, `memo`, `expected_arrival_date`, tracking category. Delete and recreate the purchase order to change its lines.

Updates need `row_version` from a prior read of the record: without it the update is rejected with `Missing required field: data.editSequence`. Writes are applied on the Web Connector's next run, so an update can return a `504` timeout after 28 seconds while QuickBooks still applies it; read the record back before retrying.

## GET /accounting/bill-payments

QuickBooks Desktop does not expose a reliable cross-page total record count. Getting `total_count` requires a separate COUNT query — an extra API call that is not currently implemented. `meta.total_count` will not appear.

## GET /accounting/bank-feed-accounts

A bank feed account is a QuickBooks Desktop `Bank` or `CreditCard` account; `id` is the
account ListID and listing returns exactly those accounts.

## POST /accounting/bank-feed-accounts

Creating with `target_account_id` links that existing Bank/CreditCard account (no write).
Creating without it adds the account in QuickBooks; because the Web Connector polls on a
schedule, that call can return a timeout error — the account is still created, and
retrying the same request links it (create is idempotent by name). Bank feeds post
transactions straight into the register: set the `bank_feed_offset_account` connection
setting to the income/expense account lines are categorised to. If it is blank,
QuickBooks' Uncategorized Income / Uncategorized Expenses accounts are used, and files
that do not have them reject every line (error 3140).

## GET /accounting/bank-feed-statements

QuickBooks Desktop has no bank-feed review screen: lines are posted to the register as
native transactions on the Web Connector's next run. `status` is `pending` until every
line posted, then `success`, or `rejected` as soon as QuickBooks rejected a line. Use
`filter[bank_feed_account_id]` to read one account's statements. Per-line QuickBooks
transaction ids and rejection reasons are not part of the unified transaction model;
read the statement with `raw=true` to see them.

## POST /accounting/bank-feed-statements

Each transaction is written to the register as a native Deposit, Check, Credit Card
Charge or Credit Card Credit (chosen from the account type and `credit_or_debit`),
categorised to the `bank_feed_offset_account` connection setting; leave it blank only if
the company file has QuickBooks' Uncategorized Income / Uncategorized Expenses accounts,
otherwise every line is rejected (error 3140). Creating a statement returns its `id` with
status `pending`; poll the statement until `status` is `success` or `rejected`.
`source_transaction_id` is required and is the dedup key: re-sending a statement never
posts a line twice. `counterparty`, `currency` and balances are stored but not written.


[API reference](https://developers.apideck.com/apis/accounting/reference.md) · [Coverage matrix](https://developers.apideck.com/apis/accounting/coverage)
