Skip to content
Desktop Accounting API

Money, dates and data conventions

QuickBooks Desktop has its own types and quirks: two-decimal amounts, five-decimal prices, local-time timestamps, a Windows code page for text. The API keeps those rules visible instead of hiding them, so values round-trip without surprises.

  • JSON only (application/json; charset=utf-8), except passthrough, which also accepts XML.
  • Field names are camelCase. Enum values are lowercase snake_case, such as "accounts_receivable". Error type and code values are UPPER_SNAKE_CASE.
  • Every object has objectType, such as "qbd_invoice", "end_user" or "list".
  • Responses always contain every documented field. Missing values are null; empty collections are []. Fields that can repeat are always arrays, even with one item. Apart from a QuickBooks object’s id, objectType, createdAt, updatedAt and revisionNumber, any response field can be null; see Damaged and unusual data.
  • Request bodies are strict. An unknown field returns 400 UNKNOWN_PARAMETER with param naming it, so a misspelled memmo never gets dropped silently.
  • Array query parameters repeat the key: ?customerIds=80000001-1&customerIds=80000002-1. Comma-joined values are rejected.
  • Enums are open: new values can appear in responses. Handle unknown values gracefully.
QuickBooks type JSON Example Rules
Amount (totals, balances, line amounts) decimal string "1234.50" Up to 13 digits before the point and 2 after. Input may have 0 to 2 decimals and comes back with exactly 2.
Price (rates, unit prices) decimal string "12.34567" Up to 10 digits before the point and 5 after. Output keeps QuickBooks’ digits.
Quantity number 2.5 Up to 10 digits before the point and 5 after.
Percentage decimal string "7.5" "7.5" means 7.5 percent. Up to 10 digits before the point and 5 after.
Exchange rate number 1.3521
Integer, boolean integer, boolean 3, true

Three values are JSON numbers although QuickBooks stores them as decimals, matching Conductor: valueDifference on inventory adjustments (still limited to 2 decimal places), and minimumFinanceCharge and annualInterestRate in company preferences.

Money is a string so that 0.1 + 0.2 problems never touch an invoice. Parse it with a decimal type: decimal.Decimal in Python, decimal in C#, BigDecimal in Java, a decimal library in JavaScript. The Python, C# and Java SDKs already return those types.

More decimal places than QuickBooks stores returns 400 DECIMAL_PRECISION_EXCEEDED with param set. We never round for you, because a silently rounded amount is an accounting error that nobody notices.

Output always uses . as the decimal separator and no thousands separators, whatever the Windows language settings on the customer’s computer. QuickBooks on a computer set to, say, Portuguese or German can write 672,00, 1.234,56 or 1 234,56; you receive "672.00" and "1234.56".

Amounts are in the transaction’s currency. With multicurrency on, objects also carry exchangeRate and home-currency amounts such as balanceRemainingInHomeCurrency. See Editions, versions and features.

Kind Format Example
Accounting dates (transactionDate, dueDate, shippingDate) YYYY-MM-DD, no time zone "2026-10-05"
QuickBooks timestamps (createdAt, updatedAt on QuickBooks objects) ISO 8601 with the customer computer’s UTC offset "2026-10-05T09:14:03-07:00"
Our timestamps (requests, end users, events, cursorExpiresAt) ISO 8601 UTC with milliseconds "2026-10-05T16:14:03.120Z"

Accounting dates are calendar dates. An invoice dated 2026-10-05 is dated October 5 everywhere; do not convert it to a time zone.

QuickBooks timestamps keep the offset QuickBooks reports. We do not convert them to UTC, because QuickBooks’ own filters work on that local clock.

Date filters such as updatedAfter, updatedBefore, transactionDateFrom and deletedAfter accept:

  • a date: 2026-10-05. Lower bounds mean the start of that day, upper bounds the end;
  • a local date-time without an offset: 2026-10-05T09:00:00, read in the customer computer’s time zone;
  • a date-time with an offset: 2026-10-05T16:00:00Z, converted to the computer’s time zone.

