Integrate with the QuickBooks Online API

This is a guide to creating an eCommerce integration with QuickBooks Online and Payments APIs, showing:

This guide is for developers who want to implement an eCommerce app. The QuickBooks entities used in this exercise are Sales Receipt, Customers, and Items for QuickBooks Online API and Charges and Tokens for Payments API. In order get the most out of this information, you need the following:

The sample transaction

For this scenario, your sandbox serves as the QuickBooks company that manages the transaction where Pye’s Cakes buys twenty sprinkler pipes from the merchant with a credit card. All moving parts for this transaction are explored.

A note about OAuth access tokens

For the complete cycle of a merchant service credit card transaction, corresponding QuickBooks sales transactions, and settlement reconciliation to work properly, it is critical that the Payments connection and QuickBooks connection be on the same companyId. This is typically accomplished by ensuring that when you request an OAuth access token and secret you provide the complete picture of what your user expects your app to be doing with QuickBooks data sources. In your OAuth authorization implementation select both com.intuit.quickbooks.accounting and com.intuit.quickbooks.payments scopes.

When your user changes their settings to turn ON a new part of your integration with QuickBooks, initiate a subsequent request for a set of OAuth access token and secret to ensure that the correct services are setup on the company for your application. The worst possible situation would be for you to transact credit cards using a payments account set up for one company, while syncing the corresponding business transaction to a completely different QuickBooks company. Reconciliation will fail at best, and at worst, you are transacting for one business using the payments account of another business (albeit owned by the same user) which is fraudulent use of the QuickBooks payments service and can lead to service disruption for the merchant.

Processing the order
qbpayments/docs/workflows/Merchant_Order_Processing.png
Gather info from customer

Accept order from the customer, request credit card details.

Order: 20 sprinkler pipes at $4 each = $80.00

Use customer information once or save, based on the merchant’s business model. To save, create an account and store detail in Customer object, credit card details in Payments API Cards object (opaque to merchant).

Creating the charge

Information in this section shows you how to submit a credit card charge to QuickBooks Payments via the API, without the need to swipe the physical card. There are three steps:

  1. Create a token—Your app’s browser code collects credit card information on behalf of the merchant and sends the token request, resulting in an opaque container to use in the subsequent charge request. In this way, your servers are immune for seeing or storing any credit card information.
  2. Authorize the purchase—The first half of the credit card transaction. Before the merchant ships the product, he receives authorization from the credit card issuer that the merchandise will be paid. The card has not been charged yet.
  3. Capture the transaction—The second half of the credit card transaction. After authorization, you ship the product and then submit the charge for processing. This is called capturing the charge.
Create a token

First, create a token to keep CC info opaque from you, the developer. Become informed about handling credit card information.

Request
Operation: POST (from your browser) https://api.intuit.com/quickbooks/v4/payments/tokens
Content type: application/json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
   "card": {
      "expYear": "2017",
      "expMonth": "03",
      "address": {
         "region": "NJ",
         "postalCode": "07079",
         "streetAddress": "350 Mountain View Dr.",
         "country": "US",
         "city": "South Orange"
      },
      "name": "Pye's Cakes",
      "cvc": "123",
      "number": "4111111111111111"
    }
}
Response

1
2
3
{
   "value": "4ALvl3ZJZESJwjiQr6vQQCfDz74="
}
Create the authorization

Now create a charges authorization using the token created in the last section. Life time of a token is 15 minutes and is for one time use. This is the first half of a credit card transaction, with the charges.capture attribute set to false, and is used to get authorization that the merchandise will be paid by the card issuer.

Request
Operation: POST (from your server) https://api.intuit.com/quickbooks/v4/payments/charges
Content type: application/json

