QBWC lets your Rails 4 application talk to QuickBooks Desktop.

Build Status


gem install qbwc

Or add it to your Gemfile

gem "qbwc"

and run

bundle install


Run the generator:

rails generate qbwc:install

Then the migrations:

rake db:migrate

Open config/initializers/qbwc.rb and check the settings there. (Re-)start your app.

Quickbooks requires HTTPS connections when connecting to remote machines. ngrok may be useful to fulfill this requirement.

Authentication and multiple company files

If connecting to more than one company file or if you want different logins for different users, you can configure QBWC authentication. This is a Proc in config/initializers/qbwc.rb that accepts the username and password and returns the path to the QuickBooks company file to access:

c.authenticator = Proc.new{|username, password|
  # qubert can access Oceanic
  next "C:\\QuickBooks\\Oceanic.QBW" if username == "qubert" && password == "brittany"
  # quimby can access Veridian
  next "C:\\QuickBooks\\Veridian.QBW" if username == "quimby" && password == "bethany"
  # no one else has access
  next nil

QuickBooks configuration

Install QuickBooks Web Connector on the machine that has QuickBooks installed.

For a single-user, single-company install, on the QuickBooks machine, visit the path /qbwc/qwc on your domain over an HTTPS connection. Download the file it provides. In QuickBooks Web Connector, click "Add an application", and pick the file. Give Quickbooks the password you specified in config/initializers/qbwc.rb.

At this point, QuickBooks Web Connector should be able to send requests to your app, but will have nothing to do, and say "No data exchange required".

Multiple users and multiple company files

If you want to have more than one person to connect to the same QuickBooks company file, you will need to manually edit the QWC file to change the OwnerID (any GUID will do) before giving it to QuickBooks Web Connector.

If you want each person to have their own login, set up authentication per Authentication and multiple company files. In the QWC file, you will need to change UserName.

If you are connecting to multiple company files, you will additionally need to change AppName and FileID (any GUID) to be unique to each file.

Creating jobs

QuickBooks Web Connector (the app you installed above) acts as the HTTP client, and your app acts as the HTTP server. To have QuickBooks perform tasks, you must add a qbwc job to your app, then get QuickBooks Web Connector to check your app for work to do.

To create a job (e.g. from rails console or wherever):

require 'qbwc'
QBWC.add_job(:list_customers, true, '', CustomerTestWorker)
  • The first argument is a unique name for the job. You can use this later to disable or delete the job.
  • The second argument indicates whether the job is initially enabled.
  • The third argument specifies the path to the QuickBooks company file this job affects. An empty string will make the job run against any company file.
  • The fourth argument is your worker class. See the next section for a description of workers.

Your job will be persisted in your database and will remain active and run every time QuickBooks Web Connector runs an update. If you don't want this to happen, you can have have your job disable or delete itself after completion. For example:

    def handle_response(r, session, job, request, data)

Alternately, you can custom logic in your worker's requests and should_run? methods, as described below.


A job is associated to a worker, which is an object descending from QBWC::Worker that can define three methods:

  • requests(job) - defines the request(s) that QuickBooks should process - returns a Hash or an Array of Hashes.
  • should_run?(job) - whether this job should run (e.g. you can have a job run only under certain circumstances) - returns Boolean and defaults to true.
  • handle_response(response, session, job, request, data) - defines what to do with the response from Quickbooks.

All three methods are not invoked until a QuickBooks Web Connector session has been established with your web service.

A sample worker to get a list of customers from QuickBooks:

require 'qbwc'

class CustomerTestWorker < QBWC::Worker

    def requests(job)
            :customer_query_rq => {
                :xml_attributes => { "requestID" =>"1", 'iterator'  => "Start" },
                :max_returned => 100

    def handle_response(r, session, job, request, data)
        # handle_response will get customers in groups of 100. When this is 0, we're done.
        complete = r['xml_attributes']['iteratorRemainingCount'] == '0'

        r['customer_ret'].each do |qb_cus|
            qb_id = qb_cus['list_id']
            qb_name = qb_cus['name']
            Rails.logger.info("#{qb_id} #{qb_name}")


Use the Onscreen Reference for Intuit Software Development Kits (use Format: qbXML) to see request and response formats to use in your jobs. Use underscored, lowercased versions of all tags (e.g. customer_query_rq, not CustomerQueryRq).

Referencing memory values when constructing requests

A QBWC::Worker#requests method cannot access values that are in-memory (global variables, local variables, model attributes, etc.) at the time that QBWC.add_job is called; however, in lieu of using QBWC::Worker#requests, you can construct and pass requests directly to QBWC.add_job (Hash, String, or array of Hashes and Strings). These requests will be immediately persisted by QBWC.add_job (in contrast to requests constructed by QBWC::Worker#requests, which are persisted during a QuickBooks Web Connector session).

If requests are passed to QBWC.add_job, the requests method on your worker will be ignored.

Referencing memory values when handling responses

Similarly, a QBWC::Worker#handle_response method cannot access variables that are in-memory at the time that QBWC.add_job is called; however, you can optionally pass a serializable value (for example, String, Array, or Hash) to QBWC.add_job. This data will immediately be persisted by QBWC.add_job, then later passed to QBWC::Worker#handle_response during a QuickBooks Web Connector session.


In certain cases, you may want to perform some initialization prior to each QuickBooks Web Connector session. For this purpose, you may optionally provide initialization code that will be invoked once when each QuickBooks Web Connector session is established, and prior to executing any queued jobs. This initialization code will not be invoked for any session in which no jobs are queued.

You assign this initialization code either (a) during configuration, and/or (b) in application code by calling set_session_initializer (prior to any QuickBooks Web Connector session being established). For example:

In config/initializers/qbwc.rb:

c.session_initializer = Proc.new{|session|
  puts "New QuickBooks Web Connector session has been established (configured session initializer)"

In application code: ```ruby require 'qbwc'

QBWC.set_session_initializer() do |session|
      puts "New QuickBooks Web Connector session has been established (overridden session initializer)"
      @information_from_jobs = {}
    end if the_application_needs_a_different_session_initializer

    QBWC.add_job(:list_customers, false, '', CustomerTestWorker)


Note: If you set_session initializer in your application code, you're only affecting the process that your application code runs in. A request to another process (e.g. if you're multiprocess or you restarted the server) means that QBWC won't see the session initializer.

Note: a QuickBooks Web Connector session is established when you manually run (update) an application's web service in QuickBooks Web Connector, or when QuickBooks Web Connector automatically executes a scheduled update.

Handling errors

By default, when an error response is received from QuickBooks, QBWC::Worker#handle_response will be invoked but no further requests will be processed in the current job or in subsequent jobs. However, the job will remain persisted and so will be attempted again at next QuickBooks Web Connector session. Unless there is some intervention, presumably the job will fail again and block all remaining jobs and their requests from being serviced.

To have qbwc continue with the next request after receiving an error, set on_error to :continue in config/initializers/qbwc.rb.

Contributing to qbwc

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Run tests - rake test.