Guided Tour: REST API

Background

QBO's RESTful API allows developers to leverage QBO functionality without relying on our user interface. Our API can be called from:
  • Java, ASP.NET or any other server-side language using simple HTTP requests.
  • Javascript, using standard AJAX request
  • The QBO javascript library
We'll start with a use case: managing an insurance claim for a customer.

Create a customer.

The QBO Contact table represent names and addresses. Customers are a perfect fit for the Contact table. Thus, we'll create a Contact to represent our customer.

Request:

Contact/Contact.ashx/Save?FirstName=John&LastName=Doe&Address=123%20Main%20Street&City=Anywhere&State=NY&PostalCode=12001&Output=Json

Response:

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
X-Execution-Time: 33
Date: Fri, 06 Feb 2015 19:01:45 GMT
Content-Length: 207

{
    "Methods": [],
    "Licenses": [],
    "ContactID": 49781,
    "Contact": "Doe, John",
    "FirstName": "John",
    "LastName": "Doe",
    "Address": "123 Main Street",
    "City": "Anywhere",
    "State": "NY",
    "PostalCode": "12001"
}

Notes:
  • The request includes Contact.ashx/Save. Generically, this follows a {ClassName}/{Operation} pattern which we'll refer to repeatedly.
  • In the request, we've included &Output=Json, because we like working with JSON. You could choose &Output=Xml, or JsonP, or Csv if you prefer.
  • We've use a GET here for brevity; you are welcome to use a POST instead
  • The response includes a ContactID; this is the primary key of the contact created
  • From here on out, we'll ignore the top of the HTTP response for brevity

Updated a Customer

Request:

Contact/Contact.ashx/Save?ContactID=49781&Phone=800.555.1212&Email=jdoe@example.com&Output=Json

Response:

{
    "Methods": [
        {
            "ContactMethodID": 25672,
            "ContactMethod": "Email",
            "ContactID": 49781,
            "MethodType": "Email",
            "ContactValue": "jdoe@example.com",
            "PrimaryMethod": true
        },
        {
            "ContactMethodID": 25671,
            "ContactMethod": "Phone",
            "ContactID": 49781,
            "MethodType": "Phone",
            "ContactValue": "800.555.1212",
            "PrimaryMethod": true
        }
    ],
    "Licenses": [],
    "ContactID": 49781
}

Notes:
  • We just wanted to update the contact with a phone number
  • Methods represent all methods of communicating with a contact; here we see email and phone listed

Create an Insurance Claim

An insurance claim can be a complicated creature, especially if it winds up being disputed. If we were living in a paper world, we'd probably put each insurance claim in a manilla folder, label the outside with the customer's name and the date the claim was filed, and then stick all related paperwork into said folder.  The QBO Process table is a good fit for such a construct.

Request:

Process/Process.ashx/Save?Object=Contact&ObjectID=49781&Process=Insurance%20Claim&DateOpened=2/1/2015&Output=Json

Response:

{
    "Delays": [],
    "ProcessID": 3396,
    "Process": "Insurance Claim",
    "DateOpened": "2015-02-01T00:00:00",
    "Object": "Contact",
    "ObjectID": 49781
}

Notes:
  • A Process can be bound to any object using the QBO Object/ObjectID pattern.  
    • In this case, we're setting the Process.Object = 'Contact', and Process.ObjectID = 49781 (the primary key for our customer created above).
  • The primary key for the newly created Process in this example is 3396

View all Information Related to an Insurance Claim

The Select statement will retrieve basic information about an object, while Summary will retrieve an object and is ancestors and descendants.

Select Request:

Process/Process.ashx/Select?ID=3396&Output=Json

Select Response:

{
    "Delays": [],
    "ProcessID": 3396,
    "Process": "Insurance Claim",
    "DateOpened": "2015-02-01T00:00:00",
    "Object": "Contact",
    "ObjectID": 49781
}

Summary Request:

Process/Process.ashx/Summary?ID=3396&Output=Json

Summary Response:

{
    "Root": {
        "ContactItem": {
            "ContactID": "49781",
            "Contact": "Doe, John",
            "FirstName": "John",
            "LastName": "Doe",
            "Address": "123 Main Street",
            "City": "Anywhere",
            "State": "NY",
            "PostalCode": "12001",
            "CreatedPersonID": "374",
            "CreatedDate": "2015-02-06T14:30:24.773",
            "UpdatedPersonID": "374",
            "UpdatedDate": "2015-02-06T14:30:24.773",
            "Phone": "800.555.1212",
            "Email": "jdoe@example.com"
        },
        "ProcessItem": {
            "ProcessID": "3396",
            "Process": "Insurance Claim",
            "DateOpened": "2015-02-01T00:00:00",
            "Object": "Contact",
            "ObjectID": "49781",
            "CreatedPersonID": "374",
            "CreatedDate": "2015-02-06T14:45:47.400",
            "UpdatedPersonID": "374",
            "UpdatedDate": "2015-02-06T14:45:47.400",
            "CreatedPerson": "epatrick@quandis.com",
            "UpdatedPerson": "epatrick@quandis.com",
            "ParentLabel": "Doe, John"
        }
    }
}

Add a Message

Messages are the yellow stickies on the manila folder that is our process.

Request:

Message/Message.ashx/Save?Process&ObjectID=3396&Subject=Customer is now healthy&BodyText=Doc says they'll be fine&Output=Json

Response:

{
    "Object": "Process",
    "ObjectID": 3396,
    "ActiveRecipients": [],
    "BccAddress": "",
    "CcAddress": "",
    "DateAdded": "/Date(1423493949801-0500)/",
    "From": null,
    "Message": "Customer is now healthy",
    "MessageID": 54358,
    "Recipients": [],
    "ReplyToAddress": "",
    "ToAddress": "",
    "BodyText": "Doc says they'll be fine"
}

