New Python Sample App for QuickBooks Online API

Are you a Python developer? We have had many requests for more help for devs using Python. We are happy to announce that, in response, we’ve created a new sample app that gives you a working example of how to use the QuickBooks Online API in Python.

The features of this sample app include:

  1. Importing data from an external Excel file
  2. Creating a customer in your Sandbox company using the QuickBooks API
  3. Implementing the Connect to QuickBooks button using OAuth 1.0

This sample app uses the Flask web framework with Python2.7.

You can find the app in our GitHub repository.

What do you think?  Based on your feedback, we’ll improve and extend the features.





6 responses to “New Python Sample App for QuickBooks Online API”

  1. xtiansimon Avatar

    Thanks Nikita. I’m looking forward to diving into your sample. Just two questions. Why did you choose Python 2.7? and Your example seems to cover just the AR side, do you plan to make other samples for the rest of the cycle?

    1. Nikita Avatar

      Hi. A lot of our third party developers code in Python 2.7 which is why I chose it. Right now, this app has very limited functionality as this is supposed to be a starting point for new developers. I will have future releases with additional features though. I do appreciate your feedback.

  2. xtiansimon Avatar

    > “Right now, this app has very limited functionality as this is supposed to be a starting point for new developers.”

    And as I’m sure you know, the starting points for doing actual business bookkeeping are income and expenses for the purpose of producing the basic financial statements: “Balance Sheet, Income Statements, Statement of Cash Flows…”– literally Text Book. I’m looking forward to when Intuit makes a commitment to help customers make QuickBooks more efficient using Python, rather than these half measures.

    1. Nikita Avatar

      Hi, this app aims to show how to work with OAuth as a first step along with a few other things. There are plans to add features to it in the future.

  3. Rosie Avatar

    Hi–I am using your sample app as a basic framework for an app I am working on. I am having issues retrieving User Profile information.

    def getUserProfile(access_token):
    userinfo_endpoint = discovery_document.userinfo_endpoint
    stdlib.logw(userinfo_endpoint, ‘USER INFO ENDPOINT’)
    stdlib.logw(access_token, “ACCESS TOKEN BEFORE HEADERS”)
    auth_header = ‘Bearer ‘ + access_token
    headers = {‘Accept’ : ‘application/json’, ‘Authorization’ : auth_header} #’accept’ : ‘application/json’
    stdlib.logw(headers, “HEADERS”)
    response = requests.get(userinfo_endpoint, headers=headers)
    status_code = response.status_code
    stdlib.logw(response, ‘RESPONSE FROM USER PROFILE:’)

    return response
    When I print out the response code, I get a 403 error. Could you help?

    Also, in Views, a realmId is always generated when I complete my data authorization, but in the code, it looks like I will never trigger the loop if I have a realmId to make the call to getUserProfile

    def connected(request):
    stdlib.logw(request.session, ‘REQUEST SESSION’)
    access_token = request.session.get(‘accessToken’,None)
    if access_token is None:
    return HttpResponse(‘Your Bearer token has expired, please initiate Sign In With Intuit flow again’)

    refresh_token = request.session.get(‘refreshToken’,None)
    realmId = request.session[‘realmId’]
    stdlib.logw(realmId, ‘REALMID’)

    if realmId is None:
    user_profile_response = services.getUserProfile(access_token)
    user_profile = user_profile_response.json()
    stdlib.logw(user_profile, ‘USER PROFILE’)

    if user_profile_response.status_code >= 400:
    # if call to User Profile Service doesn’t succeed then get a new bearer token from refresh token and try again
    bearer = services.getBearerTokenFromRefreshToken(refresh_token)
    user_profile_response = services.getUserProfile(bearer.accessToken)
    stdlib.logw(user_profile_response, ‘USER PROFILE RESPONSE’)

    if user_profile_response.status_code >= 400:
    return HttpResponseServerError()
    c = {
    ‘first_name’: user_profile_response.get(‘givenName’,’ ‘),
    if request.session.get(‘name’) is None:
    stdlib.logw(request.session.get(‘name’), ‘REQUEST SESSION’)
    name = ”
    name = request.session.get(‘name’)
    c = {
    ‘first_name’: name,

    1. Rosie Avatar

      I didn’t realize that this would be so arduous to read because all of the CRs are removed. I am having problems retrieving the User Profile information so that I can populate the user’s name onto the page. When getUserProfile is called, I am retrieving a 403 error. While I was troubleshooting the problem in both services and views, I notice that the loop in the connected function never triggers calling getUserProfile because I always generate a realID. Let me know if there is a better medium to send you formatted code, e.g. Slack, Intuit support.

Leave a Reply

Your email address will not be published. Required fields are marked *