# Create an AuthSession
POST /auth-sessions
To launch the authentication flow, create an AuthSession and pass the returned session’s `authFlowUrl` to the client for your end-user to visit in their browser.
# The AuthSession object
An AuthSession is the secure way to programmatically launch the client-side Conductor authentication flow that lets your users connect their accounts to your integration.
# Retrieve an AuthSession
GET /auth-sessions/{id}
Retrieves the details of an AuthSession that has previously been created.
# Authentication
The Conductor API uses [API keys](/usage/keys) to authenticate requests.
Your secret API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas such as Git, client-side code, or a public website.
You must make all API calls over HTTPS. Calls that you make over plain HTTP will fail. API requests without authentication will also fail.
Authentication to the API is performed with bearer auth. Provide your API key in the `Authorization` header.
```sh Example authenticated request
curl -X GET https://api.conductor.is/v1/end-users \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}"
```
Use your API key by setting it in the initial configuration of Conductor. The Node.js library then automatically sends this key in each request.
```ts Example authenticated request
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
const endUsers = await conductor.endUsers.list();
```
# Create an EndUser
POST /end-users
Creates an EndUser.
# Delete an EndUser
DELETE /end-users/{id}
Permanently deletes an EndUser object and all of its connections.
# List all EndUsers
GET /end-users
Returns a list of your EndUsers.
# The EndUser object
An EndUser represents a user of your application. Use it to connect integrations.
# Ping an EndUser's connection
GET /end-users/{id}/ping/{integrationSlug}
Checks whether the specified IntegrationConnection can connect and process requests end-to-end. This is useful for showing a "connection status" indicator in your app.
# Send a request to an EndUser's integration connection
POST /end-users/{id}/request/{integrationSlug}
Sends a request to the specified integration connection (e.g. QuickBooks Desktop) on behalf of the end-user.
# Retrieve an EndUser
GET /end-users/{id}
Retrieves an EndUser object.
# The ConductorError object
Every error returned by the Conductor API takes the form of a `ConductorError` object.
### Attributes
The developer error message for your logs.
The user-friendly error message, written specifically for displaying to your end-users in your app's UI.
This value exists for *every* error. E.g., for a QBD connection error, it might recommend the end-user to confirm their QuickBooks Desktop is open and that they're logged in. But if a Conductor API key is expired, e.g., this message will just say *"An internal server error occurred. Please try again later."*.
Categorizes the error. See the possible [error types](/usage/error-handling#error-types).
This value is the same as the subclass name. E.g., `"ConductorIntegrationError"` or `"ConductorInvalidRequestError"`.
The unique error code from Conductor, which is useful for adding special handling for specific errors. E.g., `"RESOURCE_MISSING"`, `"API_KEY_INVALID"`, or `"QBD_REQUEST_ERROR"`.
In contrast, `type` is more general and categorizes the error.
The HTTP status code of the response that included the error.
The unique error code supplied by the third-party integration for errors returned by the integration (i.e., `ConductorIntegrationError`) or integration connector (i.e., `ConductorIntegrationConnectorError`). This is useful for adding special handling for specific errors from the third-party integration or connector.
The integration's corresponding error message for this code is in `error.message`.
The third-party integrations' error codes are not standardized, so you should not rely on this code to be the same across integrations.
The unique identifier for the request that caused the error.
If you need to contact us about a specific request, providing the request identifier will ensure the fastest possible resolution.
```json Example ConductorError object
{
"error": {
"message": "QBD Connection Error (0x80040420): The QuickBooks user
has denied access.",
"userFacingMessage": "We could not connect to QuickBooks Desktop
because we must re-authorize our connection. To fix this, open
QuickBooks Desktop, log in as Admin, navigate to 'Edit >
Preferences > Integrated Applications', click 'Company Preferences',
select our app, click 'Properties...', ensure 'Allow this
application to log in automatically' is checked, then click 'OK'.
Then try again.",
"type": "INTEGRATION_CONNECTION_ERROR",
"code": "QBD_CONNECTION_ERROR",
"httpStatusCode": 502,
"integrationCode": "0x80040420",
"requestId": "req_1234567890"
}
}
```
# Request IDs
Each API request has an associated unique identifier. This identifier is returned in the response headers as `Conductor-Request-Id`. You can use this identifier to track the request in the logs. If you need to contact us about a specific request, providing the request identifier will ensure the fastest possible resolution.
# Timeouts
When you send a request to QuickBooks Desktop through Conductor, Conductor will wait up to four minutes for QuickBooks Desktop to process the request and return a response. While the four-minute timeout might seem long, it is necessary for the following reasons:
1. **Large Data Requests:** Without paginating your requests (via the `MaxReturned` or other range-based parameters), you may unintentionally request tens of thousands of records in a single call. Processing such a large volume of data can take several minutes in QuickBooks Desktop.
2. **Sequential Processing:** QuickBooks Desktop can only process one request at a time. If multiple requests are sent concurrently, they are placed in a queue and processed sequentially, requiring sufficient time for each request to complete before the next one can begin.
3. **Potential Program Startup:** If QuickBooks Desktop is not open but the user’s computer is on, Conductor will automatically launch the program when a request is made. Given that QuickBooks Desktop can take at least 30 seconds to start, adding considerably to the response time.
If you prefer a different timeout period, you can customize it by setting the `Conductor-Timeout-Seconds` request header to your desired value.
**NOTE:** If QuickBooks Desktop is already offline when you send the request, Conductor will immediately return an error without initiating the timeout period.
# How to fix: "Your QuickBooks Desktop connection is not active"
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
If Conductor is unable to sync your QuickBooks Desktop data, you may see the following error:
```
Your QuickBooks Desktop connection is not active. It was last active...
```
This error indicates that Conductor cannot establish a connection with the QuickBooks Web Connector on your computer. The Web Connector is an essential component that comes pre-installed with QuickBooks Desktop. It runs silently in the background, facilitating secure synchronization of your QuickBooks Desktop data with Conductor.
Follow these troubleshooting steps to resolve the issue:
## Troubleshooting your connection
The Web Connector requires your computer to be powered on and connected to the internet. If your computer is off, turn it on and ensure it has an active internet connection before attempting to sync again.
If the error persists, proceed to the next step.
The Web Connector should always be running in the background on your computer. If it's not, launch the program by following these steps:
1. Open QuickBooks Desktop with the company file you want to sync.
2. In the top menu bar, click "**File**" > "**App Management**" > "**Update Web Services**" to launch the QuickBooks Web Connector.
3. In the window that appears, click "**Hide**" in the bottom-right corner to keep the Web Connector running in the background.
After completing these steps, attempt to sync your QuickBooks Desktop data again.
If the error persists, continue to the next step.
If the Web Connector doesn't start automatically with your computer, Conductor may face difficulties in reliably syncing your QuickBooks Desktop data. To ensure automatic startup, [follow this guide](/help/guides/ensure-web-connector-opens-at-startup).
Reopen the Web Connector (following the steps in Step 2) and **confirm that the Auto-Run checkbox next to your connection is ticked**. This setting is required for Conductor to connect to your QuickBooks Desktop.
If the Auto-Run checkbox is not ticked, tick it and click "**Hide**" in the bottom-right corner.
After enabling Auto-Run, attempt to sync your QuickBooks Desktop data once more.
If you continue to receive the "Your QuickBooks Desktop connection is not active" error after completing these steps, please contact our support team at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Connection%20Issue).
# How to fix: "Could not start QuickBooks"
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
If you were directed to this page, it was likely because you encountered the following error attempting to sync with your QuickBooks Desktop:
```
We could not connect to your QuickBooks Desktop because either QuickBooks
Desktop is closed and we could not start it, or an error popped up on your
Windows computer.
```
Alternatively, you might have been directed to this page for the following error *(which is the exact same error; the message above is merely Conductor's user-friendly version)*:
```
(0x80040408): Could not start QuickBooks.
```
## Solution
### 1. Ensure only one version of QuickBooks Desktop is installed
Having multiple versions of QuickBooks Desktop installed on your Windows computer can cause the error above and several other issues. Please [complete this guide to ensure](/help/guides/ensure-only-one-version-installed) only one version of QuickBooks Desktop is installed on your computer. Then, try syncing with QuickBooks Desktop again.
### 2. Do you encounter any of these errors when syncing QuickBooks Desktop?
The first common culprit for the error above is if QuickBooks Desktop is unable to properly open. If QuickBooks Desktop is not open, please open it and try syncing with Conductor again.
If you still see the same error, check if any of the following errors pop up on your Windows computer while attempting to sync with QuickBooks Desktop:
If when syncing with QuickBooks Desktop, a dialog box opens on your Windows computer saying, *"Do you want to allow this app to make changes to your device?"*, then please [complete this guide to resolve that issue](/help/connection-errors/do-you-want-to-allow-this-app-to-make-changes-to-your-device). Then, try syncing with QuickBooks Desktop again.
If when syncing with QuickBooks Desktop, the error shown below popped up on your Windows computer saying, "There was a problem with the log file", then please [complete this guide to resolve that error](/help/connection-errors/there-was-a-problem-with-the-log-file). Then, try syncing with QuickBooks Desktop again.
If either no error appeared on your Windows computer or some other error not listed above appeared, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help). We want to help you resolve this issue and use your experience to improve this guide for others.
# How to fix: "Do you want to allow this app to make changes to your device?"
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
If you ever see the Windows prompt shown below whenever you attempt to sync with QuickBooks Desktop, it is preventing Conductor from syncing with QuickBooks Desktop. To resolve this issue, you must configure QuickBooks Desktop and the QuickBooks Web Connector to run as an administrator. Please follow all of the steps in this guide to resolve this issue.
{/* NOTE: The following solution is identical to `there-was-a-problem-with-the-log-file.mdx` */}
## Solution
To prevent Windows from showing you the prompt above, which blocks Conductor from syncing QuickBooks Desktop, you must configure QuickBooks Desktop and the QuickBooks Web Connector to run as an administrator. To do so, follow the steps below:
### 1. Run QuickBooks Desktop as an administrator
Using Windows search (usually located in the bottom-left corner of your
screen), type "**QuickBooks Desktop**", right-click on the QuickBooks
Desktop result, and select "**Open file location**". If you have QuickBooks
Desktop pinned to your taskbar or on your desktop, you can right-click on
the icon there instead.
In the folder that opens, right-click on the QuickBooks Desktop icon and
select "**Properties**" to open the Properties window.
In the Properties window, navigate to the "**Compatibility**" tab.
Check the box labeled "**Run this program as an administrator**" under the
Settings section.
Click "**Apply**" to save the changes, then click "**OK**" to close the
Properties window.
If QuickBooks Desktop is currently open, close it completely and then
re-open it.
### 2. Run the QuickBooks Web Connector as an administrator
Using Windows search (usually located in the bottom-left corner of your
screen), type "**Web Connector**", right-click on the Web Connector result,
and select "**Open file location**".
In the folder that opens, right-click on the Web Connector icon and select
"**Properties**" to open the Properties window.
In the Properties window, navigate to the "**Compatibility**" tab.
Check the box labeled "**Run this program as an administrator**" under the
Settings section.
Click "**Apply**" to save the changes, then click "**OK**" to close the
Properties window.
Restart your computer to ensure the changes take effect.
By following these steps, QuickBooks Desktop and the Web Connector will always run with administrator privileges, preventing the error from occurring.
If you're still encountering the error after completing all the steps in this guide, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help) for further assistance.
# How to fix: "QBWC1085: There was a problem with the log file"
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
When connecting to QuickBooks Desktop with Conductor, you might encounter the error shown below, which prevents syncing your QuickBooks Desktop data with Conductor. This guide outlines two possible solutions to resolve this issue.
## Solution 1: Delete the QuickBooks Web Connector log file
A corrupted QuickBooks Web Connector log file can cause this error. Deleting the log file will force the Web Connector to generate a new one. To do so, follow these steps:
Ensure QuickBooks Desktop is completely closed.
Terminate the QuickBooks Web Connector process to ensure it is not running in the background:
1. Open the Windows Task Manager by searching for "Task Manager" in the Windows search bar (usually located in the bottom-left corner of your screen).
2. In the Task Manager, find "QuickBooks Web Connector", right-click it, and select "**End Task**". You may need to click "**More details**" at the bottom of the Task Manager window to see all running processes.
3. Close the Task Manager.
Open File Explorer and navigate to the QuickBooks Web Connector log directory by copying and pasting the following path into the address bar:
```
C:\ProgramData\Intuit\QBWebConnector\log
```
In the log directory, locate the file named `QWCLog.txt`, right-click on it, and select "**Delete**".
Restart QuickBooks Desktop and the QuickBooks Web Connector to generate a new log file:
1. Open QuickBooks Desktop with the company file you want to sync.
2. In the top menu bar, click "**File**" > "**App Management**" > "**Update Web Services**" to launch the QuickBooks Web Connector.
3. In the window that appears, click "**Hide**" in the bottom-right corner to keep the Web Connector running in the background.
After completing these steps, attempt to sync your QuickBooks Desktop data again. If the error persists, proceed to Solution 2.
{/* NOTE: The following solution is identical to `do-you-want-to-allow-this-app-to-make-changes-to-your-device.mdx` */}
## Solution 2: Run QuickBooks Desktop and Web Connector as administrator
If the error persists after completing Solution 1, it may be due to QuickBooks Desktop or the QuickBooks Web Connector lacking permission to write to the log file. Running both as an administrator will grant the necessary permissions. To do so, follow these steps:
### 2.1 Run QuickBooks Desktop as an administrator
Using Windows search (usually located in the bottom-left corner of your
screen), type "**QuickBooks Desktop**", right-click on the QuickBooks
Desktop result, and select "**Open file location**". If you have QuickBooks
Desktop pinned to your taskbar or on your desktop, you can right-click on
the icon there instead.
In the folder that opens, right-click on the QuickBooks Desktop icon and
select "**Properties**" to open the Properties window.
In the Properties window, navigate to the "Compatibility" tab.
Check the box labeled "**Run this program as an administrator**" under the
Settings section.
Click "**Apply**" to save the changes, then click "**OK**" to close the
Properties window.
If QuickBooks Desktop is currently open, close it completely and then
re-open it.
### 2.2 Run the QuickBooks Web Connector as an administrator
Using Windows search (usually located in the bottom-left corner of your
screen), type "**Web Connector**", right-click on the Web Connector result,
and select "**Open file location**".
In the folder that opens, right-click on the Web Connector icon and select
"Properties" to open the Properties window.
In the Properties window, navigate to the "Compatibility" tab.
Check the box labeled "**Run this program as an administrator**" under the
Settings section.
Click "**Apply**" to save the changes, then click "**OK**" to close the
Properties window.
Restart your computer to ensure the changes take effect.
By following these steps, QuickBooks Desktop and the Web Connector will always run with administrator privileges, preventing the error from occurring.
If you're still encountering the error after completing all the steps in this guide, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help) for further assistance.
# How to fix: "Unable to cast COM object of type System.__ComObject..."
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
If a Conductor error message directed you to this page, it's because we encountered the following error when attempting to connect to QuickBooks Desktop on your computer:
```
Unable to cast COM object of type 'System.__ComObject' to interface type
'Interop.QBXMLRP2.RequestProcessor2'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{8DB91B17-D5A2-41DB-80A7-CC6F1E449A05}' failed due to the following error:
No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
```
## Solution
Complete the following steps to re-register the QuickBooks Desktop components to resolve this issue:
Ensure QuickBooks Desktop is completely closed.
Using Windows search (usually located in the bottom-left corner of your screen), type "**cmd**", right-click on the "**Command Prompt**" result, and select "**Run as administrator**".
In the PowerShell window, paste the following command and press Enter:
```shell
regsvr32 "C:\Program Files (x86)\Common Files\Intuit\QuickBooks\QBXMLRP2.dll"
```
If the command was successful, restart your computer to ensure the changes take effect. After restarting, try connecting to QuickBooks Desktop again.
If you're still encountering the same error after following these steps, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# How to fix: "QBWC1039: Unique OwnerID/FileID pair value required"
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide will walk you through resolving the following error that occurs when attempting to add a connection to the QuickBooks Web Connector:
This error typically occurs when:
* You previously added a connection to the QuickBooks Web Connector, removed it, and are now attempting to add it again for the same QuickBooks company file.
* You previously added the connection to the QuickBooks Web Connector *on another computer* for the same QuickBooks company file, removed it, and are now attempting to add it *on a different computer*.
#### If you are also getting the "Unhandled exception has occurred" error
In addition to the error above, some users also encounter the following error *at the same time:*
If you are encountering this error as well, we must first force-quit the QuickBooks Web Connector before we can fix the other error at the top of this page. To do this, follow the steps below.
1. Open the Windows Task Manager by searching for "Task Manager" in the Windows search bar (usually located in the bottom-left corner of your screen).
2. In the Task Manager, find the QuickBooks Web Connector, right-click it, and select "**End Task**". You may need to click "**More details**" at the bottom of the Task Manager window to see all running processes.
After force-quitting the QuickBooks Web Connector, continue to the next section to fix the original error for *"Unique OwnerID/FileID pair value required"*.
## Solution
Complete the following steps to fix the error shown above for *"Unique OwnerID/FileID pair value required"*.
Download the [QBWC CP3 tool](https://http-download.intuit.com/http.intuit/CP3Tool/QBWC_CP3Tool.exe?_ga=2.67283025.1765810068.1652776906-1422200743.1652776904), created by Intuit (the makers of QuickBooks Desktop), to address this issue. Open the program ("QBWC\_CP3Tool.exe") from your downloads folder.
In the window that opens, as shown below, click "**Select File**", locate the QWC file that you attempted to open earlier which resulted in the error, and click "**Open**". This file is often found in your downloads folder.
QuickBooks Desktop will prompt you to grant permission to the CP3 Tool to make the necessary changes:
1. In the QuickBooks Application Certificate window that appears, click "**Yes**", then "**Continue**".
2. On the Access Confirmation window, select "**Done**".
3. Follow the instructions, then select "**OK**".
You should receive a confirmation that the Owner ID was removed. Select "**OK**" and close the CP3 tool.
Attempt to open the same QWC file you tried opening earlier. This time, it should work without any errors, and you should see the connection added to the QuickBooks Web Connector.
If you continue to encounter the error after completing these steps or have trouble with any step, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help) for further assistance.
# QuickBooks Desktop FAQ for end-users
An FAQ guide written for the end-users of Conductor's QuickBooks Desktop integration.
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
This FAQ is designed to answer any questions you may have about your QuickBooks Desktop connection and Conductor, the technology provider that powers it.
### How does the integration connect with QuickBooks Desktop?
The integration uses the QuickBooks Web Connector, an built-in feature of QuickBooks Desktop designed for secure data synchronization. This method is officially recommended by QuickBooks and involves robust user authentication and SSL (Secure Socket Layer) encryption. This ensures that your data is encrypted during transmission, protecting it from unauthorized access.
### Do you store any of my QuickBooks Desktop data?
**No, we do not store any of your QuickBooks Desktop data.** The integration acts as a secure conduit, facilitating the transfer of information between your QuickBooks Desktop and the software you are using, without retaining any of that information on our systems.
### What is the QuickBooks Desktop Web Connector?
The QuickBooks Web Connector is a program that comes preinstalled with QuickBooks Desktop that the integration uses to securely sync your data. This program always runs invisibly in the background on your computer and starts automatically whenever you start your computer. If it does not start automatically, the integration cannot reliably sync your data. The only time you should ever see the Web Connector is when you first set up your QuickBooks Desktop connection with the integration; other than that, it should be invisible.
### What security measures does the integration implement to secure data?
Our QuickBooks Desktop integration adheres to the industry's top security practices, including:
* **SSL Encryption:** For secure data transmission.
* **Encrypted API Keys:** Unique keys that ensure only authorized software can access your data.
* **Zero Data Storage Policy:** We don't store your QuickBooks data, maintaining your privacy.
* **Continuous Monitoring:** Our systems are monitored continuously for any unusual activity to prevent unauthorized access.
### Does the integration impact the speed or performance of QuickBooks Desktop?
No, the integration does not slow down QuickBooks Desktop. Here's why:
* The integration is powered by QuickBooks Desktop's built-in Web Connector. When the Web Connector is running in the background, it operates independently of QuickBooks Desktop, much like any other Windows program. In this idle state, it simply waits for new requests without interacting with QuickBooks Desktop.
* Even when processing a request, QuickBooks Desktop's performance would only be impacted if more than 5,000 records were being retrieved at once, however, we prevent this by limiting requests to 500 records at a time.
* The Web Connector is lightweight and only checks for new requests every 10 seconds, making it unlikely to slow down the Windows system as a whole.
* We have never observed or received reports of the integration affecting system performance.
### Which data from QuickBooks Desktop can the integration access?
The integration can read and write most data types in your QuickBooks Desktop, ***excluding* sensitive personal information like Social Security Numbers and customer credit card details**. This broad access is necessary because the QuickBooks Web Connector does not support limited permissions for selective data access.
### Does my computer need to be powered on to sync my QuickBooks Desktop data?
Yes, your computer must be powered on to sync your QuickBooks Desktop data.
### Does QuickBooks Desktop need to be open to sync my data?
No, we can sync your QuickBooks Desktop data even if QuickBooks Desktop is not open. However, if QuickBooks Desktop is open to a different company file, we will return an error.
### Does my computer need to sign in as the Admin user to sync my data?
No, signing in as the Admin user is only required for the initial setup process. After the setup is complete, you can switch back to your regular QuickBooks Desktop user.
### Is it a problem if the Web Connector says "Update postponed by application"?
No, there is no problem at all if you see this message. It means that things are working correctly. This message indicates that the Web Connector has checked for updates, but no sync is necessary at the moment.
### How often does the integration access my QuickBooks data?
The frequency of data access is determined by the software you are using. Typically, data syncs occur when you initiate them (e.g., clicking a "sync" button in your software). For specifics, please contact your software provider.
### Does the integration work with Rightworks (formerly called Right Networks)?
Yes, the integration fully supports QuickBooks Desktop when hosted on Rightworks. For setup instructions, please see our [Connecting to Rightworks guide](/help/guides/rightworks).
### How can I disable the QuickBooks Desktop connection?
Please follow [this guide](/help/guides/disable-connection) to disable the QuickBooks Desktop connection.
### Who is Conductor?
Conductor is a technology provider that powers the QuickBooks Desktop integration for the software you're using. We specialize in creating secure, reliable connections between different software platforms, ensuring your data flows smoothly and safely from QuickBooks Desktop to your business application.
### Any other questions?
If you have any other questions, please check the other guides in the sidebar on the left, contact your software provider, or email us at [support@conductor.is](mailto:support@conductor.is).
# How to disable the QuickBooks Desktop connection
Learn how to disable the QuickBooks Desktop connection in the QuickBooks Web Connector.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
Follow the steps below to disable a QuickBooks Desktop connection in the QuickBooks Web Connector.
1. Open QuickBooks Desktop.
2. In the top menu bar, click "**File**" > "**App Management**" > "**Update Web Services**" to launch the QuickBooks Web Connector.
In the Web Connector window that opens, find the connection for the product or service you want to disconnect, and uncheck the box in the "**Auto-Run**" column for that connection.
We recommend disabling "Auto-Run" instead of clicking "Remove" because the "Remove" button is known to cause issues. Plus, it is convenient to save the old connection's configuration in case you want to restore this connection later.
Finally, click "**Hide**" in the bottom-right corner of the window to close the Web Connector.
Conductor's QuickBooks Desktop connection will no longer run on your computer.
If you encountered any unexpected issues while following these steps, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# Ensure only one version of QuickBooks Desktop is installed
Conductor will not function properly if multiple versions of QuickBooks Desktop are installed on the same computer.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
Having multiple versions of QuickBooks Desktop installed on the same computer can cause issues with Conductor. Often, this prevents the QuickBooks Web Connector from connecting to QuickBooks Desktop or causes it to crash. Please follow the steps below to ensure only one version of QuickBooks Desktop is installed on your computer.
Using Windows search (usually located in the bottom-left corner of your screen), search for "Control Panel", and open it.
In the Control Panel, click on "**Programs and Features**" or "**Uninstall a program**" (exact wording may vary depending on your version of Windows).
In the list of installed programs, look for any versions of QuickBooks Desktop. If you see multiple versions, such as in the example below, continue to the next step. If you only see one version, you can stop here.
Before uninstalling any versions of QuickBooks Desktop, make sure QuickBooks Desktop is completely closed.
Back in the Control Panel window, right-click on the older version(s) of QuickBooks Desktop in the list of installed programs and click "**Uninstall**". Follow the prompts to uninstall the program. For example:
After uninstalling the older version(s), reopen QuickBooks Desktop and follow any prompts for updates.
1. If QuickBooks Desktop asks you to fix the installation, click "**Continue**".
2. If QuickBooks Desktop asks you to reboot after fixing the installation, click "**OK**".
By following these steps, you can ensure only one version of QuickBooks Desktop is installed on your computer, which will help prevent issues with Conductor.
# Ensure the QuickBooks Web Connector opens at startup
Set up the QuickBooks Web Connector to automatically launch and run in the background whenever you start your computer.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
The QuickBooks Web Connector is a program that comes preinstalled with QuickBooks Desktop that Conductor uses to securely sync your data. This program always runs invisibly in the background on your computer and starts automatically whenever you start your computer. If it does not start automatically, Conductor cannot reliably sync your data.
If you are having trouble syncing your data, please follow the steps below to ensure that the Web Connector starts automatically when you start your computer. If we discover it does not, we will configure the Windows Task Scheduler to start the Web Connector automatically.
## 1. Check if the Web Connector starts automatically when you start your computer
First, let's check whether the Web Connector starts automatically when you start your computer:
Restart your computer so we can check in the next step whether the Web Connector automatically starts when your computer starts.
After your computer finishes booting up, the Web Connector should automatically start invisibly in the background. Let's check if it is running:
1. Open the Windows Task Manager by searching for "Task Manager" in the Windows search bar (usually located in the bottom-left corner of your screen).
2. If you see a "More details" button in the bottom-left corner of the Task Manager window, click it to expand the Task Manager.
3. Navigate to the "Details" tab and scroll down until you see the "QBWebConnector.exe" process which should look like the screenshot below. **If you see it, you can skip the rest of this guide. Otherwise, continue to the section below.**
## 2. Configure the Web Connector to start automatically using the Windows Task Scheduler
After confirming that the Web Connector does not start automatically when you start your computer in the previous section, we will now configure the Windows Task Scheduler to start the Web Connector automatically.
Open the Windows Task Scheduler by searching for "Task Scheduler" in the Windows search bar (usually located in the bottom-left corner of your screen).
In the Task Scheduler, go to the "Action" menu and select "**Create Task**".
In the "General" tab of the new task window:
1. Enter any name for your task, such as "Open QuickBooks Web Connector".
2. Check the option "**Run with highest privileges**" near the bottom to ensure the task runs with administrator rights.
Go to the "**Triggers**" tab and click "**New**".
1. Under "Begin the task", select "**At startup**" from the dropdown menu.
2. Set a delay for 1 minute by checking "Delay task for" and choose "1 minute".
Finally, click "**OK**".
1. Using Windows search (usually located in the bottom-left corner of your screen), type "**Web Connector**", right-click on the Web Connector result, and select "**Open file location**".
2. In the folder that opens, you should see a shortcut for the Web Connector. Right-click on the Web Connector icon and select "**Properties**" from the context menu to open the Properties window.
3. In the Properties window, as shown below, copy the file path in the "**Target**" field. You can do this by selecting the text and pressing `Ctrl + C` on your keyboard. Then click "**Cancel**" to close the Properties window.
Go back to the Task Scheduler window and go to the "Actions" tab. Click "**New**" and paste the file path you copied in the previous step into the "**Program/script**" field by right-clicking and selecting "**Paste**" from the context menu. Then click "**OK**".
In the "Settings" tab, check the option "**If the task fails, restart every**" and set the value to "**1 minute**" and the "**Attempt to restart up to**" value to "**3 times**". Then click "**OK**".
Click "**OK**" to save your new task. You might be prompted to enter an administrator password at this point.
Finally, test your task by restarting your computer, waiting one minute, and confirming that the QuickBooks Web Connector opened automatically after startup using [the same steps as in the first section of this guide](/help/guides/ensure-web-connector-opens-at-startup#1-check-if-the-web-connector-starts-automatically-when-you-start-your-computer).
By following these steps, the QuickBooks Web Connector will now always start automatically whenever you start your computer.
If you're still having trouble after completing all steps, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# Move your QuickBooks Desktop connection to a different computer
Learn how to transfer your QuickBooks Desktop connection to a different computer for the same company file.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
Before setting up the new connection, follow [this guide to disable the existing connection](/help/guides/disable-connection) on your **current** computer.
It is essential that you complete this step first to avoid synchronization conflicts with your new computer's connection.
1. Launch QuickBooks Desktop on your **new** computer.
2. Open the company file you want to connect.
3. Log in using your QuickBooks **Admin** user credentials.
Ensure you're using the exact same company file as before. The file path can be different, but it must be the same QuickBooks company file.
Return to the setup guide, click **"Download config file"**, and then the downloaded configuration file.
QuickBooks Desktop might *not* show the permissions prompt when adding the new connection because you previously authorized access to this company file on your old computer. This is normal and doesn't indicate any problem with the setup.
Follow the remaining steps in the setup guide. When complete, the final step of the guide will confirm that the connection is successful.
You have now successfully moved your connection to a different computer.
If you encountered any unexpected issues while following these steps, please email us at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# Connect to multiple QuickBooks company files on a single computer
How to connect to multiple QuickBooks Desktop company files on a single computer.
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
In QuickBooks Desktop, a **company file** is the primary local file that stores all financial data for a specific company. While most QuickBooks Desktop users have only one company file, some users, such as accounting firms managing finances for multiple clients, work with several company files on a single computer. This guide will walk you through connecting Conductor (which powers your integration) to multiple company files on a single computer, as well as best practices and performance considerations.
## Important requirement
**QuickBooks Desktop must always remain open *without* any company file loaded
when connecting to multiple company files on a single computer.** This setup
allows the Web Connector to open the correct company file when it receives a
request from your QuickBooks Desktop integration.
### Why is this necessary?
The [QuickBooks Web Connector](/help/faq/end-user-faq#what-is-the-quickbooks-desktop-web-connector) has certain limitations when working with multiple company files on a single computer:
1. It can only communicate with one company file at a time.
2. It can only communicate with the company file that is currently open in QuickBooks Desktop.
3. It cannot switch between company files if QuickBooks Desktop already has a different company file open (to avoid disrupting an active user).
Despite these limitations, **the Web Connector can open a specified company file if no other company file is currently open, fulfill the request, and then close the company file** without fully closing QuickBooks Desktop. Therefore, keeping QuickBooks Desktop open without any company file loaded allows the Web Connector to open and process requests for the correct company file as needed.
### How to close a company file
To ensure QuickBooks Desktop is open without any company file loaded:
1. Open **QuickBooks Desktop**.
2. Go to the "**File**" menu.
3. Select "**Close Company**".
![QuickBooks Desktop without any company file
loaded](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/help/guides/multiple-connections-one-computer/qbd-no-company-open.jpg)
If you or someone else opens a company file *on this machine* without returning QuickBooks Desktop to this state, you may encounter an error stating that the wrong company file is open.
## How to set up connections to multiple company files
To connect to multiple company files on one computer, you must complete the setup process **for each company file**, as each requires its own connection and authentication.
1. Open **QuickBooks Desktop**.
2. Open the company file you wish to connect.
3. Sign in as the **Admin** user.
4. Complete the setup guide *while* the corresponding company file is open.
5. Repeat steps 1-4 for each company file.
Once complete, each company file will have a separate connection in the Web Connector, resembling the state shown below:
![QuickBooks Web Connector with multiple
connections](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/help/guides/multiple-connections-one-computer/web-connector-multiple-connections.jpg)
## Best practices
* **Use a dedicated virtual machine (optional):** Many users managing multiple company files on a single computer set up an always-on virtual machine dedicated to fulfilling Conductor requests. This dedicated instance allows QuickBooks Desktop to remain open without a company file loaded, ready to receive requests and open the correct company file. This setup is preferable to sharing a personal computer used for other tasks, where the Web Connector cannot fulfill requests if the wrong company file is open.
* **Add QuickBooks Desktop to Windows startup:** Adding QuickBooks Desktop to the computer's startup programs ensures it is always open and ready to receive requests whenever you restart the computer. The Web Connector already automatically starts in the background when the computer boots up and can open QuickBooks Desktop if it receives a request from Conductor while QuickBooks Desktop is closed; however, doing so will delay the request because QuickBooks Desktop takes a while to launch.
## Performance considerations
* **Increased request time:** Keeping QuickBooks Desktop open without a company file loaded adds 20–30 seconds to each request due to the time it takes to load a company file. However, when you send numerous Conductor requests for the same company file in quick succession, the Web Connector will resolve the sequence rapidly because Conductor keeps the company file open between these requests.
* **Serial processing:** The Web Connector can only process requests for one company file at a time because it can only communicate with QuickBooks Desktop when one company file is loaded. Therefore, Conductor manages your requests in a queue, ensuring that the Web Connector processes them serially, opening and closing the appropriate company file for each request.
# Rebuild and verify Data in QuickBooks Desktop
Learn how to use the Rebuild and Verify Data utilities to fix and identify data issues in your QuickBooks Desktop company file.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
Over time, your QuickBooks Desktop company file may accumulate data issues that can lead to unexpected behavior or errors. QuickBooks provides built-in tools—**Rebuild Data** and **Verify Data**—to help fix and identify these issues. This guide will walk you through the steps to rebuild and verify your company file to ensure data integrity.
**When to use these utilities:** Use the **Rebuild Data** utility if you
experience symptoms like missing transactions, program crashes, balance sheet
discrepancies, or other unexpected behaviors. After rebuilding your data, use
the **Verify Data** utility to confirm that all issues have been resolved.
Use the Rebuild Data utility to fix data issues in your company file:
1. Open QuickBooks Desktop.
2. Go to the "**File**" menu, hover over "**Utilities**", and select "**Rebuild Data**".
3. When prompted to back up your company file, click "**OK**". QuickBooks will ask you to create a backup before rebuilding to prevent data loss.
4. Choose a location to save the backup, then click "**OK**".
5. QuickBooks will begin rebuilding your data. This may take some time, depending on the size of your company file.
6. Once the rebuild is complete, click "**OK**" when you see the message "Rebuild has completed".
After rebuilding your data, use the Verify Data utility to confirm that all issues have been resolved:
1. Go to the "**File**" menu, hover over "**Utilities**", and select "**Verify Data**".
2. QuickBooks will begin scanning your company file. This may take a few minutes.
After the verification process completes, QuickBooks will display a message:
* **If you see "QuickBooks detected no problem with your data":** Your company file is now repaired and in good shape.
* **If you see "Your data has lost integrity":** Data issues still exist, repeat the rebuild process.
* **If you see a specific error message or code:** Note the details as they may be helpful if you need to contact support.
**Note:** If errors continue after rebuilding your data multiple times, your company file may be damaged beyond repair through these utilities. Please contact Intuit support for further assistance.
By following these steps, you've ensured that your QuickBooks Desktop company file is free of data issues. If you encounter any problems during this process or need additional assistance, please contact our support team at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# Connecting to Rightworks
How to set up the QuickBooks Web Connector to connect to QuickBooks Desktop when using Rightworks.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
Rightworks (formerly called Right Networks) is a hosting provider for QuickBooks Desktop, offering remote access to a QuickBooks Desktop instance. We fully support connecting to Rightworks; however, there is **one important limitation you must remember**:
**Important:** To sync data with your QuickBooks Desktop, you must be actively
connected to your Rightworks remote desktop session with QuickBooks Desktop
open. This requirement is due to Rightworks preventing programs from running
in the background after you disconnect.
**One more requirement for setup:** You must also configure your Rightworks account to allow the QuickBooks Web Connector (a built-in program we use to connect to QuickBooks Desktop) to start automatically whenever you connect to Rightworks. Please follow the steps below to configure this.
## Required: Enable the Web Connector to start automatically
Follow the steps below to configure the Web Connector to start automatically when you log into Rightworks.
If this guide does not work for you, please [contact
us](mailto:support@conductor.is?subject=Rightworks%20Help) so we can continue
to improve it. There are many different versions of Rightworks, and there
might be steps missing that we would like to add.
To configure the Web Connector to start automatically, you must contact Rightworks support. This cannot be done on your own. Visit the [Rightworks Support](https://helpdesk.rightnetworks.com) page to get started.
Rightworks support is available Monday - Friday, 8:00 AM - 8:00 PM ET.
On the Rightworks support page, click the yellow "Chat" bubble in the bottom-right corner to start a live chat (there is no email or phone support available for this task).
In the chat window, **provide the full name and email address** associated with your Rightworks account. This is typically the information for the person at your company who set up your Rightworks account.
**Copy and send** the entire message below to the Rightworks support agent:
```
Hello! Could you please configure our Rightworks account to ensure
that BOTH of the following applications are added to our startup
items and automatically launch in the background every time we sign
into our Rightworks instance?
1. QuickBooks Web Connector
2. QuickBooks Desktop
We need BOTH applications to launch automatically.
Please apply this setting for ALL USERS on our Rightworks account.
```
1. Wait for the support agent to confirm that the Web Connector has been added to your startup programs.
2. Sign out and sign back into your Rightworks desktop session for the changes to take effect.
That's it! From now on, the QuickBooks Web Connector will automatically start every time you connect to Rightworks, ensuring a stable connection to your QuickBooks Desktop company file.
# Upgrade the QuickBooks Web Connector
Learn how to upgrade the QuickBooks Web Connector to ensure compatibility with Conductor.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
This guide is provided by Conductor, the service that powers the QuickBooks
Desktop integration for many business tools, including the one that sent you
here.
The QuickBooks Web Connector is a vital component that comes pre-installed with QuickBooks Desktop. Conductor uses this tool to securely sync your data. To use Conductor, you must have at least **version 2.3.0.20** of the QuickBooks Web Connector installed. In our experience, fewer than 1% of users have an older version. If you're using an outdated version, you might see an error message like this:
Follow these steps to upgrade the QuickBooks Web Connector to the latest version:
Ensure that QuickBooks Desktop is completely closed before proceeding.
Close the QuickBooks Web Connector process to ensure it's not running in the background:
1. Open the Windows Task Manager by pressing `Ctrl + Shift + Esc` or by searching for "Task Manager" in the Windows search bar.
2. In the Task Manager, locate "QuickBooks Web Connector". Right-click it and select "**End Task**". If you don't see it, click "**More details**" at the bottom of the Task Manager window to view all running processes.
3. Close the Task Manager.
To upgrade, you must first delete the current installation:
1. Open File Explorer and navigate to `C:\Program Files (x86)\Common Files\Intuit\QuickBooks`.
2. Delete the folder named `QBWebConnector` and, if present, the folder named `QBWebConnector3.0`.
Visit Intuit's [official download page](https://developer.intuit.com/app/developer/qbdesktop/docs/get-started/get-started-with-quickbooks-web-connector#download-and-install-the-quickbooks-web-connector) to get the latest version of the QuickBooks Web Connector. Always download the most recent version, even if you're using an older version of QuickBooks Desktop.
Once the download is complete, open the downloaded file and follow the installation wizard's instructions.
1. Open QuickBooks Desktop.
2. In the top menu bar, click "**File**" > "**App Management**" > "**Update Web Services**" to launch the QuickBooks Web Connector.
3. In the window that appears, click "**Hide**" in the bottom-right corner to keep the Web Connector running in the background.
You have now successfully upgraded to the latest version of the QuickBooks Web Connector and can proceed with setting up your connection to Conductor. If you encounter any issues during this process, please don't hesitate to contact our support team at [support@conductor.is](mailto:support@conductor.is?subject=QuickBooks%20Desktop%20Help).
# FAQ
The fundamentals of Conductor.
## Conductor basics
Conductor is a web service that securely connects your app to one or more QuickBooks Desktop instances. It provides a RESTful API and fully-typed client libraries that you can use to read and write data to/from QuickBooks Desktop.
Behind the scenes, Conductor uses the QuickBooks Web Connector, which is a Windows SOAP-based program that comes preinstalled with QuickBooks Desktop on your end-users' computers. This program always runs invisibly in the background, waiting for requests from Conductor. When you send a request to Conductor, it forwards the request to the Web Connector, which then forwards the request to QuickBooks Desktop. The response follows the same path in reverse. Between each of those steps, there are many layers of error handling, validation, and data transformation.
Conductor abstracts away all of the complexity, idiosyncrasies, and fragility of working with QuickBooks Desktop so that interfacing with this criminally outdated technology is as easy and wonderful as using Stripe's API.
Conductor leverages a program called QuickBooks Web Connector, which comes preinstalled with all versions of QuickBooks Desktop and runs invisibly in the background on the Windows computer to maintain the connection. To connect, the QuickBooks Desktop users will step through Conductor's [authentication flow](/usage/auth-flow), which has them download a config file that Conductor generates, open it in the Web Connector, authenticate, and connect to Conductor (and thereby to your application). Here is a [demo of the auth flow](https://connect.conductor.is/qbd/demo).
Conductor is priced at **\$49 month for each active QuickBooks Desktop company file connection**. A connection is considered active if *both* of the following conditions are met within the same monthly billing period:
1. Conductor receives a heartbeat from the QuickBooks Desktop instance.
2. Your application makes a Conductor API call to that connection.
NOTE: Connections used for testing and development are free. Connections using data from an active production environment are not.
Volume discounts are available for enterprises requiring a large number of connections.
Integrating with QuickBooks Desktop from scratch is a painful nightmare. It's a decades-old API that hasn't been modernized and is riddled with edge cases, idiosyncrasies, and bugs that are incredibly difficult to work with. Conductor solves all of these problems and takes only a fraction of the time to implement with none of the maintenance headaches. We have obsessed over the edge cases and performance. Beyond the significant time savings, **Conductor preserves your team's mental well-being**.
## Data handling and security
No, every Conductor API call is a real-time direct request to/from QuickBooks Desktop. If you make a request when the end-user's computer is off or QuickBooks Desktop is inaccessible, Conductor will return an error message with instructions for how the end-user can resolve the issue.
By design, Conductor has no cache layer because it causes all sorts of problems when data is out-of-sync. E.g., you modify data on one end that has already been removed on the other.
Ideally, the computer running QuickBooks Desktop is always on and accessible. If that is not possible for some end-users, this design has still worked well because if such an end-user triggers a sync while using your app, they likely did so from the same computer as where QuickBooks Desktop is already running.
No, Conductor does not retain any of your end-users' QuickBooks Desktop data on a permanent basis. For operational purposes, API request logs, which includes QuickBooks Desktop data, are temporarily, securely stored in a SOC 2 and GDPR-compliant log manager for 14 days before permanent deletion. Access to these logs is strictly limited to authorized Conductor engineers, who use them solely for debugging, offering customer support, and product improvement purposes. This approach ensures both the confidentiality of your data and compliance with the highest standards of data protection.
No, Conductor's APIs currently only support working with a single object at a time because QuickBooks Desktop itself only resolves requests serially. If you want to create 50 invoices, for example, you will need to call the create-invoice API 50 times. However, you can send multiple requests in parallel; for example, you can use `await Promise.all([ ... ])` in JavaScript with multiple requests, but you cannot send multiple requests in a single HTTPS request.
## QuickBooks Desktop and Web Connector
The QuickBooks Web Connector is a Windows program that comes preinstalled with QuickBooks Desktop that Conductor uses to securely communicate with QuickBooks Desktop. This program runs invisibly in the background on the end-user's computer, waiting for requests from Conductor. The only time your end-user should see the Web Connector is when they first set up their QuickBooks Desktop connection with Conductor; other than that, it should be invisible to them.
In the world of QuickBooks Desktop, a "company file" is the main local file for all the financial data for a specific company. Typically, a QuickBooks Desktop user will have only one company file: the one they use to manage their business. However, some users manage multiple company files on one computer and actively switch between them. For example, an accounting firm might manage the books for multiple clients, each with their own QuickBooks Desktop company file.
Each Conductor connection is tied to a specific company file. If you need to connect to multiple company files, you will need to create multiple EndUsers in Conductor, each with their own connection. See this [guide](/help/guides/multiple-connections-one-computer) for more information.
Conductor supports every version, variant, and edition of QuickBooks Desktop since 2018, including:
* **QuickBooks Enterprise Solutions - any version or year**
* Any edition: Accountant, Contractor, Manufacturing and Wholesale, Nonprofit, Professional Services, Retail.
* **QuickBooks Premier (Plus) - 2018 or later**
* Any edition: Accountant, Contractor, Manufacturing and Wholesale, Nonprofit, Professional Services, Retail.
* **QuickBooks Desktop Pro (Plus) - 2018 or later**
* **QuickBooks Accountant Desktop (Plus) - 2018 or later**
No, QuickBooks Desktop is not being discontinued.
1. **Ongoing Support:** Intuit continues to support all existing versions of QuickBooks Desktop for current customers.
2. **Continued Sales:** Intuit is still actively selling "QuickBooks Enterprise", the main version of QuickBooks Desktop tailored for medium to large businesses, to new customers.
3. **Product Changes:** Intuit will soon cease sales of "QuickBooks Desktop Pro/Premier Plus" – a less popular variant primarily used by small family businesses – to *new* customers (existing customers will still be supported).
While Intuit has encouraged users to migrate to QuickBooks Online, Desktop users consistently tell us that it doesn't fully meet their business needs. Consequently, the base of existing QuickBooks Desktop users, including both "Enterprise" and "Pro/Premier" versions, remains robust. Conductor continues to support these users and their ongoing reliance on QuickBooks Desktop.
## Compatibility and connectivity
Yes, you can set up Web Connector connections on multiple computers for the same QuickBooks Desktop company file. This is applicable if your company shares the same company file across multiple computers on your office network. This setup can serve as a backup in case one computer is offline. However, we haven't seen any Conductor users needing this approach so far, but we have confirmed that it works.
No, there is no way to access QuickBooks Desktop instances when the user's computer is off because QuickBooks Desktop data is not stored online. Instead, QuickBooks Desktop is a local application that runs on a user's computer. As a result, this means an active Conductor connection is always direct and real-time. Conductor intentionally avoids using a cache layer to prevent potential data conflicts when data is out-of-sync.
While this may seem limiting to many developers, we find that typical QuickBooks Desktop users do not mind:
1. **User Availability:** When a user is interacting with your application that syncs data with QuickBooks Desktop, they are typically at their computer anyway, which means that QuickBooks Desktop is accessible.
2. **User Control:** Many QuickBooks Desktop users are protective of their data and prefer to manually initiate data syncs rather than rely on automatic background processes. This approach gives them greater control over their data and ensures that no syncs occur without their explicit consent.
No, QuickBooks Desktop does not need to be actively open. As long as the computer itself is powered on, Conductor can send a request to QuickBooks Desktop, which will then automatically launch in the background, process the request, and close itself once completed.
**Important Note:** Launching QuickBooks Desktop in the background adds approximately 30 seconds to the request processing time due to the software's startup process. For optimal faster response times, we recommend keeping QuickBooks Desktop open while using Conductor.
Yes, please see this [guide](/help/guides/multiple-connections-one-computer) for more information.
Yes, Conductor is fully compatible with Rightworks. Users can establish the connection just as they would with a typical Windows instance running QuickBooks Desktop.
However, there is an important consideration: Rightworks users must sign in to their remote desktop session each time they wish to sync with QuickBooks Desktop. This requirement exists because Rightworks terminates inactive instances once the connection is closed, preventing background processes from running when the user is signed out. Despite this, most users find this process manageable because signing in to Rightworks is a routine part of their workflow. It is worth noting that, based on our experience, remote QuickBooks Desktop hosts like Rightworks account for fewer than 2% of all QuickBooks Desktop companies.
Please see [this guide](/help/guides/rightworks) for setting up a Conductor connection with a Rightworks QuickBooks Desktop instance.
# Get started with Conductor
The best QuickBooks Desktop integration on the planet.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
## What is Conductor?
Conductor is a real-time, fully-typed API for QuickBooks Desktop (sometimes called QuickBooks Enterprise), available via Python, Node.js, TypeScript, and REST. In just a few lines, get real-time access to fetch, create, or update [*any* QuickBooks Desktop object type](/qbd/api#supported-object-types) and receive a fully-typed response. Check out the documentation below to get started.
Conductor, the company, is building a data integration platform for vertical SaaS companies, starting with QuickBooks Desktop. Our team has spent over a decade building companies, scaling vast software systems, and obsessing over quality.
## Key features
* **Any data type:** Query, create, or update any QuickBooks Desktop data type.
* **Real-time**: Get real-time updates on your QuickBooks Desktop data. No queues, no polling.
* **Modern API:** JSON-based REST API, replacing the old XML-based SOAP model.
* **Typed client libraries:** Fully typed libraries in Node.js and Python with autocomplete, inline docs, and type validation for endpoints, parameters, and responses.
* **Request handling:** Invisibly manages queues, timeouts, retries, and pagination.
* **Multi-company support:** Connects to multiple QuickBooks Desktop company files.
* **Validation:** Sanitizes and validates all inputs and outputs.
* **Unified error handling:** Streamlines error handling across the QuickBooks stack.
* **Authentication flow UI:** Simple UI for securely connecting QuickBooks Desktop accounts.
* **Dashboard**: UI to monitor and manage your QuickBooks Desktop connections and data.
* **Error resolution:** Detailed guides and instructions for resolving errors and handling edge cases.
## Explore the documentation
Create your first EndUser and connect to QuickBooks Desktop in 5 minutes.
The key concepts you must know to use Conductor.
Execute any QuickBooks Desktop API through fully-typed async TypeScript.
Access Conductor's REST API to connect to QuickBooks Desktop from any
language.
Catch and respond to connection errors, invalid requests, data problems, and
more.
# Quickstart
Create your first EndUser and connect to QuickBooks Desktop in 5 minutes.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
The following server-side walkthrough will guide you through connecting a QuickBooks Desktop instance to your Conductor account. In just a few minutes, you'll be able to create, read, and update data in your QuickBooks Desktop instance.
#### Requirements
1. A Conductor API key pair: one secret key, one publishable key. To obtain these, please [join our private beta](https://73a5v9t55ed.typeform.com/to/VRX7rfrN).
2. A QuickBooks Desktop instance for testing. If you do not have one, you can [create a free test instance](/qbd/test-instance).
## Create your first EndUser and IntegrationConnection
```sh npm
npm install conductor-node
```
```sh yarn
yarn add conductor-node
```
```sh pnpm
pnpm add conductor-node
```
```sh
pip install --pre conductor-py
```
Continue to the next step to access our REST API directly via `curl`.
An EndUser is a user of *your* application for whom we are creating an IntegrationConnection. Each EndUser can represent an individual or an entire company/organization of multiple users within your application. You can attach one or more IntegrationConnections to this EndUser.
After you create your EndUser, you must save the EndUser's `id` to your database for sending requests to their IntegrationConnections in the future.
For example, if your database has a `users` table, you can store the `id` in a column like `conductor_end_user_id`.
Either create the EndUser via the web dashboard or use the following code on your server to create an EndUser programmatically:
```ts Node.js
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
// Replace these placeholders with your own values.
const endUser = await conductor.endUsers.create({
// Your end-user's company name shown elsewhere in Conductor.
companyName: "{{END_USER_COMPANY_NAME}}",
// Your end-user's unique ID from _your_ database. Must be distinct from
// your other EndUsers. Can be anything you want if you are just testing.
sourceId: "{{UNIQUE_ID_FROM_YOUR_DB}}",
// Your end-user's email address for identification purposes.
email: "{{END_USER_EMAIL}}",
});
console.log("Save this EndUser ID to auth future requests:", endUser.id);
```
```py Python
from conductor import Conductor
conductor = Conductor(api_key="{{YOUR_SECRET_KEY}}")
# Replace these placeholders with your own values.
end_user = conductor.end_users.create(
# Your end-user's company name shown elsewhere in Conductor.
company_name="{{END_USER_COMPANY_NAME}}",
# Your end-user's unique ID from _your_ database. Must be distinct from
# your other EndUsers. Can be anything you want if you are just testing.
source_id="{{UNIQUE_ID_FROM_YOUR_DB}}",
# Your end-user's email address for identification purposes.
email="{{END_USER_EMAIL}}"
)
print("Save this EndUser ID to auth future requests:", end_user.id)
```
```sh cURL
curl -X POST https://api.conductor.is/v1/end-users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"companyName": "{{END_USER_COMPANY_NAME}}",
"sourceId": "{{UNIQUE_ID_FROM_YOUR_DB}}",
"email": "{{END_USER_EMAIL}}"
}'
```
This API call will return the newly created EndUser object, for example:
```json Example EndUser response {2-3}
{
// ❗❗ Save this `id` to your database!
"id": "end_usr_1234567abcdefg",
"objectType": "end_user",
"createdAt": "2022-11-16 23:51:08.996+00",
"companyName": "Big Construction Co.",
"sourceId": "12345678-abcd-abcd-example-1234567890ab",
"email": "bob@bigconstruction.com",
"integrationConnections": []
}
```
Before you can read/write data to/from an EndUser's IntegrationConnection, your EndUser must complete the connection authentication flow. The following operation creates a session and returns a URL to redirect your end-user.
```ts Node.js
// ... continued from above
const authSession = await conductor.authSessions.create({
publishableKey: "{{YOUR_PUBLISHABLE_KEY}}",
// Use `endUser.id` from above.
endUserId: endUser.id,
});
console.log("Complete the QuickBooks Desktop auth flow:", authSession.authFlowUrl);
```
```py Python
# ... continued from above
auth_session = conductor.auth_sessions.create(
publishable_key="{{YOUR_PUBLISHABLE_KEY}}",
end_user_id=end_user.id
)
print("Complete the QuickBooks Desktop auth flow:", auth_session.auth_flow_url)
```
```sh cURL
curl -X POST https://api.conductor.is/v1/auth-sessions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"publishableKey": "{{YOUR_PUBLISHABLE_KEY}}",
"endUserId": "{{END_USER_ID_FROM_ABOVE}}"
}'
```
```json Example AuthSession response {6-7}
{
"id": "auth_sess_1234567abcdefg",
"endUserId": "end_usr_1234567abcdefg",
"clientSecret": "auth_sess_client_secret_1234567abcdefg",
"expiresAt": "2022-11-16 23:51:08.996+00",
// 👇 Visit this URL from the response to launch the authentication flow.
"authFlowUrl": "https://connect.conductor.is/qbd/auth_sess_client_secret_1234567abcdefg?key={{YOUR_PUBLISHABLE_KEY}}"
}
```
Visit the returned `authSession.authFlowUrl` in your browser on the same computer or instance as your QuickBooks Desktop installation. This authentication flow will guide you through connecting your QuickBooks Desktop instance to Conductor.
After completing the authentication flow, you can access your QuickBooks Desktop instance through the Conductor library. The following example fetches a list of invoices from your QuickBooks Desktop instance.
```ts Node.js
// ... continued from above
const qbdInvoices = await conductor.qbd.invoice.query(endUser.id, {
MaxReturned: 10,
});
console.log("QBD invoices:", qbdInvoices);
```
```py Python
# ... continued from above
qbd_invoices = conductor.qbd.invoices.list(
conductor_end_user_id=end_user.id,
limit=10,
)
print("QBD invoices:", qbd_invoices)
```
```sh cURL
curl --request GET \
--url 'https://api.conductor.is/v1/quickbooks-desktop/invoices?limit=10' \
--header 'Authorization: Bearer {{YOUR_SECRET_KEY}}' \
--header 'Conductor-End-User-Id: {{END_USER_ID_FROM_ABOVE}}'
```
```json Example QBD response
{
"objectType": "list",
"url": "/v1/quickbooks-desktop/invoices",
"data": [
{
"id": "123ABC-1234567890",
"objectType": "qbd_invoice",
"createdAt": "2021-10-01T17:34:56.000Z",
"updatedAt": "2021-10-01T20:45:30.000Z",
"revisionNumber": "1721172183",
"customer": {
"id": "80000001-1234567890",
"fullName": "Acme Corporation"
},
"invoiceLines": [
{
"id": "456DEF-1234567890",
"objectType": "qbd_invoice_line",
"item": {
"id": "80000010-1234567890",
"fullName": "Widget A"
},
"description": "High-quality widget with custom engraving",
"quantity": 5,
"amount": "1000.00",
// ... more fields omitted
}
],
// ... more fields omitted
},
// ... more invoices omitted
],
"nextCursor": "12345678-abcd-abcd-example-1234567890ab",
"remainingCount": 10,
"hasMore": true
}
```
# Security and data retention
Conductor's security and data retention policies.
### Temporary data storage
* **Conductor does not permanently retain your end-user data (such as QuickBooks Desktop data).**
* **For operational purposes, API request logs, which include end-user data, are temporarily stored securely in a SOC 2 compliant log manager for 14 days before permanent deletion.**
* The logs are encrypted at rest using AES-256 and in transit using HTTPS/TLS.
* The logs are stored in certified data centers located in Germany and Finland within the EU.
* Access to these logs is strictly limited to authorized Conductor engineers, who use them solely for debugging, customer support, and product improvement.
### Permanent data storage
* The only data Conductor stores permanently pertains to managing and authenticating your Conductor account, connections, end-users, API keys, and projects. This does not include any end-user data.
* This data is stored in a centralized SOC 2 compliant database hosted by AWS in the US West (Oregon) region. There is no physical or logical separation of customer data within the database.
* The database is encrypted at rest and requires SSL/TLS encryption for all connections.
* Access to the database is strictly limited to authorized Conductor engineers.
### API request security
* All API requests to Conductor are authenticated using an API key and restricted to HTTPS.
* Data in transit is encrypted, and requests are processed through our SOC 2 compliant backend hosted by AWS in the US West (Oregon) region.
### Security and compliance
* **SOC 2:** Conductor is actively working toward achieving its SOC 2 certification, implementing and monitoring the necessary measures to meet the Security, Availability, and Confidentiality Trust Service Criteria. We have engaged an independent AICPA-accredited auditor to formally assess and report on Conductor's controls.
* Conductor's [Trust Center](https://trust.conductor.is) monitors our progress toward SOC 2 compliance.
* Conductor's [Privacy Policy](https://conductor.is/privacy) outlines our data handling practices.
{/* We remove the section below because it's mostly redundant with the above. */}
{/* ### Sensitive data handling */}
{/* Based on Conductor's recommended API configuration, the QuickBooks Desktop data accessible via Conductor's API typically would not include highly sensitive personal data, such as Social Security Numbers, customer credit card details, or bank account numbers. However, depending on the specific data the customer chooses to request, some sensitive data transferred may still include: */}
{/* - Payroll and benefits information for employees and contractors, without direct identifiers such as Social Security Numbers. */}
{/* - Confidential revenue, expense, and profitability data for end-users' businesses. */}
{/* - Proprietary vendor and supplier details, contracts, and transaction terms. */}
{/* Conductor applies the following safeguards to protect this sensitive data: */}
{/* - **Strict purpose limitation:** Sensitive data is only used for the specific purposes of enabling end-user integrations (e.g., QuickBooks Desktop) via Conductor's API, and never for any other purposes. */}
{/* - **Encryption:** All sensitive data is encrypted in transit (HTTPS/TLS) and at rest (AES-256) using industry-standard encryption protocols. */}
{/* - **Onward transfer restrictions:** Conductor does not transfer any sensitive data to third parties or subprocessors without prior consent from the customer, and any approved transfers are governed by contracts ensuring the same level of data protection. */}
{/* - **Retention limitations:** Conductor does not retain any end-user data on a permanent basis. For operational purposes, API request logs that include end-user data are temporarily stored securely in a log manager for 14 days before permanent deletion. */}
{/* - **Access restrictions:** Access to sensitive customer and end-user data is restricted to only the necessary Conductor staff who have undergone specialized privacy and security training. */}
## Data subprocessors
Conductor subprocessors are third-party entities authorized to process data to support Conductor services in accordance with our service agreements. Conductor requires each subprocessor to meet specific contractual obligations to ensure they enforce security controls and comply with data protection regulations.
| **Subprocessor** | **Function** | **Location** |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| **Better Stack** | Logging manager for ingesting, parsing, and querying API request logs for debugging, offering customer support, and product improvement purposes. Retains end-user data for 14 days before deletion. | Germany, Finland |
| **Neon** | Postgres database hosting (using AWS underneath) for managing customer data, such as for authentication, connections, and account management. Does not store any end-user data. | Oregon - US West (AWS) |
| **Render** | Compute instance hosting (using AWS underneath) for running Conductor's core API services. Processes and transmits end-user data as needed to authenticate, process, and fulfill customers' API requests. | Oregon - US West (AWS) |
| **Sentry** | Application monitoring and error tracking. Captures diagnostic data and metadata around application errors and performance issues. May include limited customer data if present in error contexts. | Iowa, U.S.; Frankfurt, Germany |
| **Vercel** | Web app hosting for Conductor's web user interfaces. Does not directly process or store customer and end-user data. | N. California - US West (AWS) |
# Terminology
The key concepts you should know to use Conductor.
Familiarize yourself with the terms below that we use throughout the documentation and APIs.
| Term | Definition |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [EndUser](/apis/end-users/object) | A user of *your* application for whom you will connect integrations through Conductor. Each EndUser can represent an individual or an entire company/organization of multiple users within your application. |
| Integration | A third-party service you want to connect to your application. For example, QuickBooks Desktop. |
| [IntegrationConnection](/apis/integration-connections/object) | A connection for a specific EndUser to a specific integration. For example, a connection for the company "ABC Company" to their QuickBooks Desktop instance. |
| [Authentication flow](/usage/auth-flow) | The UI walkthrough that guides your users through securely connecting their QuickBooks Desktop to your Conductor account. |
# Create an account
POST /quickbooks-desktop/accounts
Creates a new financial account.
# List all accounts
GET /quickbooks-desktop/accounts
Returns a list of accounts.
# The Account object
An account represents a financial account, allowing customization like sub-accounting, account numbering, and initial balance setting.
# Retrieve an account
GET /quickbooks-desktop/accounts/{id}
Retrieves an account by ID.
# Update an account
POST /quickbooks-desktop/accounts/{id}
Updates a financial account.
# Create a bill payment check
POST /quickbooks-desktop/bill-payment-checks
Creates a new bill payment check.
# List all bill payment checks
GET /quickbooks-desktop/bill-payment-checks
Returns a list of bill payment checks.
# The Bill Payment Check object
A bill payment check is a transaction that represents a payment by check for a bill.
# Retrieve a bill payment check
GET /quickbooks-desktop/bill-payment-checks/{id}
Retrieves a bill payment check by ID.
# Update a bill payment check
POST /quickbooks-desktop/bill-payment-checks/{id}
Updates an existing bill payment check.
# Create a bill payment credit card
POST /quickbooks-desktop/bill-payment-credit-cards
Creates a new bill payment credit card.
# List all bill payment credit cards
GET /quickbooks-desktop/bill-payment-credit-cards
Returns a list of bill payment credit cards.
# The Bill Payment Credit Card object
A bill payment credit card is a transaction that represents a payment by credit card for a bill.
# Retrieve a bill payment credit card
GET /quickbooks-desktop/bill-payment-credit-cards/{id}
Retrieves a bill payment credit card by ID.
# Create a bill
POST /quickbooks-desktop/bills
Creates a new bill.
# List all bills
GET /quickbooks-desktop/bills
Returns a list of bills.
# The Bill object
A bill is a transaction that represents a request-for-payment from a vendor for goods or services that it has provided.
# Retrieve a bill
GET /quickbooks-desktop/bills/{id}
Retrieves a bill by ID.
# Update a bill
POST /quickbooks-desktop/bills/{id}
Updates an existing bill.
# Create a check
POST /quickbooks-desktop/checks
Creates a new check.
# List all checks
GET /quickbooks-desktop/checks
Returns a list of checks.
# The Check object
A check is a transaction that represents a paper check.
# Retrieve a check
GET /quickbooks-desktop/checks/{id}
Retrieves a check by ID.
# Update a check
POST /quickbooks-desktop/checks/{id}
Updates an existing check.
# Create a class
POST /quickbooks-desktop/classes
Creates a new class.
# List all classes
GET /quickbooks-desktop/classes
Returns a list of classes.
# The Class object
A class is a category used to group QuickBooks objects into meaningful categories. For example, classes can be used to classify transactions by department, location, or type of work.
# Retrieve a class
GET /quickbooks-desktop/classes/{id}
Retrieves a class by ID.
# Update a class
POST /quickbooks-desktop/classes/{id}
Updates an existing class.
# Create a credit card charge
POST /quickbooks-desktop/credit-card-charges
Creates a new credit card charge for the specified account.
# List all credit card charges
GET /quickbooks-desktop/credit-card-charges
Returns a list of credit card charges.
# The Credit Card Charge object
A credit card charge is a general charge incurred when a QuickBooks user makes a purchase using a credit card. Credit card charges for purchases can be tracked as expenses (in expense accounts) or as items.
# Retrieve a credit card charge
GET /quickbooks-desktop/credit-card-charges/{id}
Retrieves a credit card charge by ID.
# Update a credit card charge
POST /quickbooks-desktop/credit-card-charges/{id}
Updates an existing credit card charge.
# Create a credit card credit
POST /quickbooks-desktop/credit-card-credits
Creates a new credit card credit for the specified account.
# List all credit card credits
GET /quickbooks-desktop/credit-card-credits
Returns a list of credit card credits.
# The Credit Card Credit object
A credit card credit is a credit card refund issued to a customer.
# Retrieve a credit card credit
GET /quickbooks-desktop/credit-card-credits/{id}
Retrieves a credit card credit by ID.
# Update a credit card credit
POST /quickbooks-desktop/credit-card-credits/{id}
Updates an existing credit card credit.
# Create a customer
POST /quickbooks-desktop/customers
Creates a new customer.
# List all customers
GET /quickbooks-desktop/customers
Returns a list of customers.
# The Customer object
A customer can refer to either one of the QuickBooks user's customers or an individual job that is being performed for a customer.
# Retrieve a customer
GET /quickbooks-desktop/customers/{id}
Retrieves a customer by ID.
# Update a customer
POST /quickbooks-desktop/customers/{id}
Updates an existing customer.
# Create a date-driven term
POST /quickbooks-desktop/date-driven-terms
Creates a new date-driven term.
# List all date-driven terms
GET /quickbooks-desktop/date-driven-terms
Returns a list of date-driven terms.
# The Date-Driven Term object
A date-driven term shows the day of the month by which payment is due and can include a discount for early payment.
# Retrieve a date-driven term
GET /quickbooks-desktop/date-driven-terms/{id}
Retrieves a date-driven term by ID.
# Welcome to Conductor's new QuickBooks Desktop API (alpha)
Conductor's new QuickBooks Desktop API is a massive leap forward and sets the foundation for future integrations.
This new API is **neither stable nor ready for use**. We are iterating
rapidly. Expect changes to the API and documentation every single day.
Welcome to Conductor's new QuickBooks Desktop API. It brings the following improvements over the current generation:
1. Proper HTTP methods: `GET` for reading, `POST` for creating or updating. No more `POST` for everything.
2. Cleaner URL endpoints: `/quickbooks_desktop/invoices` instead of `/end-users/{id}/request/quickbooks_desktop` with `InvoiceQueryRq` in the body.
3. An OpenAPI spec for the entire API.
4. Full online documentation of all fields and their types.
5. API playground in the documentation to test requests and see responses.
6. Always returns all response fields. Uses `null` for undefined fields instead of omitting them.
7. Consistently returns arrays for any nested fields that previously returned a single object for one item and an array for multiple items.
* Returns an empty array instead of `null` for empty lists.
8. Clean response bodies: No more unwrapping outer objects; e.g., no more `InvoiceQueryRs.InvoiceRet`.
9. Proper object wrapper for all list responses: Previously, we returned an array of objects. Now, we return an object with a `data` field that contains the array of objects.
10. Pagination for all list endpoints.
11. Better parameter names instead of QuickBooks Desktop's unconventional naming. For example:
* `MaxReturned` → `limit`
* `TimeModified` → `updatedAt`
* `DataExtRet` → `customFields`
12. Uses `camelCase` for input and output field names instead of `PascalCase`.
13. Simplified request structure. For example:
* `refNumberStartsWith: "REF"` instead of `RefNumberFilter: { MatchCriterion: "StartsWith", RefNumber: "REF" }`
* `accountId: "123"` instead of `AccountRef: { ListID: "123" }`
14. Correct types for obscure fields: Previously, we inferred types from XML. Now, we define the type of every field to ensure it is always correct.
15. Better field descriptions: we are using our own descriptions instead of QuickBooks' descriptions.
16. Field-specific coercions: better handling of dates and money amounts.
17. Enforced upper bound on `limit` of 1000 items to prevent overloading QuickBooks Desktop instances.
18. Better defaults. For example:
* `includeLineItems` is `true` by default because who wants an empty invoice?
* `ownerId` is 0 by default to always include your end-users' custom fields.
## Feedback
We value your input! If you have suggestions or requests for improvements, changes, field names, documentation, or anything else, [please let us know](mailto:support@conductor.is?subject=Conductor%20QuickBooks%20Desktop%20API%20Feedback).
# Create an inventory assembly item
POST /quickbooks-desktop/inventory-assembly-items
Creates a new inventory assembly item.
# List all inventory assembly items
GET /quickbooks-desktop/inventory-assembly-items
Returns a list of inventory assembly items.
# The Inventory Assembly Item object
An inventory assembly item is an item that is assembled or manufactured from inventory items. The items and/or assemblies that make up the assembly are called components.
# Retrieve an inventory assembly item
GET /quickbooks-desktop/inventory-assembly-items/{id}
Retrieves an inventory assembly item by ID.
# Update an inventory assembly item
POST /quickbooks-desktop/inventory-assembly-items/{id}
Updates an existing inventory assembly item.
# Create an inventory item
POST /quickbooks-desktop/inventory-items
Creates a new inventory item.
# List all inventory items
GET /quickbooks-desktop/inventory-items
Returns a list of inventory items.
# The Inventory Item object
An inventory item is any merchandise or part that a business purchases, tracks as inventory, and then resells.
# Retrieve an inventory item
GET /quickbooks-desktop/inventory-items/{id}
Retrieves an inventory item by ID.
# Update an inventory item
POST /quickbooks-desktop/inventory-items/{id}
Updates an existing inventory item.
# Create an inventory site
POST /quickbooks-desktop/inventory-sites
Creates a new inventory site.
# List all inventory sites
GET /quickbooks-desktop/inventory-sites
Returns a list of inventory sites.
# The Inventory Site object
An inventory site is a location where inventory is stored. For example, a company might have a warehouse, a stockroom, and a showroom, each of which is an inventory site. NOTE: Inventory sites require QuickBooks Enterprise with an Advanced Inventory subscription.
# Retrieve an inventory site
GET /quickbooks-desktop/inventory-sites/{id}
Retrieves an inventory site by ID.
# Update an inventory site
POST /quickbooks-desktop/inventory-sites/{id}
Updates an existing inventory site.
# Create an invoice
POST /quickbooks-desktop/invoices
Creates a new invoice.
# List all invoices
GET /quickbooks-desktop/invoices
Returns a list of invoices.
# The Invoice object
An invoice records the amount owed by a customer who purchased goods or services but did not pay in full at the time of the sale.
# Retrieve an invoice
GET /quickbooks-desktop/invoices/{id}
Retrieves an invoice by ID.
# Update an invoice
POST /quickbooks-desktop/invoices/{id}
Updates an existing invoice.
# Create a non-inventory item
POST /quickbooks-desktop/non-inventory-items
Creates a new non-inventory item.
# List all non-inventory items
GET /quickbooks-desktop/non-inventory-items
Returns a list of non-inventory items.
# The Non-Inventory Item object
A non-inventory item is any material or part that a business buys but does not keep on hand as inventory.
There are two types of non-inventory items: 1. Materials or parts that are part of the business’s overhead (for example, office supplies) 2. Materials or parts that the business buys to finish a specific job and then charges back to the customer.
# Retrieve a non-inventory item
GET /quickbooks-desktop/non-inventory-items/{id}
Retrieves a non-inventory item by ID.
# Update a non-inventory item
POST /quickbooks-desktop/non-inventory-items/{id}
Updates an existing non-inventory item.
# Create a sales order
POST /quickbooks-desktop/sales-orders
Creates a new sales order.
# List all sales orders
GET /quickbooks-desktop/sales-orders
Returns a list of sales orders.
# The Sales Order object
A sales order tracks inventory that is on back order for a customer. In QuickBooks, sales orders and invoices use similar fields, and a sales order can be “converted” into an invoice (by linking the invoice to the sales order) once the inventory is in stock.
# Retrieve a sales order
GET /quickbooks-desktop/sales-orders/{id}
Retrieves a sales order by ID.
# Update a sales order
POST /quickbooks-desktop/sales-orders/{id}
Updates an existing sales order.
# Create a sales receipt
POST /quickbooks-desktop/sales-receipts
Creates a new sales receipt.
# List all sales receipts
GET /quickbooks-desktop/sales-receipts
Returns a list of sales receipts.
# The Sales Receipt object
Sales receipts include payments by cash, check, or credit card. For partial payments, use an invoice transaction with a payment item instead of a sales receipt.
# Retrieve a sales receipt
GET /quickbooks-desktop/sales-receipts/{id}
Retrieves a sales receipt by ID.
# Update a sales receipt
POST /quickbooks-desktop/sales-receipts/{id}
Updates an existing sales receipt.
# Create a sales-tax code
POST /quickbooks-desktop/sales-tax-codes
Creates a new sales-tax code.
# List all sales-tax codes
GET /quickbooks-desktop/sales-tax-codes
Returns a list of sales-tax codes.
# The Sales-Tax Code object
A sales tax code helps categorize items on a sales form as taxable or non-taxable, detailing reasons and associating tax codes with customers, items, or transactions.
# Retrieve a sales-tax code
GET /quickbooks-desktop/sales-tax-codes/{id}
Retrieves a sales-tax code by ID.
# Update a sales-tax code
POST /quickbooks-desktop/sales-tax-codes/{id}
Updates an existing sales-tax code.
# Create a sales-tax item
POST /quickbooks-desktop/sales-tax-items
Creates a new sales-tax item.
# List all sales-tax items
GET /quickbooks-desktop/sales-tax-items
Returns a list of sales-tax items.
# The Sales-Tax Item object
A sales-tax item is an item used to calculate a single sales tax that is collected at a specified rate and paid to a single agency.
# Retrieve a sales-tax item
GET /quickbooks-desktop/sales-tax-items/{id}
Retrieves a sales-tax item by ID.
# Update a sales-tax item
POST /quickbooks-desktop/sales-tax-items/{id}
Updates an existing sales-tax item.
# Create a service item
POST /quickbooks-desktop/service-items
Creates a new service item.
# List all service items
GET /quickbooks-desktop/service-items
Returns a list of service items.
# The Service Item object
A service item is an item that refers to services that a business charges for or purchases. Examples include specialized labor, consulting hours, and professional fees.
# Retrieve a service item
GET /quickbooks-desktop/service-items/{id}
Retrieves a service item by ID.
# Update a service item
POST /quickbooks-desktop/service-items/{id}
Updates an existing service item.
# Create a standard term
POST /quickbooks-desktop/standard-terms
Creates a new standard term.
# List all standard terms
GET /quickbooks-desktop/standard-terms
Returns a list of standard terms.
# The Standard Term object
A standard term is a payment term that shows the number of days within which payment is due and can include a discount for early payment.
# Retrieve a standard term
GET /quickbooks-desktop/standard-terms/{id}
Retrieves a standard term by ID.
# Create a transfer
POST /quickbooks-desktop/transfers
Creates a new transfer.
# List all transfers
GET /quickbooks-desktop/transfers
Returns a list of transfers.
# The Transfer object
A transfer is a transaction that moves money from one account to another account.
# Retrieve a transfer
GET /quickbooks-desktop/transfers/{id}
Retrieves a transfer by ID.
# Update a transfer
POST /quickbooks-desktop/transfers/{id}
Updates an existing transfer.
# Create a vendor
POST /quickbooks-desktop/vendors
Creates a new vendor.
# List all vendors
GET /quickbooks-desktop/vendors
Returns a list of vendors.
# The Vendor object
A vendor is any person or company from whom a small business owner buys goods and services. (Banks and tax agencies usually are included on the vendor list.) A company’s vendor list contains information such as account balance and contact information about each vendor.
# Retrieve a vendor
GET /quickbooks-desktop/vendors/{id}
Retrieves a vendor by ID.
# Update a vendor
POST /quickbooks-desktop/vendors/{id}
Updates an existing vendor.
# Accounts
export const pluralObjectName_0 = "accounts"
In QuickBooks Desktop, an **account** is a record that tracks the money coming in and going out of your business. Accounts are organized into a chart of accounts which includes assets, liabilities, income, and expenses. Each account has specific properties and characteristics.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching accounts
Fetching accounts in QuickBooks Desktop is straightforward. You can use optional request parameters to filter the results as needed.
```ts Fetching all accounts
const accounts = await conductor.qbd.account.query("{{END_USER_ID}}");
```
```ts Fetching all accounts with a filter
const accounts = await conductor.qbd.account.query("{{END_USER_ID}}", {
NameFilter: {
MatchCriterion: "StartsWith",
Name: "Test Account",
},
});
```
## Creating accounts
Creating accounts is also straightforward. There are several optional request parameters available, but the only required ones are `Name` and `AccountType`.
```ts Creating an account
const account = await conductor.qbd.account.add("{{END_USER_ID}}", {
// Create a unique name for testing because QBD requires unique names.
Name: "Test Account " + Date.now(),
AccountType: "Expense",
});
```
```json Example account object from QBD
{
"ListID": "80000001-1234567890",
"TimeCreated": "2022-01-01T09:00:00-07:00",
"TimeModified": "2024-05-02T14:30:00-07:00",
"EditSequence": "1234567890",
"Name": "Test Account",
"FullName": "Parent Account:Test Account",
"IsActive": true,
"ParentRef": {
"ListID": "80000002-0987654321",
"FullName": "Parent Account"
},
"Sublevel": 1,
"AccountType": "Expense",
"SpecialAccountType": "AccountsPayable",
"IsTaxAccount": true,
"AccountNumber": "1234",
"BankNumber": "987654321",
"Desc": "This is a test account.",
"Balance": "1000.00",
"TotalBalance": "1500.00",
"SalesTaxCodeRef": {
"ListID": "80000003-2345678901",
"FullName": "Tax Code"
},
"TaxLineInfoRet": {
"TaxLineID": 1,
"TaxLineName": "Tax Line Name"
},
"CashFlowClassification": "Operating",
"CurrencyRef": {
"ListID": "20000000-1234567890",
"FullName": "USD"
},
}
```
# Bills
export const pluralObjectName_0 = "bills"
A **bill** in QuickBooks Desktop is a record of a transaction that represents a request-for-payment from a [vendor](/qbd-examples/vendors) for goods or services that it has provided. Companies use bills to track the expenses they need to pay but have not yet paid. Bills are also known as payables.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching bills
Each bill has one or multiple line items, which are the goods or services that the vendor is requesting payment for. The following example fetches all bills for a given EndUser, including the line items for each bill.
```ts Fetching all bills with line items
const bills = await conductor.qbd.bill.fetchAll("{{END_USER_ID}}", {
IncludeLineItems: true,
});
```
## Creating bills
To create a bill in QuickBooks Desktop, you either need the identifiers (e.g., `ListID`) of the required associated objects, or you must create the associated objects first.
The following example uses mock data to create a bill in QuickBooks Desktop, which also requires creating a mock vendor, account, and service-item using the `add()` method of each object. The `add()` method returns the created object, which contains the `ListID` identifier to associate the objects with each other.
```ts Creating a bill
const END_USER_ID = "{{END_USER_ID}}";
// Use unique names for mock objects because QBD requires each to be unique.
const UNIQUE_SUFFIX = Math.random().toFixed(6);
const vendor = await conductor.qbd.vendor.add(END_USER_ID, {
Name: `Test Vendor ${UNIQUE_SUFFIX}`,
});
// A bill cannot be empty, so we must create an item to add to the bill,
// and every item requires an account, which we must create first.
const incomeAccount = await conductor.qbd.account.add(END_USER_ID, {
Name: `Test Income Account ${UNIQUE_SUFFIX}`,
AccountType: "Income",
});
// Create a service-item for the invoice with the account we just created.
const serviceItem = await conductor.qbd.itemService.add(END_USER_ID, {
Name: `Construction Work ${UNIQUE_SUFFIX}`,
SalesOrPurchase: {
Price: "100.00",
AccountRef: {
ListID: incomeAccount.ListID,
},
},
});
const bill = await conductor.qbd.bill.add(END_USER_ID, {
VendorRef: {
ListID: vendor.ListID,
},
ItemLineAdd: [
{
ItemRef: {
ListID: serviceItem.ListID,
},
Amount: "100.00",
Quantity: 1,
},
],
});
```
```json Example bill object from QBD
{
"TxnID": "ABC-1234567890",
"TxnNumber": 123,
"TxnDate": "2024-05-01",
"DueDate": "2024-05-15",
"TimeCreated": "2024-05-01T09:30:00+05:30",
"TimeModified": "2024-05-01T09:30:00+05:30",
"EditSequence": "9876543210",
"VendorRef": {
"ListID": "8000000A-1234567890",
"FullName": "Acme Inc."
},
"APAccountRef": {
"ListID": "8000000B-1234567890",
"FullName": "Accounts Payable"
},
"LinkedTxn": {
"TxnID": "XYZ-0987654321",
"TxnType": "PurchaseOrder",
"TxnDate": "2024-04-25",
"RefNumber": "PO-12345",
"LinkType": "QUANTYPE",
"Amount": "0.00"
},
"AmountDue": "5000.00",
"OpenAmount": "5000.00",
"IsPaid": false,
"ItemLineRet": [
{
"TxnLineID": "1A1-1234567890",
"ItemRef": {
"ListID": "8000000C-1234567890",
"FullName": "Widget A"
},
"Quantity": 10,
"Cost": "250.00",
"Amount": "2500.00"
},
{
"TxnLineID": "1A2-1234567890",
"ItemRef": {
"ListID": "8000000D-1234567890",
"FullName": "Widget B"
},
"Quantity": 5,
"Cost": "300.00",
"Amount": "1500.00"
},
{
"TxnLineID": "1A3-1234567890",
"ItemRef": {
"ListID": "8000000E-1234567890",
"FullName": "Widget C"
},
"Quantity": 2,
"Cost": "500.00",
"Amount": "1000.00"
}
]
}
```
# Inventory items
export const pluralObjectName_0 = "inventory items"
In QuickBooks Desktop, an inventory item is any merchandise or part that a business purchases, tracks as inventory, and then resells. In QuickBooks, information about an inventory item is grouped into three categories:
1. **Purchase Information:** `PurchaseDesc`, `PurchaseCost`, `COGSAccountRef`, and `PrefVendorRef`.
2. **Sales Information:** `SalesDesc`, `SalesPrice`, and `SalesTaxCodeRef`.
3. **Inventory Information:** `AssetAccountRef`, `ReorderPoint`, `QuantityOnHand`, `TotalValue`, and `InventoryDate`.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
In addition to the inventory item operations documented herein, **Conductor can fetch, create, and update every other inventory-related QuickBooks Desktop data type**:
* Inventory assembly items
* Inventory transfers
* Inventory adjustments
* Inventory sites
We will document these data types in the future. In the meantime, contact us if you need help with them.
## Fetching inventory items
It is quite simple to fetch inventory items. There are many optional request parameters you can use to filter the results.
```ts Fetching all inventory items
const inventoryItems =
await conductor.qbd.itemInventory.query("{{END_USER_ID}}");
```
```ts Fetching all inventory items with a filter
const inventoryItems = await conductor.qbd.itemInventory.query(
"{{END_USER_ID}}",
{
NameFilter: {
MatchCriterion: "StartsWith",
Name: "Test Inventory Items",
},
},
);
```
## Creating inventory items
Creating vendors is also quite simple. There are many optional request parameters available, but the only required one is `Name`.
```ts Creating an inventory item
const END_USER_ID = "{{END_USER_ID}}";
// Use unique names for mock objects because QBD requires each to be unique.
const UNIQUE_SUFFIX = Math.random().toFixed(6);
// An inventory item requires an income account, asset account, and a COGS
// account. These will usually already exist for an end-user, but we create
// mock accounts below for this example:
const incomeAccount = await client.qbd.account.add(END_USER_ID, {
Name: `Test Income Account ${UNIQUE_SUFFIX}`,
AccountType: "Income",
});
const assetAccount = await client.qbd.account.add(END_USER_ID, {
Name: `Test Asset Account ${UNIQUE_SUFFIX}`,
AccountType: "FixedAsset",
});
const cogsAccount = await client.qbd.account.add(END_USER_ID, {
Name: `Test COGS Account ${UNIQUE_SUFFIX}`,
AccountType: "CostOfGoodsSold",
});
const inventoryItem = await client.qbd.itemInventory.add(END_USER_ID, {
Name: `Test Inventory Item ${UNIQUE_SUFFIX}`,
IncomeAccountRef: {
ListID: incomeAccount.ListID,
},
AssetAccountRef: {
ListID: assetAccount.ListID,
},
COGSAccountRef: {
ListID: cogsAccount.ListID,
},
PurchaseCost: "50.00",
SalesPrice: "100.00",
});
```
```json Example inventory item object from QBD
{
"ListID": "800012AB-1234567890",
"Name": "MS-EX-ITEM",
"FullName": "MS-EX-ITEM",
"ManufacturerPartNumber": "EXITEM123",
"IsActive": true,
"Sublevel": 0,
"QuantityOnHand": 100,
"QuantityOnOrder": 50,
"QuantityOnSalesOrder": 75,
"PurchaseCost": "50.00",
"AverageCost": "48.50",
"SalesPrice": "99.99",
"PurchaseDesc": "EXAMPLE ITEM PURCHASE DESCRIPTION",
"SalesDesc": "EXAMPLE ITEM SALES DESCRIPTION",
"ClassRef": {
"ListID": "80000ABC-1234567890",
"FullName": "EXAMPLE CLASS"
},
"UnitOfMeasureSetRef": {
"ListID": "80000XYZ-1234567890",
"FullName": "EACH"
},
"PrefVendorRef": {
"ListID": "80000DEF-1234567890",
"FullName": "EXAMPLE VENDOR"
},
"AssetAccountRef": {
"ListID": "80000JKL-1234567890",
"FullName": "Inventory Asset"
},
"COGSAccountRef": {
"ListID": "80000MNO-1234567890",
"FullName": "Cost of Goods Sold"
},
"IncomeAccountRef": {
"ListID": "80000PQR-1234567890",
"FullName": "Sales"
},
"SalesTaxCodeRef": {
"ListID": "80000GHI-1234567890",
"FullName": "EXAMPLE TAX CODE"
},
"EditSequence": "1234567890",
"TimeCreated": "2024-05-01T09:30:00-05:00",
"TimeModified": "2024-05-02T14:45:30-05:00"
}
```
# Invoices
export const pluralObjectName_0 = "invoices"
An **invoice** in QuickBooks Desktop records the amount owed by a customer who purchased goods or services but did not pay in full at the time of the sale. If full payment is received at the time of the sale, it is recorded as a [sales receipt](/qbd-examples/sales-receipts), not an invoice.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching invoices
Each invoice in QuickBooks Desktop has several line items, which you would typically want to include when fetching invoices. The following example does just that:
```ts Fetching all invoices with line items
const invoices = await conductor.qbd.invoice.query("{{END_USER_ID}}", {
IncludeLineItems: true,
});
```
Invoices are also assigned to specific jobs under a customer or to the customer directly when not related to a particular job. The following example fetches all invoices for a specific customer:
```ts Fetching all invoices for a specific customer
const invoices = await conductor.qbd.invoice.query("{{END_USER_ID}}", {
EntityFilter: {
FullName: "Test customer 1234",
},
IncludeLineItems: true,
});
```
Here is an example of fetching invoices modified (or created) after a specific date:
```ts Fetching invoices modified after a specific date
const invoices = await conductor.qbd.invoice.query("{{END_USER_ID}}", {
ModifiedDateRangeFilter: {
FromModifiedDate: "2024-04-01",
},
IncludeLineItems: true,
});
```
## Creating invoices
An invoice is a complex object with many associated objects. To create an invoice from scratch, you either need the identifiers (e.g., `ListID`) of the required associated objects, or you must create the associated objects first.
The following example uses mock data to create an invoice in QuickBooks Desktop, which also requires creating a mock customer, account, and service-item using the `add()` method of each object. The `add()` method returns the created object, which contains the `ListID` identifier to associate the objects with each other.
```ts Creating an invoice
const END_USER_ID = "{{END_USER_ID}}";
// Use unique names for mock objects because QBD requires each to be unique.
const UNIQUE_SUFFIX = Math.random().toFixed(6);
const customer = await conductor.qbd.customer.add(END_USER_ID, {
Name: `Test customer ${UNIQUE_SUFFIX}`,
});
// An invoice cannot be empty, so we must create an item to add to the invoice,
// and every item requires an account, which we must create first.
const account = await conductor.qbd.account.add(END_USER_ID, {
Name: `Test income account ${UNIQUE_SUFFIX}`,
AccountType: "Income",
});
// Create a service-item for the invoice with the account we just created.
const serviceItem = await conductor.qbd.itemService.add(END_USER_ID, {
Name: `Construction work ${UNIQUE_SUFFIX}`,
SalesOrPurchase: {
Price: "100.00",
AccountRef: {
ListID: account.ListID,
},
},
});
const invoice = await conductor.qbd.invoice.add(END_USER_ID, {
CustomerRef: {
ListID: customer.ListID,
},
TxnDate: "2021-09-01",
InvoiceLineAdd: [
{
Amount: "100.00",
ItemRef: {
ListID: serviceItem.ListID,
},
},
],
});
```
We do not yet have a Python client library for our API, but it is coming soon. For now, Python users can use [Conductor's REST API for QuickBooks Desktop](/qbd/rest) and still leverage Conductor's powerful backend.
The following Python script creates an invoice in QuickBooks Desktop using Conductor's REST API. This script includes several helper functions that are an excellent example for how to use Conductor's REST API for QuickBooks Desktop in Python.
We are actively working on a complete rewrite of our REST API for QuickBooks Desktop that is much more powerful and much simpler. Available in Q1 2025.
In the meantime, use the approach documented below, which will be backward-compatible and easily adaptable to the new REST API when it is released.
```py Creating an invoice
import json
import random
import requests
API_KEY = "{{YOUR_SECRET_KEY}}"
END_USER_ID = "{{END_USER_ID}}"
def create_objects() -> None:
# Use unique names for mock data because QBD requires each to be unique.
mock_data_suffix = str(random.random())[:8]
customer = create_customer(END_USER_ID, f"Test customer {mock_data_suffix}")
print("New Customer:", json.dumps(customer, indent=4))
# An invoice cannot be empty, so we must create an item to add to the
# invoice, and every item requires an account, which we must create first.
income_account = create_income_account(
END_USER_ID, f"Test income account {mock_data_suffix}"
)
print("\nNew Income Account:", json.dumps(income_account, indent=4))
# Create a service-item for the invoice with the account we just created.
service_item = create_service_item(
END_USER_ID,
f"Construction work {mock_data_suffix}",
income_account["ListID"],
)
print("\nNew Service Item:", json.dumps(service_item, indent=4))
# Create an invoice with the customer and service-item we just created.
invoice = create_invoice(END_USER_ID, customer["ListID"], service_item["ListID"])
print("\nNew Invoice:", json.dumps(invoice, indent=4))
def create_customer(end_user_id: str, customer_name: str) -> dict:
response = send_qbd_request_to_conductor(
end_user_id,
{"CustomerAddRq": {"CustomerAdd": {"Name": customer_name}}},
)
return extract_return_value(response, "CustomerAddRs", "CustomerRet")
def create_income_account(end_user_id: str, account_name: str) -> dict:
response = send_qbd_request_to_conductor(
end_user_id,
{
"AccountAddRq": {
"AccountAdd": {
"Name": account_name,
"AccountType": "Income",
}
}
},
)
return extract_return_value(response, "AccountAddRs", "AccountRet")
def create_service_item(
end_user_id: str, item_name: str, income_account_list_id: str
) -> dict:
response = send_qbd_request_to_conductor(
end_user_id,
{
"ItemServiceAddRq": {
"ItemServiceAdd": {
"Name": item_name,
"SalesOrPurchase": {
"Price": "100.00",
"AccountRef": {
"ListID": income_account_list_id,
},
},
}
},
},
)
return extract_return_value(response, "ItemServiceAddRs", "ItemServiceRet")
def create_invoice(
end_user_id: str, customer_list_id: str, service_item_list_id: str
) -> dict:
response = send_qbd_request_to_conductor(
end_user_id,
{
"InvoiceAddRq": {
"InvoiceAdd": {
"CustomerRef": {
"ListID": customer_list_id,
},
"TxnDate": "2021-09-01",
"InvoiceLineAdd": [
{
"Amount": "100.00",
"ItemRef": {
"ListID": service_item_list_id,
},
}
],
}
},
},
)
return extract_return_value(response, "InvoiceAddRs", "InvoiceRet")
def send_qbd_request_to_conductor(end_user_id: str, request_body: dict) -> dict:
try:
response = requests.post(
url=f"https://api.conductor.is/v1/end-users/{end_user_id}/request/quickbooks_desktop",
json=request_body,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
)
response.raise_for_status()
return response.json()
except requests.HTTPError:
print(f"Conductor error: {response.text}")
raise
except requests.RequestException as e:
print(f"Error during requests to {response.url}: {e}")
raise
# Helper function to safely extract data from response.
def extract_return_value(response, *keys):
for key in keys[:-1]:
response = response.get(key, {})
return response.get(keys[-1])
if __name__ == "__main__":
create_objects()
```
## Updating invoices and line-items
To modify existing line-items or add line-items to an invoice, QuickBooks Desktop requires that you include all unmodified line-items in the update request, even the ones you do not want to change. Otherwise, QuickBooks Desktop will remove the line-items you did not include in the update request. Hence, we recommend you first query the invoice you want to update, then update that invoice with the new line-items you want to add or modify while including all the existing line-items returned from the query.
```ts Updating an invoice by adding a new line-item
const END_USER_ID = "{{END_USER_ID}}";
const newInvoice = await conductor.qbd.invoice.add(END_USER_ID, {
CustomerRef: {
FullName: "Test Customer",
},
Memo: "New invoice",
InvoiceLineAdd: [
{
ItemRef: {
FullName: "Test Item",
},
Desc: "First line item",
Amount: "100.00",
},
{
ItemRef: {
FullName: "Test Item",
},
Desc: "Second line item",
Amount: "200.00",
},
],
});
const updatedInvoice = await conductor.qbd.invoice.mod(END_USER_ID, {
TxnID: newInvoice.TxnID,
// `EditSequence` from the original object is required to update
// any QuickBooks Desktop object.
EditSequence: newInvoice.EditSequence,
Memo: "Updated invoice",
InvoiceLineMod: [
// QuickBooks Desktop requires that you re-include the
// existing line items in the request. Otherwise, it will
// remove them from the invoice.
...newInvoice.InvoiceLineRet,
{
ItemRef: {
ListID: inventoryItems[0].ListID,
},
Desc: "Item 3",
// Set `TxnLineID` to -1 to add a new line item.
TxnLineID: "-1",
},
],
});
```
```json Example invoice object from QBD
{
"TxnID": "ABC123-9876543210",
"TxnNumber": 2345,
"RefNumber": "INV-2345",
"TxnDate": "2024-05-01",
"TimeCreated": "2024-05-01T09:30:00+00:00",
"TimeModified": "2024-05-01T09:45:00+00:00",
"EditSequence": "9876543210",
"CustomerRef": {
"ListID": "100000-1234567890",
"FullName": "John Doe"
},
"ARAccountRef": {
"ListID": "200000-1234567890",
"FullName": "Accounts Receivable"
},
"TemplateRef": {
"ListID": "300000-1234567890",
"FullName": "Standard Invoice Template"
},
"ItemSalesTaxRef": {
"ListID": "400000-1234567890",
"FullName": "State Sales Tax"
},
"CustomerSalesTaxCodeRef": {
"ListID": "500000-1234567890",
"FullName": "Standard Tax Code"
},
"ShipMethodRef": {
"ListID": "600000-1234567890",
"FullName": "FedEx Ground"
},
"Subtotal": "1000.00",
"SalesTaxTotal": "80.00",
"SalesTaxPercentage": 8.0,
"AppliedAmount": "500.00",
"BalanceRemaining": "580.00",
"DueDate": "2024-06-01",
"ShipDate": "2024-05-03",
"IsPaid": false,
"IsPending": true,
"IsFinanceCharge": false,
"IsToBeEmailed": true,
"IsToBePrinted": false,
"InvoiceLineRet": [
{
"TxnLineID": "LI1-9876543210",
"ItemRef": {
"ListID": "700000-1234567890",
"FullName": "Product A"
},
"Desc": "Product A description",
"Quantity": 10,
"Rate": "100.00",
"Amount": "1000.00",
"SalesTaxCodeRef": {
"ListID": "500000-1234567890",
"FullName": "Standard Tax Code"
}
},
{
"TxnLineID": "LI2-9876543210",
"ItemRef": {
"ListID": "800000-1234567890",
"FullName": "Discount"
},
"Desc": "10% discount",
"RatePercent": -10,
"Amount": "-100.00"
},
{
"TxnLineID": "LI3-9876543210",
"ItemRef": {
"ListID": "900000-1234567890",
"FullName": "Subtotal"
},
"Desc": "Subtotal",
"Amount": "900.00"
}
]
}
```
# Jobs and customers
Understanding the relationship between customers and jobs in QuickBooks Desktop.
export const pluralObjectName_0 = "customers"
## Overview
In QuickBooks Desktop, both "customers" and "jobs" are represented as `Customer` objects. Jobs are considered a subset of customers and cannot be queried separately. This data model is a quirk of QuickBooks Desktop and is outside of Conductor's control.
## Differences between jobs and customers
A job in QuickBooks Desktop differs from a customer in the following ways:
1. **ParentRef:** A job has a `ParentRef` property that points to the parent customer.
2. **FullName:** A job's `FullName` property is the concatenation of the parent customer's `FullName` and the job's Name.
* Example: If the parent customer's `FullName` is `"Annie's Alligators"` and the job's Name is `"Swamp"`, the job's `FullName` will be `"Annie's Alligators:Swamp"`.
3. **Sublevel:** A job has a `Sublevel` property set to `1`, while the parent customer's `Sublevel` property is set to `0`.
## Querying customers and jobs
To fetch all customers and jobs for a given end-user, use the following query:
```ts Fetching all customers and jobs
const customersAndJobs = await conductor.qbd.customer.query("{{END_USER_ID}}");
```
If you're looking for a specific job in QuickBooks Desktop, you must query for
the customer and then filter the results to find the job.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching objects related to customers' jobs
Some objects in QuickBooks Desktop, such as SalesOrders, are associated with a customer's job instead of directly with the customer. In these cases, querying using the `EntityFilter.ListID` parameter set to a customer's `ListID` will return no results.
To fetch objects related to a customer's jobs, use the `EntityFilter.ListIDWithChildren` parameter with the customer's `ListID`. This will return the objects corresponding to all of the customer's jobs. For example:
```ts Fetching SalesOrders for all jobs of a customer
const salesOrders = await conductor.qbd.salesOrder.query("{{END_USER_ID}}", {
EntityFilter: {
// The `ListID` of the customer whose jobs' SalesOrders you want to fetch.
ListIDWithChildren: "800000AB-1234567890",
},
});
```
By using the `ListIDWithChildren` parameter, you can effectively query for objects related to a customer's jobs without having to query for each job individually.
```json Example customer object from QBD
{
"ListID": "800000AB-1234567890",
"Name": "SUNNY GARDENS INC.",
"FullName": "SUNNY GARDENS INC.",
"CompanyName": "SUNNY GARDENS INC.",
"Phone": "555-987-6543",
"AltPhone": "800-246-1357",
"Fax": "555-123-4567",
"Email": "info@sunnygardens.com",
"IsActive": true,
"Balance": "5678.92",
"TotalBalance": "5678.92",
"TimeCreated": "2021-09-15T14:30:00-05:00",
"TimeModified": "2023-09-01T09:45:12-05:00",
"EditSequence": "1987654321",
"CustomerTypeRef": {
"ListID": "8000000F-1234567890",
"FullName": "Wholesale"
},
"PriceLevelRef": {
"ListID": "80000003-1234567890",
"FullName": "WHOLESALE PRICE LEVEL LIST"
},
"SalesTaxCodeRef": {
"ListID": "80000003-1234567890",
"FullName": "Taxable"
},
"TermsRef": {
"ListID": "80000007-1234567890",
"FullName": "Net 60"
},
"BillAddress": {
"Addr1": "SUNNY GARDENS INC.",
"Addr2": "4321 MAIN STREET",
"City": "SPRINGFIELD, IL 62701 US, IL 62",
"State": "IL 62701 US"
},
"BillAddressBlock": {
"Addr1": "SUNNY GARDENS INC.",
"Addr2": "4321 MAIN STREET",
"Addr3": "SPRINGFIELD, IL 62701 US, IL 62701"
},
"ShipAddress": {
"Addr1": "SUNNY GARDENS INC.",
"Addr2": "4321 MAIN STREET",
"City": "SPRINGFIELD",
"State": "IL",
"PostalCode": "62701",
"Country": "United States"
},
"ShipAddressBlock": {
"Addr1": "SUNNY GARDENS INC.",
"Addr2": "4321 MAIN STREET",
"Addr3": "SPRINGFIELD, IL 62701",
"Addr4": "United States"
},
"Sublevel": 0,
"JobStatus": "None",
"Notes": "John Smith - Owner\\nMary Smith - Manager"
}
```
```json Example "job" for the customer above
{
"ListID": "8000000D-1987654321",
"TimeCreated": "2022-03-01T10:15:00-05:00",
"TimeModified": "2023-09-01T14:30:00-05:00",
"EditSequence": 1987654322,
"Name": "Spring Planting",
// For jobs, `FullName` is the concatenation of the
// parent customer's `FullName` and the job's `Name`.
"FullName": "SUNNY GARDENS INC.:Spring Planting",
"IsActive": true,
// `ParentRef` only exists for jobs and points to
// the parent customer object.
"ParentRef": {
"ListID": "800000AB-1234567890",
"FullName": "SUNNY GARDENS INC."
},
"Sublevel": 1,
"Balance": 1234.56,
"TotalBalance": 1234.56,
"JobStatus": "In Progress",
"PreferredDeliveryMethod": "Email",
"StartDate": "2022-03-15",
"ProjectedEndDate": "2022-05-31",
"JobTypeRef": {
"ListID": "8000000G-1987654321",
"FullName": "Landscaping"
},
"JobDescription": "Annual spring planting and garden setup for Sunny Gardens Inc.",
"PrimaryContactRef": {
"ListID": "8000000H-1987654321",
"FullName": "Mary Smith"
}
}
```
# Request more examples!
Conductor supports read, create, and update for *every* QuickBooks Desktop object type.
**Conductor has fully-typed APIs for reading, creating, and updating [*any* object in QuickBooks Desktop](/qbd/api#supported-object-types).** If the QuickBooks Desktop UI can do it, then so can Conductor's API.
We have dozens more guides we want to write with code samples and examples. If you have a specific use case you'd like to see, [email us](mailto:support@conductor.is?subject=Conductor%20Docs%20Request\&body=Conductor%20supports%20every%20possible%20QuickBooks%20Desktop%20operation.%20Describe%20below%20what%20you%20are%20trying%20to%20do%2C%20and%20we%27ll%20either%20point%20you%20to%20an%20existing%20document%20or%20create%20one%20ASAP.) and we will publish it within 24 hours.
In the meantime, we recommend using our client library's [awesome autocomplete
functionality](/usage/autocomplete) to discover all of the available APIs,
request parameters, and response fields.
# Refunds
This guide covers how to implement refunds using Conductor's QuickBooks Desktop API. We'll cover two main scenarios:
1. Invoice-based refunds (full or partial)
2. Custom refunds (not linked to any invoice)
## Invoice-based refund
For invoice-based refunds, you will create a credit memo and then apply it to the relevant invoice using a receive payment transaction to reduce the outstanding balance.
### Step 1: Create the credit memo
First, create a credit memo for the customer for the amount you wish to refund. This credit memo can be for the full or partial amount of the invoice.
Here's an example of how to create a credit memo:
```typescript
const creditMemo = await conductor.qbd.creditMemo.add("{{END_USER_ID}}", {
CustomerRef: {
ListID: "customer_list_id", // Customer's ListID from the original invoice
},
TxnDate: "2024-10-23", // Current date
RefNumber: "REFUND-123", // Optional: Your reference number
Memo: "Refund for Invoice INV-001", // Add a memo for reference
CreditMemoLineAdd: [
{
ItemRef: {
ListID: "item_list_id", // Original item from the invoice
},
Desc: "Refund for Invoice #123",
Quantity: 1, // Quantity being refunded
Amount: "50.00", // Amount being refunded for the item
},
],
});
```
### Step 2: Apply the credit memo to the invoice
Next, apply the credit memo to the outstanding invoice using a receive payment request. This will reduce the balance of the invoice by the credit amount.
Here's an example of how to apply the credit:
```typescript
const receivePayment = await conductor.qbd.receivePayment.add(
"{{END_USER_ID}}",
{
CustomerRef: {
ListID: "customer_list_id", // Must match the customer from credit memo
},
TotalAmount: "0.00", // No new payment being received
Memo: "Applying credit memo to invoice",
AppliedToTxnAdd: {
TxnID: "original_invoice_txn_id", // Original invoice's TxnID
PaymentAmount: "0.00", // No payment being made
SetCredit: {
CreditTxnID: creditMemo.TxnID, // TxnID from the credit memo we just created
AppliedAmount: "50.00", // Amount of credit to apply
},
},
},
);
```
## Custom refund (not linked to any invoice)
For a custom refund not linked to any specific invoice, simply create a credit memo to record the amount owed to the customer.
Here's an example of how to create a custom credit memo:
```typescript
const standaloneCreditMemo = await conductor.qbd.creditMemo.add(
"{{END_USER_ID}}",
{
CustomerRef: {
ListID: "customer_list_id", // Required: Customer's ListID
},
TxnDate: "2024-10-23", // Current date
RefNumber: "REFUND-124", // Optional: Your reference number
Memo: "Goodwill refund",
CreditMemoLineAdd: [
{
ItemRef: {
ListID: "refund_item_list_id", // Use a specific item for refunds
},
Desc: "Customer satisfaction refund",
Amount: "75.00", // Refund amount
},
],
},
);
```
## Common scenarios
### Partial refund
Modify the `CreditMemoLineAdd.Amount` to match the partial refund amount:
```typescript
CreditMemoLineAdd: [
{
ItemRef: { ListID: "item_list_id" },
Desc: "Partial refund - 50%",
Amount: "25.00", // Half of the original amount
},
];
```
### Multiple item refund
Use multiple `CreditMemoLineAdd` entries:
```typescript
CreditMemoLineAdd: [
{
ItemRef: { ListID: "item1_list_id" },
Desc: "Refund - Item 1",
Amount: "30.00",
},
{
ItemRef: { ListID: "item2_list_id" },
Desc: "Refund - Item 2",
Amount: "20.00",
},
];
```
# Sales receipts
export const pluralObjectName_0 = "sales receipts"
A **sales receipt** in QuickBooks Desktop is a record of a sale to a customer, such as a payment by cash, check, or credit card. Each sales receipt has several line items, which are the products or services sold.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching sales receipts
The following example fetches all sales receipts for the specified EndUser, including the line items:
```ts Fetching all sales receipts with line items
const salesReceipts = await conductor.qbd.salesReceipt.query(
"{{END_USER_ID}}",
{ IncludeLineItems: true },
);
```
## Creating sales receipts
To create a sales receipt in QuickBooks Desktop from scratch, you either need the identifiers (e.g., `ListID`) of the required associated objects, or you must create the associated objects first.
The following example uses mock data to create a sales receipt in QuickBooks Desktop, which also requires creating a mock customer, account, and service-item using the `add()` method of each object. The `add()` method returns the created object, which contains the `ListID` identifier to associate the objects with each other.
```ts Creating a sales receipt
const END_USER_ID = "{{END_USER_ID}}";
// Use unique names for mock objects because QBD requires each to be unique.
const UNIQUE_SUFFIX = Math.random().toFixed(6);
const customer = await conductor.qbd.customer.add(END_USER_ID, {
Name: `Test Customer ${UNIQUE_SUFFIX}`,
});
// A sales receipt cannot be empty, so we must create an item to add to the
// sales receipt, and every item requires an account, which we create first.
const account = await conductor.qbd.account.add(END_USER_ID, {
Name: `Test Income Account ${UNIQUE_SUFFIX}`,
AccountType: "Income",
});
// Create a service-item for the sales receipt with the account we just created.
const serviceItem = await conductor.qbd.itemService.add(END_USER_ID, {
Name: `Construction Work ${UNIQUE_SUFFIX}`,
SalesOrPurchase: {
Price: "100.00",
AccountRef: {
ListID: account.ListID,
},
},
});
const salesReceipt = await conductor.qbd.salesReceipt.add(END_USER_ID, {
CustomerRef: {
ListID: customer.ListID,
},
SalesReceiptLineAdd: [
{
Quantity: 5,
ItemRef: {
ListID: serviceItem.ListID,
},
},
],
});
```
```json Example sales receipt object from QBD
{
"TxnID": "1234-5678901234",
"TxnNumber": 1000,
"TxnDate": "2024-05-01",
"RefNumber": "11",
"CustomerRef": {
"ListID": "1234567890",
"FullName": "John Doe"
},
"Subtotal": "1000.00",
"SalesTaxTotal": "80.00",
"TotalAmount": "1080.00",
"DepositToAccountRef": {
"ListID": "9876543210",
"FullName": "Checking Account"
},
"ClassRef": {
"ListID": "1122334455",
"FullName": "Online Sales"
},
"TemplateRef": {
"ListID": "5544332211",
"FullName": "Standard Sales Receipt"
},
"BillAddress": {
"Addr1": "123 Main St"
},
"BillAddressBlock": {
"Addr1": "123 Main St"
},
"ShipDate": "2024-05-02",
"DueDate": "2024-05-15",
"SalesTaxPercentage": 8.0,
"IsPending": false,
"IsToBeEmailed": true,
"IsToBePrinted": false,
"EditSequence": "1683057600",
"TimeCreated": "2024-05-01T09:30:00-04:00",
"TimeModified": "2024-05-01T09:45:00-04:00",
"SalesReceiptLineRet": {
"TxnLineID": "4E3-1703630162",
"ItemRef": {
"ListID": "80000035-1703630156",
"FullName": "Construction Work"
},
"Quantity": 5,
"Rate": 100,
"Amount": 500,
"SalesTaxCodeRef": {
"ListID": "80000002-1692738438",
"FullName": "Non"
}
}
}
```
# Vendors
export const pluralObjectName_0 = "vendors"
A **vendor** in QuickBooks Desktop is an entity that represents a person, company, or business entity from which a business purchases goods or services. (Banks and tax agencies usually are included on the
vendor list.) A company’s vendor list contains information such as account
balance and contact information about each vendor. This entity is crucial for tracking and managing expenses and accounts payable.
To see all of the **request parameters and response fields** for
{pluralObjectName_0}, check out our client library's [amazing
autocomplete](/usage/autocomplete).
## Fetching vendors
It is quite simple to fetch vendors. There are many optional request parameters you can use to filter the results.
```ts Fetching all vendors
const vendors = await conductor.qbd.vendor.query("{{END_USER_ID}}");
```
```ts Fetching all vendors with a filter
const vendors = await conductor.qbd.vendor.query("{{END_USER_ID}}", {
NameFilter: {
MatchCriterion: "StartsWith",
Name: "Test Vendor",
},
});
```
## Creating vendors
Creating vendors is also quite simple. There are many optional request parameters available, but the only required one is `Name`.
```ts Creating a vendor
const vendor = await conductor.qbd.vendor.add("{{END_USER_ID}}", {
// Create a unique name for testing because QBD requires unique names.
Name: "Test Vendor " + Date.now(),
});
```
```json Example vendor object from QBD
{
"ListID": "9000008D-1234567890",
"Name": "Acme Inc.",
"CompanyName": "Acme Inc.",
"NameOnCheck": "Acme Inc.",
"IsActive": true,
"Balance": "1250.00",
"Phone": "555-123-4567",
"Fax": "555-987-6543",
"AdditionalContactRef": [
{
"ContactName": "Customer Support",
"ContactValue": "800-555-1234"
},
{
"ContactName": "Sales",
"ContactValue": "800-555-5678"
}
],
"VendorAddress": {
"Addr1": "Acme Inc.",
"Addr2": "123 Main St.",
"City": "Anytown",
"State": "CA",
"PostalCode": "12345"
},
"VendorAddressBlock": {
"Addr1": "Acme Inc.",
"Addr2": "123 Main St.",
"Addr3": "Anytown, CA 12345"
},
"TermsRef": {
"ListID": "90000007-1234567890",
"FullName": "Net 60"
},
"IsVendorEligibleFor1099": true,
"TimeCreated": "2022-01-01T09:00:00-07:00",
"TimeModified": "2024-05-02T14:30:00-07:00",
"EditSequence": "1234567890"
}
```
# Node.js / TypeScript for QuickBooks Desktop
Execute real-time requests for *any* QuickBooks Desktop object type with fully-typed requests and responses.
## Accessing QuickBooks Desktop through Conductor
With Conductor, you can read, create, or update *any* QuickBooks Desktop object type. Every operation is available through a single, consistent interface vis `conductor.qbd.*`.
We recommend using Conductor's [amazing autocomplete](/usage/autocomplete) to
discover the available operations, parameters, and responses fields.
For example:
```ts Fetch all invoices with line items
const invoices = await conductor.qbd.invoice.query("{{END_USER_ID}}", {
IncludeLineItems: true,
});
```
```ts Create an invoice
const newInvoice = await conductor.qbd.invoice.add("{{END_USER_ID}}", {
CustomerRef: {
FullName: "Acme Inc.",
},
TxnDate: "2024-01-12",
Memo: "Customer invoice for Jan 1 - 7",
InvoiceLineAdd: [
{
Amount: "100.00",
ItemRef: {
FullName: "Consulting",
},
},
],
});
```
```ts Update an invoice
const updatedInvoice = await conductor.qbd.invoice.mod("{{END_USER_ID}}", {
TxnID: "1234-ABCD",
EditSequence: "1234-ABCD",
DueDate: "2024-01-19",
InvoiceLineMod: {
TxnLineID: "1234-ABCD",
ItemRef: {
FullName: "Consulting",
},
Amount: "200.00",
},
});
```
### Supported object types
Conductor supports the following QuickBooks Desktop object types and operations. Alternatively, see [QuickBooks Desktop's official API Reference](https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop) to explore the operations available for each object type.
| Object | Read | Create | Update |
| --------------------- | :--: | :----: | :----: |
| Account | ✔ | ✔ | ✔ |
| AgingReport | ✔ | | |
| Bill | ✔ | ✔ | ✔ |
| BillPaymentCheck | ✔ | ✔ | ✔ |
| BillPaymentCreditCard | ✔ | ✔ | |
| BillingRate | ✔ | ✔ | |
| BudgetSummaryReport | ✔ | | |
| BuildAssembly | ✔ | ✔ | ✔ |
| Charge | ✔ | ✔ | ✔ |
| Check | ✔ | ✔ | ✔ |
| Class | ✔ | ✔ | ✔ |
| Company | ✔ | | |
| CreditCardCharge | ✔ | ✔ | ✔ |
| CreditCardCredit | ✔ | ✔ | ✔ |
| CreditMemo | ✔ | ✔ | ✔ |
| Currency | ✔ | ✔ | ✔ |
| CustomDetailReport | ✔ | | |
| CustomSummaryReport | ✔ | | |
| Customer | ✔ | ✔ | ✔ |
| CustomerType | ✔ | ✔ | |
| DataExt | | ✔ | ✔ |
| DateDrivenTerms | ✔ | ✔ | |
| Deposit | ✔ | ✔ | ✔ |
| Employee | ✔ | ✔ | ✔ |
| Estimate | ✔ | ✔ | ✔ |
| GeneralDetailReport | ✔ | | |
| GeneralSummaryReport | ✔ | | |
| InventoryAdjustment | ✔ | ✔ | ✔ |
| InventorySite | ✔ | ✔ | ✔ |
| Invoice | ✔ | ✔ | ✔ |
| ItemDiscount | ✔ | ✔ | ✔ |
| ItemFixedAsset | ✔ | ✔ | ✔ |
| ItemGroup | ✔ | ✔ | ✔ |
| ItemInventory | ✔ | ✔ | ✔ |
| ItemInventoryAssembly | ✔ | ✔ | ✔ |
| ItemNonInventory | ✔ | ✔ | ✔ |
| ItemOtherCharge | ✔ | ✔ | ✔ |
| ItemPayment | ✔ | ✔ | ✔ |
| ItemReceipt | ✔ | ✔ | ✔ |
| ItemSalesTax | ✔ | ✔ | ✔ |
| ItemSalesTaxGroup | ✔ | ✔ | ✔ |
| ItemService | ✔ | ✔ | ✔ |
| ItemSites | ✔ | | |
| ItemSubtotal | ✔ | ✔ | ✔ |
| JobReport | ✔ | | |
| JobType | ✔ | ✔ | |
| JournalEntry | ✔ | ✔ | ✔ |
| Lead | ✔ | ✔ | ✔ |
| ListDeleted | ✔ | | |
| OtherName | ✔ | ✔ | ✔ |
| PaymentMethod | ✔ | ✔ | |
| PayrollDetailReport | ✔ | | |
| PayrollItemWage | ✔ | ✔ | |
| PayrollSummaryReport | ✔ | | |
| PriceLevel | ✔ | ✔ | ✔ |
| PurchaseOrder | ✔ | ✔ | ✔ |
| ReceivePayment | ✔ | ✔ | ✔ |
| SalesOrder | ✔ | ✔ | ✔ |
| SalesReceipt | ✔ | ✔ | ✔ |
| SalesRep | ✔ | ✔ | ✔ |
| SalesTaxCode | ✔ | ✔ | ✔ |
| SalesTaxPaymentCheck | ✔ | ✔ | ✔ |
| StandardTerms | ✔ | ✔ | |
| TimeReport | ✔ | | |
| TimeTracking | ✔ | ✔ | ✔ |
| Transaction | ✔ | | |
| Transfer | ✔ | ✔ | ✔ |
| TransferInventory | ✔ | ✔ | ✔ |
| TxnDeleted | ✔ | | |
| Vehicle | ✔ | ✔ | ✔ |
| VehicleMileage | ✔ | ✔ | |
| Vendor | ✔ | ✔ | ✔ |
| VendorCredit | ✔ | ✔ | ✔ |
| VendorType | ✔ | ✔ | |
| WorkersCompCode | ✔ | ✔ | ✔ |
## TypeScript for QuickBooks Desktop
In the Conductor Node.js library, every request parameter and response attribute is fully-typed with inline documentation and will autocomplete in your editor. This makes it easy to explore the API and write code that works the first time.
If you ever need to access the raw QuickBooks Desktop types, you can import them from `conductor-node` like so:
```ts
import { QbdTypes } from "conductor-node";
const accountAddInput: QbdTypes.AccountAdd = {
Name: "Test Account",
AccountType: "Bank",
OpenBalance: "100",
};
```
# Get a free QuickBooks Desktop developer license
Obtain a free Not-For-Resale (NFR) license to use QuickBooks Desktop indefinitely for development and testing with Conductor. Takes 2 minutes.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
To develop and test integrations with Conductor, you need your own QuickBooks Desktop instance. If you don't have an existing instance, you can [install the QuickBooks Desktop free trial](/qbd/test-instance.mdx). The trial includes all features of the full version but expires after 30 days. To continue using QuickBooks Desktop for development beyond this period, you'll need a free Not-For-Resale (NFR) license. Follow these steps to obtain one:
If you haven't already, follow our guide for [installing the QuickBooks Desktop free trial](/qbd/test-instance.mdx).
[Sign up for an Intuit developer account](https://accounts.intuit.com/app/sign-in?start_screen_hint=SignUp) if you don't have one. This account is required to request the NFR license.
1. Go to [Intuit's developer support page](https://help.developer.intuit.com/s/contactsupport).
2. Choose the following options:
* **Product:** QuickBooks Desktop
* **Category:** NFR License
3. Click "Next" to proceed.
![Support ticket creation page with 'QuickBooks Desktop' selected as the
Product and 'NFR License' selected as the
Category](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/qbd/dev-license/create-ticket-1.jpg)
On the next page, specify:
* **Product Year:** 2024 (or the latest available)
* **Product Country:** US
* **Product Version:** QuickBooks Enterprise v24 (or the latest version)
Conductor works identically with all QuickBooks Desktop versions and editions. We recommend the Enterprise edition for development to avoid potential limitations in user count and dataset size.
* **Enable Advanced Inventory?** Yes (Allows testing with the full feature set)
After filling out these details, click "Create Support Ticket".
![Support ticket creation page with the specified options selected](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/qbd/dev-license/create-ticket-2.jpg)
After you click "Create Support Ticket", Intuit will send you a confirmation email. Intuit will send you another email within 24-48 hours with your license key.
Once you have the license key:
1. Open your existing QuickBooks Desktop trial installation.
2. Go to Help > Manage My License > Change Product License.
3. Enter the NFR license key when prompted.
4. Follow any additional on-screen instructions to complete activation.
Your QuickBooks Desktop is now licensed for indefinite use in development and testing with Conductor.
# Mapping your app's objects to QuickBooks Desktop
How to handle syncing your application's data objects with QuickBooks Desktop objects.
Most complex QuickBooks Desktop (QBD) object types, such as [invoices](/qbd-examples/invoices) and [sales receipts](/qbd-examples/sales-receipts), interact with various related objects. For instance, an invoice may contain multiple line items, with each item linked to a specific QBD inventory item via an ID. **When creating these objects in QBD, you must ensure that all related objects are correctly linked.**
For effective integration, depending on the data type of these related objects and you application requirements, you can either:
1. **Create new QBD objects** and store their IDs in your application's database for future reference.
2. **Map existing QBD objects to corresponding objects in your application** through manual configurations made by users within your application's UI. Consider the following example for inventory items:
1. Fetch all existing QBD inventory items using Conductor's API (e.g., `await conductor.qbd.itemInventory.query()`).
2. Display these QBD items alongside items from your application in the UI.
3. Users can then specify mappings, or opt to create new items in QBD.
4. Record the corresponding QBD item ID in your application's database (e.g., add a **`qbd_item_id`** column to the **`items`** table).
**Important:** The need to map or create objects may vary based on object type
(e.g., some users might prefer mapping existing QBD objects for certain types
while creating new ones for others). Regardless, it is crucial for your
application to store these QBD IDs in its database for all future
interactions, ensuring no duplicate objects are created.
# Pagination
Split your requests into smaller chunks to avoid overwhelming QuickBooks Desktop
Some QuickBooks Desktop users have unexpectedly large amounts of data. In addition, QuickBooks Desktop is slow and memory-intensive. Without proper limits or pagination, a request might inadvertently retrieve tens of thousands of rows, which can take many minutes to return. To avoid overwhelming QuickBooks Desktop, you may need to split your requests into smaller chunks. This process is called **pagination**.
## Pagination via the Node.js client library
Cursor-based pagination is not yet supported in the Node.js client library. Instead, we recommend batching your requests by date range and concatenating the results. This will avoid overwhelming QuickBooks Desktop by requesting only a subset of the data at a time.
For example, the following fetches all invoices from the provided date range in yearly batches:
```ts Fetch invoices in yearly batches
import Conductor, { QbdTypes } from "conductor-node";
async function getQbdInvoices(
endUserId: string,
startDate: string,
): Promise {
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
const startYear = new Date(startDate).getFullYear();
const endYear = new Date().getFullYear();
// Fetch invoices in yearly batches to avoid overwhelming QuickBooks Desktop
// because some users have tens of thousands of invoices.
const allInvoices: QbdTypes.InvoiceRet[] = [];
for (let year = startYear; year <= endYear; year++) {
const yearStartDate = year === startYear ? startDate : `${year}-01-01`;
const yearEndDate = `${year}-12-31`;
const yearInvoices = await conductor.qbd.invoice.query(endUserId, {
TxnDateRangeFilter: {
FromTxnDate: yearStartDate,
ToTxnDate: yearEndDate,
},
});
allInvoices.push(...yearInvoices);
}
return allInvoices;
}
```
## Pagination via the REST API
If you are using the REST API directly, you can paginate requests by following the instructions below.
### Initiating pagination
To paginate a QuickBooks Desktop query, include the `MaxReturned` parameter in your request body, specifying the maximum number of records you want to receive in a single response. If the total number of records exceeds `MaxReturned`, the response will include two additional fields:
1. `IteratorID`: A unique identifier for the current query.
2. `IteratorRemainingCount`: The number of records remaining to be fetched.
Here's an example of a pagination request:
```sh Start pagination request with MaxReturned
curl -X POST https://api.conductor.is/v1/end-users/{{END_USER_ID}}/request/quickbooks_desktop \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"InvoiceQueryRq": {
"MaxReturned": 2
}
}'
```
And here's an example of a pagination response:
```json Example pagination response with IteratorID and IteratorRemainingCount
{
"InvoiceQueryRs": {
"IteratorID": "fce6b40f-9700-435b-949c-f2587af31536",
"IteratorRemainingCount": 0,
"InvoiceRet": [
{
"TxnID": "4E4-1703631996",
"TimeCreated": "2021-01-01T00:00:00Z",
"CustomerRef": {
"ListID": "80000020-1703631977",
"FullName": "Alice"
},
"RefNumber": "INV-1",
"IsPaid": true,
"TotalAmount": 100
},
{
"TxnID": "4E4-1703631997",
"TimeCreated": "2021-01-02T00:00:00Z",
"CustomerRef": {
"ListID": "80000020-1703631978",
"FullName": "Bob"
},
"RefNumber": "INV-2",
"IsPaid": false,
"TotalAmount": 200
}
]
}
}
```
### Continuing pagination
**If `IteratorRemainingCount` is greater than 0**, send another request with the same request body as the previous request, but include the `IteratorID` parameter on the root level of the request body, set to the value from the previous response.
The parameter `IteratorID` goes on the root level of the request body, not
inside the query object.
```sh Continue pagination request with IteratorID
curl -X POST https://api.conductor.is/v1/end-users/{{END_USER_ID}}/request/quickbooks_desktop \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
// ❗ `IteratorID` is at root level of the request body
"IteratorID": "fce6b40f-9700-435b-949c-f2587af31536",
"InvoiceQueryRq": {
"MaxReturned": 1000
}
}'
```
### Considerations
* **The iterator can only be used within the same QuickBooks Web Connector session, which we keep open for 10 seconds.** If the iterator is not used within that time, you will receive an error. Therefore, you must implement the pagination logic programmatically in your backend to ensure that the iterator is used within the 3-second window.
* The short expiry is due to how the QuickBooks Web Connector handles pagination. Upon the initial request, the QuickBooks Web Connector requests the entire result set from QuickBooks Desktop, stores it in local memory, and returns only the first batch. As a result, the first request will take longer because QBD must process and assemble the entire result set. Subsequent requests will return immediately.
* If you attempt to use the iterator after the previous request returned `IteratorRemainingCount` of `0`, you will receive an error.
# REST API for QuickBooks Desktop
If your backend does not use Node.js, you can use the REST API to interface with QuickBooks Desktop directly.
If your backend is not in Node.js, you can use the REST API that powers our Node.js library to send requests to QuickBooks Desktop. To do so, we *strongly* recommend following the guide below to **set up Node.js and TypeScript locally to *test* Conductor, and enable verbose logging to see the REST API request format**, which you can then copy and paste to your backend. This approach enables you to easily determine the APIs and parameters you need by leveraging the client library's type-safety, autocomplete, and inline docs.
Skip to Step 10 below to see the REST API request format.
We are actively working on a complete rewrite of our REST API for QuickBooks Desktop that is much more powerful and much simpler. Available in Q1 2025.
In the meantime, use the approach documented below, which will be backward-compatible and easily adaptable to the new REST API when it is released.
Check out this [Python example for creating an
invoice](/qbd-examples/invoices#creating-invoices) in QuickBooks Desktop using
Conductor's REST API.
## Build your REST API requests with Node.js locally and Conductor
This guide will show you how to easily generate the REST API request format for QuickBooks Desktop using Node.js and Conductor in your local environment. You can then replicate the REST API request format in your backend.
If you are on a Mac:
```sh
brew install node
```
```sh
mkdir conductor-test
cd conductor-test
```
```sh
npm init -y
```
```sh
npm install conductor-node typescript @types/node
```
```sh
touch index.ts
```
If you haven't already, follow our [quickstart guide](/overview/quickstart) to create an EndUser with an authorized connection to a QuickBooks Desktop instance.
```typescript
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}", {
// ❗ Enable logging to see the REST API request format.
verbose: true,
});
async function main() {
// ❗ Replace `{{END_USER_ID}}` below with the ID of the EndUser
// you created in the Quickstart guide.
const invoices = await conductor.qbd.invoice.query("{{END_USER_ID}}", {
IncludeLineItems: true,
MaxReturned: 5,
});
};
main();
```
```sh
npx ts-node index.ts
```
You will see the complete REST API request format in the output. For example:
```ts
Conductor request: {
method: 'POST',
url: 'https://api.conductor.is/v1/end-users/{{END_USER_ID}}/request/quickbooks_desktop',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer sk_live_************',
},
body: {
InvoiceQueryRq: {
IncludeLineItems: true,
MaxReturned: 3
}
}
}
```
For example, with `curl`:
```sh
curl -X POST https://api.conductor.is/v1/end-users/{{END_USER_ID}}/request/quickbooks_desktop \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"InvoiceQueryRq": {
"IncludeLineItems": true,
"MaxReturned": 3
}
}'
```
# Create a QuickBooks Desktop test instance
Create your own QuickBooks Desktop test instance with an AWS WorkSpace.
export const Image = ({src, alt, width, shadow = true, border = true}) => ;
To develop and test integrations with Conductor, you need your own QuickBooks Desktop instance to send and receive data. If you don't have an existing instance, this guide outlines a one possible approach for setting up a dedicated QuickBooks Desktop test environment. We will guide you through the process of creating a virtual Windows instance using AWS WorkSpaces and installing the QuickBooks Desktop free trial. Once set up, you can connect your local development environment to this test instance via Conductor, enabling you to validate your integration without impacting production data.
## 1. Set up a virtual Windows environment
Create a new Amazon WorkSpace at [https://us-west-2.console.aws.amazon.com/workspaces/v2/workspaces](https://us-west-2.console.aws.amazon.com/workspaces/v2/workspaces).
Either select the directory in the list or click `Create a new Directory` if there are none:
Add yourself as a user with your email address:
Select the bundle `Standard with Windows 10 (Server 2019 based) (PCoIP)`:
Select `AlwaysOn`:
Skip the Customization step, then review the final page and click the button `Create` in the bottom-right corner:
After 20-30 minutes, look for an email from Amazon WorkSpaces with a link to set a password.
Download Amazon WorkSpaces on your local computer:
```sh
brew install amazon-workspaces
```
Open the WorkSpaces app, enter the registration key from the email, and sign in using the username and password you set via the reset link in the email. You must enter this password every time you open WorkSpaces, so best to save it to your local password manager.
After it loads, you will see your new Windows desktop instance!
## 2. Disable IE Enhanced Security Configuration
By default, you will see the following warning whenever you open QuickBooks Desktop. If you do not resolve this issue, this warning will freeze QuickBooks Desktop whenever the QuickBooks Web Connector opens QuickBooks Desktop when it is closed.
To prevent this error, follow these steps:
Search for and open Server Manager:
Choose `Local Server` from the left navigation pane:
For `IE Enhanced Security Configuration`, click the button that says `On`:
For Administrators, select `Off`. For Users, select `Off`. Choose `OK`. Then
you are done!
## 3. Install QuickBooks Desktop
From the Windows instance, open Firefox and download the QuickBooks Desktop
Enterprise trial:
[https://quickbooks.intuit.com/learn-support/en-us/new-subscriptions/download-a-trial-of-quickbooks-desktop/00/185974](https://quickbooks.intuit.com/learn-support/en-us/new-subscriptions/download-a-trial-of-quickbooks-desktop/00/185974)
Navigate to the "Downloads" directory in the Windows File Explorer, and
launch the application named `QuickBooksEnterprise23Trial.exe`. Then, walk
through the installation.
After that installation finishes, another installer should launch
automatically. Walk through that installer, too. This can take 20-30 minutes
to finish.
Next, the following window will appear. Select the variant `QuickBooks
Desktop Enterprise General Business`:
Click "I want to see a Sample company file", which will provide a mock
dataset for you to use with QuickBooks Desktop. If this option does not
work, which sometimes happens, then click "I'm ready to create my own
company file" to create a new, empty company file.
If prompted, sign in to your Intuit developer account in QuickBooks Desktop.
If you do not have one, [you can create account
here](https://accounts.intuit.com/app/sign-in?start_screen_hint=SignUp).
When you are done, you will see the QuickBooks Desktop interface:
At some point, QuickBooks Desktop might ask you to create a password.
Conductor will not ask for this password; it is internal to QuickBooks
Desktop.
The trial installation will work for 30 days, after which you will need a
developer (NFR) license, which you can [get for free by following our
guide](/qbd/dev-license.mdx). After completing that guide, you can continue
to use the trial version while you wait for your NFR license to arrive.
## 4. Connect Conductor to your QuickBooks Desktop instance
Now that you have your own QuickBooks Desktop test instance, you can return to the [Quickstart](/overview/quickstart) guide to connect it to Conductor. Don't worry; this part is much easier.
# Connect your users via the auth flow
Enable your users to securely connect their QuickBooks Desktop to your application.
The authentication flow in Conductor is a user interface walkthrough that allows your users to securely connect their QuickBooks Desktop installation to their Conductor account. For an example, check out this [demo of the auth flow](https://connect.conductor.is/qbd/demo).
There are two main approaches to integrating the auth flow with your application:
1. Integrate the auth flow with your backend to manage multiple users and connections.
2. Generate shareable auth links for getting started quickly or one-off connections.
## Integrate the auth flow with your backend
If you are building a multi-user service where each user needs to connect their QuickBooks Desktop account to your application, you'll want to integrate Conductor's QuickBooks Desktop auth flow into your backend.
Consider you have an end-user of your application who needs to connect their QuickBooks Desktop to your application. Begin by creating an EndUser for that user and saving their `id` to your database. You will use this `id` to match your users to their corresponding QuickBooks Desktop connection in Conductor.
If your database has a `users` table, consider creating a column called `conductor_end_user_id`.
```ts Create an EndUser
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
// Replace the placeholders with your actual data.
const endUser = await conductor.endUsers.create({
companyName: "{{END_USER_COMPANY_NAME}}",
sourceId: "{{UNIQUE_ID_FROM_YOUR_DB}}",
email: "{{END_USER_EMAIL}}",
});
// Save the EndUser ID to your database.
await db.users.update({
conductorEndUserId: endUser.id,
});
```
The next step is to initiate an AuthSession for your user to connect their QuickBooks Desktop. However, what if they already has an active connection? Or, what if they previously started the auth flow but didn't complete it?
Imagine your application has a web app where your users configure the integrations with their application. If you create a section for the QuickBooks Desktop integration, you can use the following approach to track whether an active connection already exists:
```ts Check the connection status
try {
// Ping to check the connection status.
await conductor.endUsers.ping("{{END_USER_ID}}", "quickbooks_desktop");
updateUI("QuickBooks Desktop is successfully connected!");
} catch (error) {
if (error instanceof ConductorIntegrationConnectionError) {
if (error.code === "INTEGRATION_CONNECTION_NOT_SET_UP") {
// Initiate an AuthSession if the user never started or completed the auth flow.
const authSession = await conductor.authSessions.create({
publishableKey: "{{YOUR_PUBLISHABLE_KEY}}",
endUserId: "{{END_USER_ID}}",
});
updateUI("Set up your QuickBooks Desktop connection: " + authSession.authFlowUrl);
} else {
// Display connection errors for your user to resolve.
updateUI("An error occurred: " + error.userFacingMessage);
}
} else {
throw error;
}
}
```
***Note:** Replace `updateUI()` with your actual code that updates your application's UI based on the status or errors received.*
## Create a shareable auth flow link
For a quick start, particularly useful for pilot deployments or small-scale operations, generate a secure, shareable link for the QuickBooks Desktop auth flow:
If you haven't already done so, create an EndUser and save their `id`. You will use this `id` to authenticate future requests.
```ts Node.js
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
// Replace these placeholders with your own values.
const endUser = await conductor.endUsers.create({
companyName: "{{END_USER_COMPANY_NAME}}",
sourceId: "{{UNIQUE_ID_FROM_YOUR_DB}}",
email: "{{END_USER_EMAIL}}",
});
console.log("Save this EndUser ID to auth future requests:", endUser.id);
```
```sh cURL
curl -X POST https://api.conductor.is/v1/end-users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"companyName": "{{END_USER_COMPANY_NAME}}",
"sourceId": "{{UNIQUE_ID_FROM_YOUR_DB}}",
"email": "{{END_USER_EMAIL}}"
}'
```
Using the EndUser ID, create an AuthSession with an extended link expiry time if needed:
```ts Node.js
import Conductor from "conductor-node";
const conductor = new Conductor("{{YOUR_SECRET_KEY}}");
const authSession = await conductor.authSessions.create({
publishableKey: "{{YOUR_PUBLISHABLE_KEY}}",
endUserId: "{{END_USER_ID}}",
linkExpiryMins: 60 * 24, // 24 hours
});
console.log("Send this link to your customer to complete the auth flow:", authSession.authFlowUrl);
```
```sh cURL
curl -X POST https://api.conductor.is/v1/auth-sessions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}" \
-d '{
"publishableKey": "{{YOUR_PUBLISHABLE_KEY}}",
"endUserId": "{{END_USER_ID}}",
"linkExpiryMins": 1440
}'
```
Share the generated `authFlowUrl` with your end-user to direct them to the auth flow to connect their QuickBooks Desktop instance to your application.
The link will resemble this mock example:
```
https://connect.conductor.is/qbd/auth_sess_client_secret_1234567abcdefg?key={{YOUR_PUBLISHABLE_KEY}}
```
# Autocomplete
Use Conductor's built-in autocomplete to discover all available APIs, requests parameters, and response fields.
We highly recommend using [Conductor's client library](https://github.com/conductor-is/quickbooks-desktop-api) because it has built-in autocomplete and documentation for every API, request parameter, and response field. This feature is especially helpful for working with the QuickBooks Desktop API.
The following examples show the autocomplete in action in VS Code, though this works in any modern editor.
#### QuickBooks Desktop object types
![Conductor autocomplete for QuickBooks Desktop object
types](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-object-types.jpg)
#### Request parameters
![Conductor autocomplete for QuickBooks Desktop request
parameters](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-request-parameters.jpg)
#### Response fields
![Conductor autocomplete for QuickBooks Desktop response
fields](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-response-fields.jpg)
#### Enum values
![Conductor autocomplete for QuickBooks Desktop enum
values](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-enum-values.jpg)
#### Inline documentation for request parameters
![Conductor inline documentation for QuickBooks Desktop request
parameters](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-docs-request-parameters.jpg)
#### Inline documentation for response fields
![Conductor inline documentation for QuickBooks Desktop response
fields](https://mintlify.s3.us-west-1.amazonaws.com/conductor/images/usage/autocomplete/qbd-docs-response-fields.jpg)
# Check an EndUser's connection status
Sometimes, it is useful to check whether an EndUser's IntegrationConnection is working. For example, you might want to display a "connection status" indicator in your app's UI.
To do this, you can use the [method `conductor.endUsers.ping()`](/apis/end-users/ping) to check whether the specified IntegrationConnection can connect and process requests end-to-end. If an error occurs, we strongly recommend displaying [the property `error.userFacingMessage`](/usage/error-handling#user-facing-error-messages) to your EndUser in your app's UI because it contains instructions for how your EndUser can resolve the error.
```ts Node.js
try {
await conductor.endUsers.ping(endUserId, "quickbooks_desktop");
} catch (error) {
if (error instanceof ConductorError) {
// Update your app's UI to display `error.userFacingMessage`, which explains
// that the connection is failing and how to resolve the error.
}
// ...
}
```
```sh cURL
curl -X GET https://api.conductor.is/v1/end-users/{{END_USER_ID}}/ping/quickbooks_desktop \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{YOUR_SECRET_KEY}}"
```
# Error handling
Catch and respond to connection errors, invalid requests, data problems, and more.
One of the most complicated aspects of QuickBooks Desktops is its error handling. QuickBooks's errors are often cryptic and unhelpful, and they can arise from several sources (e.g., Web Connector, QB request processor, QuickBooks Desktop itself), each using a different format and mechanism. Sometimes, their errors do not even describe what went wrong when they could! **Conductor unifies and simplifies these errors into a single, consistent error format and augments each with our own user-friendly language that describes how to resolve the issue.**
With Conductor, every error is an instance of [ConductorError](/apis/errors/object), each with plenty of useful information.
## Error types
Any error object you receive will be an instance of one of the following error types:
| Name | Description |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ConductorIntegrationError` | Raised when the third-party integration encounters an error while processing the end-user's request. This often results from an issue with the request or data handling that requires your attention to resolve.
E.g., a `ListID` you provided was not found in QuickBooks Desktop, or an accounting value you supplied did not adhere to the integration's accounting rules.
Refer to `error.integrationCode` for the error code returned by the integration, if available. |
| `ConductorIntegrationConnectionError` | Raised when a connection error occurs with the third-party integration on the end-user's side. This typically indicates an issue with the end-user's IntegrationConnection or configuration, which they must resolve. In other words, you cannot take action to fix these errors.
E.g., QuickBooks Web Connector (QBWC) failed to connect to QuickBooks Desktop on the end-user's computer.
Refer to `error.integrationCode` for the error code returned by the integration connector, if available.
❗ We recommend *not* triggering alerts for these errors because only the end-user can fix them. See [Global error handling](#global-error-handling) for an example of this. |
| `ConductorInvalidRequestError` | Raised when you make an API call with the wrong parameters, in the wrong state, or in an invalid way. |
| `ConductorAuthenticationError` | Raised when Conductor cannot authenticate you with the credentials you provided. E.g., an incorrect API key. |
| `ConductorPermissionError` | Raised when you attempt to access a resource that is not allowed. |
| `ConductorConnectionError` | Raised when there was a network problem between the client (on your server) and Conductor's servers. E.g., a downed network or a bad TLS certificate. |
| `ConductorInternalError` | Raised when something went wrong on Conductor's end. (These are rare.) |
## User-facing error messages
Every [ConductorError](/apis/errors/object) includes two error messages, and you should use both:
1. `error.message`: The technical error message that you should log for debugging.
2. `error.userFacingMessage`: The descriptive user-friendly error message explicitly written for the end-user that often contains instructions helping the end-user resolve the issue.
Your app's UI should display `error.userFacingMessage` to your end-users for
every `ConductorError` while logging the full `error` object for your
debugging purposes.
For example, see the `message` and `userFacingMessage` in the following QBD connection error:
```ts Example ConductorError
{
// The developer-facing error message, which includes the QBD-provided
// error code and the QBD-provided error message.
message: `QBD Connection Error (0x80040420): The QuickBooks user has
denied access.`,
// The user-facing error message with instructions for the end-user to
// resolve the issue.
userFacingMessage: `We could not connect to QuickBooks Desktop because
we must re-authorize our connection. To fix this, open QuickBooks
Desktop, log in as Admin, navigate to "Edit > Preferences >
Integrated Applications", click "Company Preferences", select our
app, click "Properties...", ensure "Allow this application to log in
automatically" is checked, then click "OK". Then try again.`,
...
// Other properties omitted for example.
}
```
## Specific error handling
If you need special handling for specific errors, you can wrap individual API calls, as shown below.
Using `async`/`await`:
```ts
try {
const newAccount = await conductor.qbd.account.add(endUserId, {
Name: "Test Account",
AccountType: "Bank",
OpenBalance: "100",
});
} catch (error) {
if (error instanceof ConductorError) {
// Check `error.code`, `error.integrationCode`, etc., for special handling.
} else {
// ...
}
}
```
Or in the form of a rejected promise:
```ts
conductor.qbd.account
.add(endUserId, {
Name: "Test Account",
AccountType: "Bank",
OpenBalance: "100",
})
.then((newAccount) => {
// ...
})
.catch((error) => {
if (error instanceof ConductorError) {
// Check `error.code`, `error.integrationCode`, etc., for special handling.
} else {
// ...
}
});
```
## Global error handling
It is unnecessary to wrap each API call individually, as demonstrated in the examples above. Instead, we suggest implementing a global error handler for your server, such as [`app.use((error, ...) => { ... })` in Express](https://expressjs.com/en/guide/error-handling.html#writing-error-handlers) or [`formatError` in Apollo Server](https://apollographql.com/docs/apollo-server/data/errors/#for-client-responses). Within this handler, perform the following actions:
1. For any `ConductorError` instance, display the `error.userFacingMessage` property to the end-user in your app's UI while logging the complete error object.
2. For all `ConductorError` instances, transmit the full error object to your error-tracking service (e.g., Sentry):
* Send a **warning** for instances of `ConductorIntegrationConnectionError`, which are not actionable by you and can only be resolved by the end-user; for example, failure to connect to QuickBooks Desktop on the end-user's computer.
* Send an **error** for all other `ConductorError` instances, such as an invalid API key.
For example, using an [Express error handler](https://expressjs.com/en/guide/error-handling.html#writing-error-handlers):
```ts
import * as Sentry from "@sentry/node";
import {
ConductorError,
ConductorIntegrationConnectionError,
} from "conductor-node";
app.use((error, req, res, next) => {
if (error instanceof ConductorError) {
Sentry.captureException(error, {
level:
error instanceof ConductorIntegrationConnectionError
? "warning"
: "error",
});
// Return a different error message for your end-user to see in your
// app's UI.
res.status(500).send({ error: { message: error.userFacingMessage } });
} else {
// ...
}
});
```
Or using [Apollo Server's error handler](https://apollographql.com/docs/apollo-server/data/errors/#for-client-responses):
```ts
import { ApolloServer } from "@apollo/server";
import { unwrapResolverError } from "@apollo/server/errors";
import * as Sentry from "@sentry/node";
import {
ConductorError,
ConductorIntegrationConnectionError,
} from "conductor-node";
const server = new ApolloServer({
// ...
formatError: (formattedError, error) => {
const origError = unwrapResolverError(error);
if (origError instanceof ConductorError) {
Sentry.captureException(origError, {
level:
origError instanceof ConductorIntegrationConnectionError
? "warning"
: "error",
});
return {
...formattedError,
// Return a different error message for your end-user to see in
// your app's UI.
message: origError.userFacingMessage,
};
}
// ...
return formattedError;
},
});
```
# API keys
Use API keys to authenticate API requests.
Conductor authenticates your API requests using your account's API keys. If a request does not include a valid key, Conductor returns an invalid request error.
## Secret and publishable keys
Every Conductor account has two API keys:
1. **Secret key:** Use this key to authenticate requests to Conductor's API from your server-side code. It is highly sensitive and should be deleted if leaked. Store this key securely in your server, such as in an environment variable or a credential management system. Do not store this key in Git, include it in client-side code, or expose it on a website.
2. **Publishable key:** Use this key when [creating an AuthSession](/apis/auth-sessions/create), which generates the unique [auth flow](/usage/auth-flow) URL for your end-user. Unlike the secret key, the publishable key can be safely shared, stored in Git, or included in client-side code.