Send an Email

Sending an email is the same as adding a message, except we call Message/Send instead of Message/Save.

Request:

Message/Message.ashx/Send?Object=Process&ObjectID=3396&ToAddress=jdoe@example.com&Subject=Insurance Claim 3966&BodyHTML=<b>Glad you're better!</b>&Output=Json

Response:

{
    "Recipients": [
        {
            "MessageRecipient": "jdoe@example.com",
            "ReadGUID": "00000000-0000-0000-0000-000000000000",
            "Category": 0
        }
    ],
    "ActiveRecipients": [
        {
            "MessageRecipient": "jdoe@example.com",
            "ReadGUID": "00000000-0000-0000-0000-000000000000",
            "Category": 0
        }
    ],
    "ToAddress": "jdoe@example.com",
    "CcAddress": "",
    "BccAddress": "",
    "ReplyToAddress": "",
    "Message": "Insurance Claim 3966",
    "DateAdded": "2015-02-09T10:22:08.9939687-05:00",
    "BodyHTML": "<b>Glad you're better!</b>",
    "Object": "Process",
    "ObjectID": 3396
}

Notes:
  • You can call Message/SaveEmail to both save and email a message (nice audit trail)
  • In this example, we used BodyHTML instead of BodyText. Pretty much everyone can read HTML email these days.

Add a Task

Let's schedule a task to verify the insurance claim with the doctor.

Request:

Decision/ImportForm.ashx/Save?Object=Process&ObjectID=3396&ImportForm=Verify Claim&ProjectedCompletion=2/2/2015&Provider=Ira Hurtin&Procedure=Hernia Operation&Phone=800.555.2323

Response:

{
    "MaximumDate": "2015-02-16T10:27:20.753",
    "ImportFormID": 4497,
    "ImportForm": "Verify Claim",
    "ProjectedCompletion": "2015-02-02T00:00:00",
    "XmlData": {
        "ImportFormXml": {
            "Provider": "Ira Hurtin",
            "Procedure": "Hernia Operation",
            "Phone": "800.555.2323"
        }
    },
    "ProjectedOriginal": "2015-02-02T00:00:00",
    "Object": "Process",
    "ObjectID": 3396
}

Notes:
  • Our "task" module is called "ImportForm"
  • Tasks track ad-hoc data in an XmlData field: in this case, Provider, Procedure, and Phone. Create fields on the fly!

Get a List of Pending Tasks

Request

Decision/ImportForm.ashx/Search?ActualCompletion=&Output=Json

Response

{
    "ImportFormCollection": {
        "ImportFormItem": [
            {
                "ImportFormID": "4497",
                "ImportForm": "Verify Claim",
                "ProjectedCompletion": "2/2/2015 12:00:00 AM",
                "XmlData": {
                    "ImportFormXml": {
                        "Provider": "Ira Hurtin",
                        "Procedure": "Hernia Operation",
                        "Phone": "800.555.2323"
                    }
                },
                "ProjectedOriginal": "2/2/2015 12:00:00 AM",
                "Object": "Process",
                "ObjectID": "3396",
                "CreatedPersonID": "374",
                "CreatedDate": "2/9/2015 10:27:20 AM",
                "UpdatedPersonID": "374",
                "UpdatedDate": "2/9/2015 12:03:29 PM",
                "CreatedPerson": "epatrick@quandis.com",
                "UpdatedPerson": "epatrick@quandis.com",
                "RecordCount": "1"
            }
        ]
    }
}

Notes:
  • When calling {ClassName}/Search, the JSON returned follows a pattern of {ClassName}Collection.{ClassName}Item
  • The search parameters are very flexible
// Show just tasks associated with our specific claim
Decision/ImportForm.ashx/Search?ActualCompletion=&Object=Process&ObjectID=3396Output=Json

// Show just 'Verify Claim' tasks
Decision/ImportForm.ashx/Search?ActualCompletion=&ImportForm=Verify Claim&Output=Json

// Show tasks due this week; note the use of a range operation -=
Decision/ImportForm.ashx/Search?ActualCompletion=&ProjectedCompletion-=2/1/2015,2/8/2015&Output=Json

Upload a Document

Request

POST {server}Attachment/Attachment.ashx/UploadChunk?Object=Process&ObjectID=3396&FileName=Sample.txt HTTP/1.1
...
Content-Length: 77

Hello World!

This is a simple text file, but QBO handles binary files too.

Response

{
    "name": "Sample.txt",
    "size": "77",
    "error": 0,
    "finish": true,
    "upload_name": "8f0ab4f9-7a5f-4113-8b96-b11da79fe8c5",
    "AttachmentItem": {
        "Object": "Process",
        "ObjectID": 3396,
        "Attachment": "Sample.txt",
        "AttachmentID": 6251,
        "Compression": false,
        "FileName": "Sample.txt",
        "FileObjectAssembly": "Amazon S3",
        "Length": 77,
        "LengthCompressed": 77,
        "PathURL": "/Process/3396/Sample.txt"
    }
}

Notes:
  • The QBO Attachment module handles documents
  • Attachment/UploadChunk supports, er, chunked upload (nice integration with the HTML5 spec)
  • The response JSON root contains properties representing the status of a chunk
  • The response JSON's AttachmentItem.AttachmentID is the unique ID of the recently uploaded document

Download a Document






Contact

Properties:
  • FirstName
  • MiddleName
  • LastName
  • Address
  • City
  • State
  • PostalCode
  • Prefix
  • Suffix
  • Company
  • Title
  • USSSN
  • BirthDate
  • DeathDate
  • Latitude
  • Longitude
Methods:
  • Save
  • Select
  • Summary
  • Geocode
  • Normalize