1
2
3
4
5
6
{
   "amount": "80.00",
   "currency": "USD",
   "capture": "false",
   "token": "4ALvl3ZJZESJwjiQr6vQQCfDz74="
}
Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
   "created": "2015-04-23T19:51:48Z",
   "status": "AUTHORIZED",
   "amount": "80.00",
   "currency": "USD",
   "token": "4ALvl3ZJZESJwjiQr6vQQCfDz74=",
   "capture": false,
   "id": "ECZG9D8YZ2WY",
   "authCode": "817677"
}
Capture the charge

At fulfillment time, you capture the charge.

Request
Operation: POST (from your server) https://api.intuit.com/quickbooks/v4/payments/charges/<id>/capture
where ``<id>`` is the id from the authorization response. For this example, ``<id>`` is ECZG9D8YZ2WY.
Content type: application/json

1
2
3
{
   amount: 80.00
}
Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
   "created": "2015-04-23T19:51:47Z",
   "status": "CAPTURED",
   "amount": "80.00",
   "currency": "USD",
   "card": {
     "number": "xxxxxxxxxxxx1111",
     "name": "Pye's Cakes",
     "address": {
        "city": "xxxxxxxxxxxx",
        "region": "xx",
        "postalCode": "xxxxx",
        "streetAddress": "xxxxxxxxxxxxxxxxxxxxx"
     },
     "expMonth": "03",
     "expYear": "2017"
   },
   "capture": false,
   "id": "ECZG9D8YZ2WY",
   "context": {
     "tax": null,
     "recurring": false,
     "deviceInfo": {}
   },
   "authCode": "817677",
   "captureDetail": {
     "created": "2015-04-23T19:53:43Z",
     "amount": "80.00",
     "context": {
        "tax": "0.00",
        "recurring": false,
        "deviceInfo": {}
     }
   }
}
Creating the sales receipt

After receiving and processing the credit card create response, create the sales receipt.

Best practice: use automatic reconciliation

When creating the sales receipt, set up the sale to be automatically reconciled with the QuickBooks company account register. After the transaction settles from merchant services, QuickBooks Online automatically creates a deposit in the merchant’s company file.

In order to take advantage of automatic reconciliation, set the following parameters in the salesreceipt create request:

Note

Note

Sandbox companies do not currently support automatic reconciliation. To get a true end-to-end experience you need to create a production QuickBooks Payments account and link it to your production QuickBooks company and issue QuickBooks Online API calls to the production endpoints. Examples below show production endpoint URLs, but request and response samples use sandbox objects

Request
Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmId>/salesreceipt
Content type: application/json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
   "Line": [{
      "Id": "1",
      "LineNum": 1,
      "Description": "Sprinkler Pipes",
      "Amount": 80.0,
      "DetailType": "SalesItemLineDetail",
      "SalesItemLineDetail": {
         "ItemRef": {
            "value": "17",
            "name": "Sprinkler Pipes"
         },
         "UnitPrice": 4,
         "Qty": 20
      }
   }],
   "CustomerRef": {
       "value": "15",
       "name": "Pye's Cakes"
      },
   "CreditCardPayment": {
      "CreditChargeInfo": {
          "ProcessPayment": "true"
      },
      "CreditChargeResponse": {
          "CCTransId": "EKFOR97XK9UD"
      }
   },
   "TxnSource": "IntuitPayment"
}
Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
   "SalesReceipt": {
      "domain": "QBO",
      "sparse": false,
      "Id": "192",
      "SyncToken": "0",
      "MetaData": {
        "CreateTime": "2015-04-15T12:59:52-07:00",
        "LastUpdatedTime": "2015-04-15T12:59:52-07:00"
      },
      "DocNumber": "1053",
      "TxnDate": "2015-04-15",
      "Line": [
        {
           "Id": "1",
           "LineNum": 1,
           "Description": "Sprinkler Pipes",
           "Amount": 80.0,
           "DetailType": "SalesItemLineDetail",
           "SalesItemLineDetail": {
             "ItemRef": {
                "value": "17",
                "name": "Sprinkler Pipes"
             },
             "UnitPrice": 4,
             "Qty": 20,
             "TaxCodeRef": {
                "value": "NON"
             }
           }
        },
        {
           "Amount": 80.0,
           "DetailType": "SubTotalLineDetail",
           "SubTotalLineDetail": {}
        }
      ],
      "TxnTaxDetail": {
        "TotalTax": 0
      },
      "CustomerRef": {
          "value": "15",
          "name": "Pye's Cakes"
           },
      "BillAddr": {
         "Id": "15",
         "Line1": "350 Mountain View Dr.",
         "City": "South Orange",
         "CountrySubDivisionCode": "NJ",
         "PostalCode": "07079",
         "Lat": "40.7633073",
         "Long": "-74.2426072"
      },
         "TxnSource": "IntuitPayment",
         "TotalAmt": 80.0,
         "ApplyTaxAfterDiscount": false,
         "PrintStatus": "NeedToPrint",
         "EmailStatus": "NotSet",
         "Balance": 0,
         "CreditCardPayment": {
           "CreditChargeInfo": {
              "ProcessPayment": true
         },
         "CreditChargeResponse": {
           "CCTransId": "EKFOR97XK9UD",
           "Status": "Completed",
           "CardSecurityCodeMatch": "NotAvailable",
           "AvsStreet": "Fail",
           "AvsZip": "Fail"
         }
      },
      "DepositToAccountRef": {
        "value": "4",
        "name": "Undeposited Funds"
      }
   },
   "time": "2015-04-15T12:59:53.035-07:00"
}
Error response