Many list and report endpoints also accept date macros such as this_month, last_quarter or this_year_to_date, which QuickBooks evaluates on the customer’s computer.

  • US editions of QuickBooks Desktop store text in the Windows-1252 code page, not Unicode. That covers Latin letters with accents (é, ñ, ü, Å), €, £, ©, µ, the no-break space (U+00A0), curly quotes and dashes. They are stored exactly as you write them.
  • Any other character returns 400 UNSUPPORTED_CHARACTER before anything is sent: emoji, Greek, Cyrillic and Asian scripts, control characters, line and paragraph separators (U+2028, U+2029), and fullwidth forms such as & and <. The error names the field in param, and details gives the code point, the character, its position and, where there is an obvious one, a suggestion (& for &, a plain space for a narrow no-break space, µ for the Greek μ).
  • We do not fold, strip or replace characters for you, because a silently changed name causes duplicate-name and matching bugs later. One exception changes no text: a letter written as a base letter plus a combining accent (common in text from macOS) is sent in its composed form, so e + ◌́ becomes é.
  • Text you read back is returned as QuickBooks stores it. Characters QuickBooks wrote as Windows-1252 byte references, such as ’ for ’, come back as the characters they stand for.
  • Each text field has a maximum length from the QuickBooks schema, shown in the API reference. Longer values return 400 STRING_TOO_LONG before anything is sent.
  • Send plain text. We escape XML special characters such as & and < for you.
  • QuickBooks stores a line break as a single line feed (\n). The API passes a carriage return through to QuickBooks unchanged, and QuickBooks converts \r\n to \n when it saves the text. So "line 1\r\nline 2" is stored and returned by later reads as "line 1\nline 2". Text sent with \n alone is stored exactly. If you compare text you sent with text you read back, normalize \r\n to \n first.
  • Name searches (names, fullNames, nameContains) are case-insensitive, as in QuickBooks.

Company files damaged by crashes, imports or old QuickBooks versions sometimes return records with elements missing or values in the wrong format. The API reads such responses without failing them and without dropping records:

  • A missing value is null, even where the QuickBooks schema says the element is always present (an invoice without a customer, a line without an id, a transaction without subtotal).
  • A value that cannot be read, such as an amount 12,3x, a date 0000-00-00 or a boolean maybe, is null. An enum value with no letters or digits (QuickBooks has returned ???) is "unknown".
  • Malformed XML text, such as a bare & in a memo, is kept as written.

Each of these is reported. The Daapi-Warnings response header counts them, and GET /v1/requests/{id} lists each one in warnings with code (QBD_VALUE_UNREADABLE or QBD_MARKUP_REPAIRED), the path of the affected value (data[2].subtotal) and a message that quotes what QuickBooks sent. If you see them often for one customer, ask them to run Verify Data and Rebuild Data in QuickBooks.

Only a missing or unreadable id, createdAt, updatedAt or revisionNumber on a QuickBooks object fails the response, with QBD_RESPONSE_UNREADABLE, because a record that cannot be identified cannot be updated safely.

  • QuickBooks IDs (id on lists and transactions, line ids) pass through unchanged. They look like 80000012-1730312001 and are at most 36 characters. Store them as strings.
  • IDs are unique within one company file, not across files. Store them together with the end user ID.
  • Our own IDs carry a type prefix: eu_ end users, conn_ connections, req_ requests, authsess_ auth sessions, evt_ webhook events, proj_ projects, org_ organizations. They are sortable by creation time.

Inputs reference other records by ID, in fields named <thing>Id: customerId, itemId, classId, accountId. Outputs return a reference object:

"customer": { "id": "80000012-1730312001", "fullName": "Acme Supply:Warehouse job" }

fullName is the record’s full hierarchical name at the time of the response, with levels separated by colons. Inputs do not accept names, because names change and can be ambiguous across hierarchy levels. Look up an ID by name with a list filter such as fullNames, then use the ID.

A reference to an ID that does not exist, or that points to the wrong kind of record, returns 422 QBD_REFERENCE_NOT_FOUND with param naming the field.

Code When
INVALID_PARAMETER A value breaks the schema: wrong type, out of range, bad format
UNKNOWN_PARAMETER A field the operation does not accept
DECIMAL_PRECISION_EXCEEDED Too many decimal places
STRING_TOO_LONG Text longer than QuickBooks allows
UNSUPPORTED_CHARACTER A character QuickBooks cannot store
FIELD_NOT_CLEARABLE null on a field QuickBooks cannot clear

All of them come back before the request is queued, with outcome: "not_applied". Nothing reaches QuickBooks.