LedgerCrossingLedgerCrossing Buy LedgerCrossing — $299

Connect PowerShell to QuickBooks Desktop (2026)

Short answer: QuickBooks Desktop has no web API. Every route in, including the Web Connector and ODBC drivers, ends at Intuit's qbXML SDK on the Windows machine where QuickBooks runs. LedgerCrossing runs on that machine and gives it an HTTP endpoint, so PowerShell can use Invoke-RestMethod: send a qbXML request with an X-Api-Key header, and get the QuickBooks response back in the same call. Your script can run on the QuickBooks machine, on another computer in the office, or anywhere through LedgerCrossing Remote or your own tunnel.

Updated November 3, 2026. QuickBooks is a trademark of Intuit Inc.; LedgerCrossing is not affiliated with or endorsed by Intuit.

Your options for PowerShell and QuickBooks Desktop

Option How PowerShell reaches QuickBooks Where your script runs Good to know
Intuit's COM request processor, called directly New-Object -ComObject on Intuit's qbXML request processor Only on the QuickBooks machine Free. Your script opens and closes the connection and session itself, and handles the one-time authorization. 32-bit vs 64-bit and COM registration errors are commonly reported
A QuickBooks ODBC driver System.Data.Odbc with SQL-style queries Wherever the driver is installed and licensed Familiar if you think in tables. Check how it handles writes and what it costs per machine
A commercial cmdlet module (for example CData's QuickBooks Cmdlets) Vendor cmdlets Per the vendor Native PowerShell feel. Check how it reaches Desktop and its licensing
The QuickBooks Web Connector Not directly. The Web Connector polls a SOAP web service that you host Your web service Built for scheduled sync. A script can't call it and get an answer back
LedgerCrossing Invoke-RestMethod to an HTTP endpoint, with an API key The QuickBooks machine, the office network, or anywhere through Remote or a tunnel One-time purchase. Every caller goes through one queue. A validate endpoint checks your qbXML before QuickBooks sees it

How to connect PowerShell to QuickBooks Desktop

1. Install LedgerCrossing on the QuickBooks machine

Run the installer on the Windows computer where QuickBooks Desktop runs, and follow setup. The first time it connects, QuickBooks asks you to allow it: see QuickBooks authorization.

2. Copy the API key

Open Settings > Allowed Connections and copy the API key. Your script sends it in the X-Api-Key header. (Authorization: Bearer <key> works too.)

3. Run your first query

This script lists the first 10 customers. It's Customer-Query.ps1 from our public examples on GitHub (LedgerCrossing/quickbooks-desktop-mcp, examples/http). We ran it on Windows PowerShell 5.1 and PowerShell 7 against Intuit's sample company file, and it returned 10 customers.

# List the first 10 customers from QuickBooks Desktop through LedgerCrossing.
$LcUrl = if ($env:LC_URL) { $env:LC_URL } else { "http://localhost:8284" }
$LcKey = $env:LC_KEY  # API key from Settings > Allowed Connections
if (-not $LcKey) { throw "Set LC_KEY to the API key from Settings > Allowed Connections" }

$qbxml = '<?xml version="1.0"?><?qbxml version="13.0"?><QBXML><QBXMLMsgsRq onError="stopOnError"><CustomerQueryRq><MaxReturned>10</MaxReturned></CustomerQueryRq></QBXMLMsgsRq></QBXML>'

$result = Invoke-RestMethod -Method Post -Uri "$LcUrl/api/v1/qbxml" `
  -Headers @{ "X-Api-Key" = $LcKey } -ContentType "application/json" `
  -Body (@{ qbxml = $qbxml } | ConvertTo-Json)

if ($result.success) { $result.response } else { $result }

Windows blocks PowerShell scripts by default, so set the key and run it like this:

$env:LC_KEY = "paste-your-key-here"
powershell -ExecutionPolicy Bypass -File .\Customer-Query.ps1

The response is QuickBooks' own qbXML, with statusCode="0" when the request succeeded.

Which company file. It depends on Settings > QuickBooks. With Always use this company file, the example works as is. With Use whatever file is open in QuickBooks, open your company file in QuickBooks first. With The caller names the file in each request, add the file to the body:

-Body (@{ qbxml = $qbxml; company_file = "C:\Users\Public\Documents\Intuit\QuickBooks\Company Files\MyCompany.qbw" } | ConvertTo-Json)

4. Run it from another computer

Turn the response into PowerShell objects

The response is XML text, so cast it to [xml] and pipe the records like any other objects. After the query above:

$xml = [xml]$result.response
$xml.QBXML.QBXMLMsgsRs.CustomerQueryRs.CustomerRet |
  Select-Object FullName, Balance |
  Export-Csv .\customers.csv -NoTypeInformation

Check a request before it reaches QuickBooks

qbXML is strict about element order, and QuickBooks rejects a misordered request with a cryptic status. POST /api/v1/validate checks the request against the catalog of 240 qbXML operations without touching QuickBooks, and names the field that's wrong. It accepts raw XML:

$qbxml = '<?xml version="1.0"?><?qbxml version="13.0"?><QBXML><QBXMLMsgsRq onError="stopOnError"><InvoiceQueryRq><MaxReturned>5</MaxReturned><PaidStatus>NotPaidOnly</PaidStatus></InvoiceQueryRq></QBXMLMsgsRq></QBXML>'

$check = Invoke-RestMethod -Method Post -Uri "$LcUrl/api/v1/validate" `
  -Headers @{ "X-Api-Key" = $LcKey } -ContentType "application/xml" -Body $qbxml

if ($check.valid) { "OK to send" } else { $check.issues }

If the request isn't valid, issues says what's wrong and where. For example:

{"success":true,"valid":false,"issues":[{"severity":"error","message":"<MaxReturned> is out of order: …","path":"QBXMLMsgsRq/InvoiceQueryRq/MaxReturned"}]}

When it's valid, send the same request to /api/v1/qbxml exactly as in step 3. That one returns up to five unpaid invoices.

Keep list and transaction queries bounded: MaxReturned, an iterator, or a specific record. Open-ended list and transaction queries are refused by default, before they reach QuickBooks.

Handle errors

Invoke-RestMethod throws on any status other than 2xx. Catch it, then branch on the HTTP status. The wording of error is meant for people and can change.

try {
  $result = Invoke-RestMethod -Method Post -Uri "$LcUrl/api/v1/qbxml" `
    -Headers @{ "X-Api-Key" = $LcKey } -ContentType "application/json" `
    -Body (@{ qbxml = $qbxml } | ConvertTo-Json)
} catch {
  $status = $_.Exception.Response.StatusCode.value__
  $body = $_.ErrorDetails.Message | ConvertFrom-Json
  "HTTP ${status}: $($body.error)"
}

On Windows PowerShell 5.1 the error text can lose anything in angle brackets; the status is reliable.

Status Meaning
400 Malformed request, or an open-ended query
401 Missing or wrong API key (from another computer; requests on the QuickBooks machine itself need no key)
403 Blocked by access rules (read-only, or company-file scope)
409 Conflicts with QuickBooks' current state, for example the file is in use. code says which
429 Queue full or waited too long. Wait for Retry-After and try again

A request QuickBooks itself rejects still comes back as 200, with the error in the qbXML statusCode. The full list of codes is on the API page.

Run it on a schedule

Point Windows Task Scheduler at powershell.exe -ExecutionPolicy Bypass -File C:\path\to\script.ps1, with LC_KEY set for the account the task runs as. The QuickBooks machine has to be on. If QuickBooks may be closed, name the company file (in the request or in Settings): the first call is then slower while LedgerCrossing opens it. For batches, see QuickBooks Desktop API performance.

What it works with

Works with anything that can make a web request. If you rely on an off-the-shelf app that syncs through the Web Connector, that vendor controls the connection, and LedgerCrossing doesn't slip in underneath it.

Frequently asked questions

Can PowerShell connect to QuickBooks Desktop directly? Yes, on the QuickBooks machine, by calling Intuit's COM request processor. Your script then manages the connection, the session and the authorization itself. With LedgerCrossing, PowerShell makes an ordinary HTTP call instead, from that machine or from another one.

Does it work with PowerShell 7? Yes. We ran the examples on this page in both Windows PowerShell 5.1, the version built into Windows, and PowerShell 7.

Can my script create invoices and other records? Yes. All 240 qbXML operations are available, including adds, mods and deletes. Over Remote, internet access starts read-only until you allow writes. If someone has the company file open in QuickBooks on that same computer, requests run in their session, as their QuickBooks user.

Why was my query refused with a 400? Open-ended list and transaction queries are refused by default. Add <MaxReturned>, page with an iterator, or name the record you want.

Do I need the QuickBooks Web Connector? No. LedgerCrossing talks to QuickBooks directly through Intuit's connection on that machine, and your script gets the answer in the same call.

Is there a record of what my scripts did? Yes. LedgerCrossing's audit log records every qbXML request: the source address, the operations and the company file.

Can I use AI agents with the same install? Yes. LedgerCrossing includes an MCP server, so Claude, Cursor, VS Code and other agents go through the same queue and access rules as your scripts. See the MCP quickstart.

What does it cost? $299 one-time per machine, with unlimited company files. No subscription for the API. 30-day money-back guarantee.

[Buy LedgerCrossing]