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
- Another computer in the office: turn on Settings > Allowed Connections > Local network, then
set
$env:LC_URL = "http://<machine-name>:8284". The Windows network on the QuickBooks machine must be set to Private or Domain, not Public. - Anywhere else (a server in the cloud, a laptop on the road): use LedgerCrossing Remote, a monthly add-on that gives the machine an HTTPS address, or your own Cloudflare Tunnel. Over Remote, a script using the API key needs Allow the API key turned on (Settings > Allowed Connections > Internet); it's off by default. Internet access also starts read-only, so writes are refused until you allow them.
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
- QuickBooks Desktop Pro, Premier and Enterprise. Supports QuickBooks Desktop 2019 and later. Older versions back to 2014 use the same Intuit connection and should work, though we haven't tested them; the 30-day guarantee covers you.
- Windows 10 and 11, and Windows Server 2016–2025.
- All 240 qbXML operations: queries, adds, mods, deletes and reports.
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]