Passthrough and raw qbXML
The typed operations cover the QuickBooks objects most integrations need. qbXML, QuickBooks’ own request language, covers more: deleting list objects, data extensions, to-dos, vehicle mileage, billing rates and other messages. Passthrough sends any qbXML request to the end user’s QuickBooks and returns QuickBooks’ response, with the same queue, request status, idempotency and error handling as every other call.
POST /v1/end-users/{endUserId}/passthrough/quickbooks_desktopThe end user comes from the path, so no Daapi-End-User-Id header is needed.
JSON form
Section titled “JSON form”Send an object whose keys are qbXML request element names. We build the qbXML in the order the schema requires, so you do not need to get element order right.
curl https://api.desktopaccountingapi.com/v1/end-users/eu_01j9.../passthrough/quickbooks_desktop \ -H "Authorization: Bearer $DAAPI_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "CustomerQueryRq": { "MaxReturned": "5", "ActiveStatus": "ActiveOnly" } }'{ "CustomerQueryRs": { "@statusCode": "0", "@statusSeverity": "Info", "@statusMessage": "Status OK", "CustomerRet": [ { "ListID": "80000001-1730311000", "Name": "Acme Supply", "IsActive": "true" } ] }}Conventions in both directions:
- XML attributes become keys starting with
@, such as"@statusCode"and"@iterator". - An element that the schema allows to repeat is an array, even with one item.
- Values are strings, exactly as qbXML writes them (
"true","125.00"). Passthrough does not apply the typed API’s conversions.
XML form
Section titled “XML form”Send Content-Type: application/xml with a <QBXMLMsgsRq> fragment and get the raw <QBXMLMsgsRs> back:
curl https://api.desktopaccountingapi.com/v1/end-users/eu_01j9.../passthrough/quickbooks_desktop \ -H "Authorization: Bearer $DAAPI_SECRET_KEY" \ -H "Content-Type: application/xml" \ --data-binary '<QBXMLMsgsRq><CustomerQueryRq><MaxReturned>5</MaxReturned></CustomerQueryRq></QBXMLMsgsRq>'We add the <?qbxml?> header, the <QBXML> envelope and onError="stopOnError" unless you set onError yourself. The qbXML version is the one negotiated with the end user’s QuickBooks.
Writes and idempotency
Section titled “Writes and idempotency”A body that contains any message other than a query (...QueryRq) is a write. For writes:
- Send an
Idempotency-Key. The fingerprint covers the generated qbXML, so the same key with a different message returns422 IDEMPOTENCY_KEY_REUSED. - We add a
newMessageSetIDso the result can be checked if the response is lost. The same outcome rules apply.
Example: delete a customer, which the typed API handles by deactivation instead.
{ "ListDelRq": { "ListDelType": "Customer", "ListID": "80000042-1730313843" }}Status codes and errors
Section titled “Status codes and errors”Passthrough answers 200 with each message’s own @statusCode, @statusSeverity and @statusMessage, even when one message failed. You read the statuses yourself. Two cases return an error instead:
400 PASSTHROUGH_INVALID_QBXML: the body cannot become valid qbXML, for example an unknown element.- No message was processed at all, for example because the connection is offline or QuickBooks could not open the file. You get the same connection errors as any other call.
With several messages and stopOnError, messages after a failed one return status 3231 (not processed).
When to use passthrough
Section titled “When to use passthrough”- A qbXML message has no typed operation, such as
ListDel,DataExtMod,ToDoAdd,VehicleMileageAdd,TransferInventoryAddorBillingRateQuery. - You need a qbXML option the typed operation does not expose.
- You are porting existing qbXML code and want to move it over before rewriting it.
Prefer typed operations where they exist. They validate input before anything is queued, handle decimals, dates and text encoding for you, paginate safely, and map QuickBooks errors to specific codes.
Passthrough is billed like any other data request, and it counts toward rate limits.