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 end of June 2024.

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 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.

1

Install Node.js locally if you do not have it already

If you are on a Mac:

brew install node
2

Create a new directory

mkdir conductor-test
cd conductor-test
3

Initialize a new Node.js project

npm init -y
4

Install TypeScript and Conductor's Node.js library

npm install conductor-node typescript @types/node
5

Create a new TypeScript file

touch index.ts
6

Follow our quickstart guide if you haven't yet

If you haven’t already, follow our quickstart guide to create an EndUser with an authorized connection to a QuickBooks Desktop instance.

7

Add the following code to your `index.ts` file

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();
8

Run the code

npx ts-node index.ts
9

Review the output

You will see the complete REST API request format in the output. For example:

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
    }
  }
}
10

Replicate the REST API request format in your backend

For example, with curl:

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
    }
  }'

Pagination

Conductor is working on a new version of our REST API for QuickBooks Desktop with many improvements, including built-in pagination support. However, if you are using the current version of our QuickBooks Desktop REST API directly, you can paginate the results by following the instructions below. Please note that this functionality is not available in our Node.js client library, which will gain pagination support when we release the new version of the REST API.

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:

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:

Example pagination response with IteratorID and IteratorRemainingCount
{
  "IteratorID": "ABC123",
  "IteratorRemainingCount": 0,
  "InvoiceQueryRs": {
    "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 set to the value from the previous response:

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": "ABC123",
    "InvoiceQueryRq": {
      "MaxReturned": 1000
    }
  }'

Considerations

  • The iterator can only be used within the same QuickBooks Web Connector session, which we keep open for 3 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.