If you attempt to create this sales receipt without having enabled the Payments data source in your app, you receive the following error.

1
2
3
4
5
6
{
   "Fault" => {
      "Error" => [{
         "Message" => "Feature Not Supported Error", "Detail" => "Feature Not Supported Error : true", "code" => "5030", "element" => "ProcessPayment"
      }], "type" => "ValidationFault"
   }, "time" => "2015-04-17T12:53:32.542-07:00"
Depositing funds and reconciliation

After the credit card transaction settles, QuickBooks Payments deposits funds into the merchant’s checking account and withdraws the transaction fee. A deposit object and purchase object, respectively, are created on his behalf. You, the developer, do not create these objects. This has the effect of automatically reconciling the transaction in the QuickBooks company account register.

To determine if a deposit object has been created, query deposit objects and parse the response to locate the deposit whose Line.LinkedTxn.TxnId matches that of the subject salesreceipt object created in the last section.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
   "Deposit": [
      {
         "DepositToAccountRef": {
          "value": "35",
          "name": "Checking"
         },
         "TotalAmt": 80.0,
         "domain": "QBO",
         "sparse": false,
         "Id": "200",
         "SyncToken": "0",
         "MetaData": {
          "CreateTime": "2015-04-20T15:24:02-07:00",
          "LastUpdatedTime": "2015-04-20T15:24:02-07:00"
         },
         "TxnDate": "2015-04-20",
         "CurrencyRef": {
          "value": "USD",
          "name": "United States Dollar"
         },
         "PrivateNote": "System-recorded deposit for QuickBooks Payments",
         "Line": [
         {
            "Amount": 80,
            "LinkedTxn": [
               {
                  "TxnId": "192",
                  "TxnType": "SalesReceipt",
                  "TxnLineId": "0"
               }
            ]
         }
         ]
      }
   ],
   "time": "2015-04-20T15:25:28.184-07:00"
}
Transaction fees

A Purchase object is created on the merchant’s behalf to represent the corresponding fee paid to QuickBooks Payments for the transaction.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{
   "Purchase": {
     "AccountRef": {
        "value": "35",
        "name": "Checking"
     },
     "PaymentType": "Cash",
     "EntityRef": {
        "value": "135",
        "name": "QuickBooks Payments",
        "type": "Vendor"
     },
     "TotalAmt": 0.28,
     "PurchaseEx": {
        "any": [
           {
             "name": "{http://schema.intuit.com/finance/v3}NameValue",
             "declaredType": "com.intuit.schema.finance.v3.NameValue",
             "scope": "javax.xml.bind.JAXBElement$GlobalScope",
             "value": {
                "Name": "TxnType",
                "Value": "54"
             },
             "nil": false,
             "globalScope": true,
             "typeSubstituted": false
           }
        ]
     },
     "domain": "QBO",
     "sparse": false,
     "Id": "958",
     "SyncToken": "0",
     "MetaData": {
         "CreateTime": "2015-04-20T15:24:02-07:00",
         "LastUpdatedTime": "2015-04-20T15:24:02-07:00"
     },
     "CustomField": [],
     "TxnDate": "2015-04-20",
     "CurrencyRef": {
        "value": "USD",
        "name": "United States Dollar"
     },
     "PrivateNote": "System-recorded fee for QuickBooks Payments. Fee-name: DiscountRateFee, fee-type: Daily.",
     "Line": [
        {
           "Id": "1",
           "Description": "System-recorded fee for QuickBooks Payments. Fee-name: DiscountRateFee, fee-type: Daily.",
           "Amount": 0.28,
           "DetailType": "AccountBasedExpenseLineDetail",
           "AccountBasedExpenseLineDetail": {
            "AccountRef": {
               "value": "79",
               "name": "Bank Service Charges"
            },
            "BillableStatus": "NotBillable",
            "TaxCodeRef": {
                "value": "NON"
            }
           }
        }
     ]
   },
   "time": "2015-04-20T13:15:47.19-07:00"
}
Creating a refund

There are two parts to refunding a transaction:

  1. Issue a refund request to QuickBooks Payments to reverse the credit card charge and to give the customer his funds.
  2. Create a QuickBooks refundrequest object so that the QuickBooks company file can reconcile the refund once settled with Payments.
qbpayments/docs/workflows/Merchant_Refund_Processing.png
Create the credit card refund
Request
Operation: POST (from your server) https://api.intuit.com/quickbooks/v4/payments/charges/{id}/refunds
Content type: application/json

1
2
3
{
   "amount": 80.00
}
Response

Note the id that is returned in this response. You use it in the subsequent request to create a refund receipt.

1
2
3
4
5
{
   "id": "EKFOR97XK9UD",
   "amount": "80.00",
   "created": "2020-09-23T01:49:12Z"
}
Create a refundreceipt

Now, create the refund receipt request. In order to take advantage of automatic reconciliation later when the payment refund transaction settles from merchant services, set the following parameters in the request:

In addition,

Request
Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmId>/refundreceipt
Content type: application/json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
   "Line": [{
      "Id": "1",
      "LineNum": 1,
      "Description": "Sprinkler Pipes",
      "Amount": 80.0,
      "DetailType": "SalesItemLineDetail",
      "SalesItemLineDetail": {
         "ItemRef": {
            "value": "17",
            "name": "Sprinkler Pipes"
         },
         "UnitPrice": 4,
         "Qty": 20
      }
   }],
   "CustomerRef": {
      "value": "15",
      "name": "Pye's Cakes"
   },
   "CreditCardPayment": {
      "CreditChargeInfo": {
         "ProcessPayment": "true"
      },
      "CreditChargeResponse": {
         "CCTransId": "EKFOR97XK9UD"
      }
   },
   "TxnSource": "IntuitPayment",
   "DepositToAccountRef": {
      "value": "40",
      "name": "Checking"
   }
}
Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{
   "RefundReceipt": {
     "domain": "QBO",
     "sparse": false,
     "Id": "930",
     "SyncToken": "0",
     "MetaData": {
        "CreateTime": "2014-04-25T09:40:43-07:00",
        "LastUpdatedTime": "2014-04-25T09:40:43-07:00"
     },
     "CustomField": [
        {
           "Name": "P.O. Number",
           "Type": "StringType"
        },
        {
           "Name": "Sales Rep",
           "Type": "StringType"
        }
     ],
     "DocNumber": "10033",
     "TxnDate": "2014-04-25",
     "DepartmentRef": {
        "value": "1",
        "name": "Garden Services"
     },
     "Line": [
        {
           "Id": "1",
           "LineNum": 1,
           "Amount": 420,
           "DetailType": "SalesItemLineDetail",
           "SalesItemLineDetail": {
             "ItemRef": {
                "value": "33",
                "name": "Concrete"
             },
             "TaxCodeRef": {
                "value": "NON"
             }
           }
        },
        {
           "Amount": 420,
           "DetailType": "SubTotalLineDetail",
           "SubTotalLineDetail": {}
        }
     ],
     "TxnTaxDetail": {
        "TotalTax": 0
     },
     "TotalAmt": 420,
     "ApplyTaxAfterDiscount": false,
     "PrintStatus": "NeedToPrint",
     "Balance": 0,
     "PaymentRefNum": "To Print",
     "DepositToAccountRef": {
        "value": "40",
        "name": "Checking"
     }
   },
   "time": "2014-04-25T09:40:43.687-07:00"
}
Inventory management

QuickBooks Online can manage product inventory. Line items entered on sales, purchase, and refund transactions flow into inventory items to automatically adjust quantity on hand. Additionally, cost and price of individual inventory items are stored so the merchant can track inventory value.

Enable inventory management for the QuickBooks company via Preferences.ProductAndServicesPrefs. By default, it is not enabled. Set these flags to true:

After enabling inventory management, add individual inventory items as Item objects.

Note

Note

Enabling inventory management requires certain preferences to be enabled. Make sure your app provides a user experience around enabling inventory management such that the merchant can make an informed decision whether to do so. An app should never modify preferences without the merchant’s knowledge and agreement.

What is supported
What’s not supported
Creating inventory items

Create an Item object for each inventory item that is tracked. Take care when using categories to define your products—they can add complexity when parsing out the inventory item of interest.

Request
Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmId>/item
Content type: application/json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
   "Name": "Office Supplies",
   "Description": "This is the sales description.",
   "Active": true,
   "Taxable": true,
   "UnitPrice": 25,
   "Type": "Inventory",
   "IncomeAccountRef": {
     "value": "79",
     "name": "Sales of Product Income"
   },
   "PurchaseDesc": "This is the purchasing description.",
   "PurchaseCost": 35,
   "ExpenseAccountRef": {
     "value": "80",
     "name": "Cost of Goods Sold"
   },
   "AssetAccountRef": {
     "value": "81",
     "name": "Inventory Asset"
   },
   "TrackQtyOnHand": true,
   "QtyOnHand": 10,
   "InvStartDate": "2013-02-19"
}
Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
   "Item": {
     "Name": "Office Supplies",
     "Description": "This is the sales description.",
     "Active": true,
     "FullyQualifiedName": "Office Supplies",
     "Taxable": true,
     "UnitPrice": 25,
     "Type": "Inventory",
     "IncomeAccountRef": {
        "value": "79",
        "name": "Sales of Product Income"
     },
     "PurchaseDesc": "This is the purchasing description.",
     "PurchaseCost": 35,
     "ExpenseAccountRef": {
        "value": "80",
        "name": "Cost of Goods Sold"
     },
     "AssetAccountRef": {
        "value": "81",
        "name": "Inventory Asset"
     },
     "TrackQtyOnHand": true,
     "QtyOnHand": 10,
     "InvStartDate": "2013-02-19",
     "domain": "QBO",
     "sparse": false,
     "Id": "36",
     "SyncToken": "0",
     "MetaData": {
        "CreateTime": "2015-04-17T15:21:09-07:00",
        "LastUpdatedTime": "2015-04-17T15:21:10-07:00"
     }
   },
   "time": "2015-04-17T15:21:09.688-07:00"
}
Customer management

Your app needs to provide options to allow merchants to manage and track their customers.

Having a customer reference attached to each sales receipt enables the merchant to accurately track customer activity.