REST vs GraphQL

If you’re familiar with our QuickBooks Online Accounting API (referred to as Accounting API for the remainder of this section), you may be used to the REST framework. On this page, we’ll go over some general differences between REST and GraphQL, and some differences between the Accounting API and the GraphQL API.

HTTP request type

Using REST, you would do a GET request to retrieve data from the server and a POST, PATCH, PUT or DELETE to modify data on the server.

With GraphQL, all requests are POST requests and the body of the request tells the server what needs to be done. All of the HTTP calls are made the same way and to the same resource but with different request bodies. To retrieve data, you would use a query operation, and to modify data you would use a mutation operation.

Single resource vs multiple resources

Let’s say you wanted to read an invoice and find out how that invoice was paid. In REST, these would typically be separate endpoints or entities called Invoice and Payment, which is what the Accounting API does. You would have to make one call to the Invoice endpoint to get the invoice information. You would then find the related Payment ID and then make another call to Payment endpoint to find out more information about the payment transaction.

If you were to do this in GraphQL, you would be dealing with a single resource. Depending on the schema, you would make a call to one resource and ask for the Invoice fields you need and the fields on the related Payment.

Fetching data

The Accounting API would return all the information it has about an entity that is queried. A simple read or query operation would return all the fields associated with the entity for the record that has been requested.

The GraphQL API gives you more control over what data you want from the server. Whether you are doing a query or a mutation, you can specify exactly which fields (and nested fields) you want from the server.

Identifiers

In the Accounting API, when you query for records, each record comes with an ID, which is unique only within that entity. So you may have an Invoice with ID 123 and a Payment with ID 123.

The GraphQL API has global IDs. Each entity returned in response has an ID that is unique across all entities.

Error response

The Accounting API returns HTTP status codes like 4** or 5** to indicate different types of errors.

The GraphQL API handles errors differently. Errors related to the API gateway later will return status codes 4** or 5**, but API errors will return HTTP status code 200 and provide all of the necessary information within the response body.

Operations

Let’s take a deeper dive into common operations: create, read, update, delete, and query. We’ll take the example of the Accounting API’s Invoice entity for this section. An Invoice represents a sales form where the customer pays for a product or service later. It is associated with Items, Customers, and Payments. Although Invoice is not supported in the GraphQL API, we’ll do a comparison between how we work with this entity in the Accounting API vs how we would hypothetically do this in the GraphQL API.

In all of the snippets below you will see that in the Accounting API (REST), the response will be the object with all of the fields. With the GraphQL API, however, you can specify which fields you want and only those fields are a part of the response.

Note

Note: The purpose of the following examples is to illustrate the differences between REST and GraphQL. The Intuit GraphQL API does not provide invoice requests.

Create an invoice

This section shows how you can create an invoice using REST and GraphQL.

REST

Request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  POST <baseUrl>/v3/company/<realmID>/invoice

  {
    "Line": [
      {
        "DetailType": "SalesItemLineDetail",
        "Amount": 100.0,
        "SalesItemLineDetail": {
          "ItemRef": {
            "name": "Services",
            "value": "1"
          }
        }
      }
    ],
    "CustomerRef": {
      "value": "1"
    }
  }

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
  {
    "Invoice": {
      "Id": "238",
      "DocNumber": "1069",
      "Balance": 100.0,
      "TxnDate": "2020-07-24",
      "TotalAmt": 100.0,
      "CustomerRef": {
        "name": "Amy's Bird Sanctuary",
        "value": "1"
      },
      "ShipAddr": {
        "City": "Bayshore",
        "Line1": "4581 Finch St.",
        "PostalCode": "94326",
        "CountrySubDivisionCode": "CA",
        "Id": "109"
      },
      "DueDate": "2020-08-23",
      "Line": [
        {
          "Amount": 100.0,
          "SalesItemLineDetail": {
            "TaxCodeRef": {
              "value": "NON"
            },
            "ItemRef": {
              "name": "Services",
              "value": "1"
            }
          },
          "DetailType": "SalesItemLineDetail"
        }
      ],
          ... other fields ...
  }
GraphQL

Request

1
2
3
4
5
6
7
8
  POST <graphBaseURL>/v1

  mutation Create{
    createInvoice(item: {type: "inventory", amount: 100, itemref: "111"}, customerRef: "222", paymentRef: "333") {
      id
      docNumber
    }
  }

Response

1
2
3
4
  {
          "id": 1,
          "docNumber": "101"
  }
Read an invoice

This section shows how to read an invoice and get the payment type of the linked payment using REST or GraphQL.

REST

Request Example 1

1
  GET /v3/company/<realmID>/invoice/101

Response Example 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  {
          "Invoice": {
                  "Id": "101",
                  "DocNumber": "1069",
                  "LinkedTxn": {
                          "TxnType": "Payment",
                          "TxnId": "801"
                  }
          ... other fields ...
  }

Request Example 2

1
  GET /v3/company/<realmID>/payment/801

Response Example 2

1
2
3
4
5
6
  {
          "Payment": {
                  "Id": "801",
                  "PaymentType": "CreditCard",
          ... other fields ...
  }
GraphQL

Request

1
2
3
4
5
6
7
8
9
  POST <graphBaseURL>/v1

  query getPaymentInfo  {
          invoices (id : 1) {
                  docNumber
                  payments {
                          paymentType
      }
  }

Response

1
2
3
4
5
6
  {
          docNumber: "101",
          payments{
                  paymentType: "Credit Card"
          }
  }
Update an invoice

This section shows how to update an existing invoice with REST or GraphQL.

REST

Request

1
2
3
4
5
6
7
8
  POST <baseUrl>/v3/company/<realmID>/invoice

  {
    "SyncToken": "0",
    "Id": "101",
    "sparse": true,
    "DueDate": "2020-09-30"
  }

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  {
    "Invoice": {
      "Id": "101",
      "SyncToken": "1",
      "DocNumber": "1069",
      "DueDate": "2020-09-30",
      "Line": [
        {
  ... other fields ...
        }
      ],
          ... other fields ...
  }
GraphQL

Request

1
2
3
4
5
6
7
8
  POST <graphBaseURL>/v1

  mutation Update($id: ID!) {
    updateInvoice(id: $id, dueDate: "2020-09-30") {
      id
      dueDate
    }
  }

Response

1
2
3
4
  {
      id: 1,
      dueDate: "2020-09-30"
  }
Delete an invoice

Delete an invoice using REST or GraphQL.

REST

Request

1
2
3
4
5
6
  POST <baseUrl>/v3/company/<realmID>/invoice?operation=delete

  {
    "Id": "239",
    "SyncToken":"3"
  }

Response

1
2
3
4
5
6
7
  {
   "Invoice": {
    "domain": "QBO",
    "status": "Deleted",
    "Id": "239"
    }
  }
GraphQL

Request

1
2
3
4
5
6
7
  POST <graphBaseURL>/v1

      mutation Delete($id: ID!) {
        deleteInvoice(id: $id) {
          status
        }
      }

Response

1
2
3
  {
      status: "void"
  }
Query an invoice

A common operation is to query invoices based on certain filters. Let’s say we want to get all invoices created within a date range.

REST

Request

1
  GET <baseUrl>/v3/company/<realmID>/query?query=select * from Invoice where TxnDate>'2020-01-18' and TxnDate<'2020-01-18'

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  {
          "QueryResponse": {
                  "Invoice": [
                          {
                                  "Id": "201",
                                  ... other fields ...
                          },
                          {
                                  "Id": "202",
                                  ... other fields ...
                          },
                          ... more records ...
          ]
          }
  }
GraphQL

Request

1
2
3
4
5
6
7
  query getInvoices() {
    invoice(filter: {txnDate: {between: ['2020-01-18' , '2020-01-18' ]}}) {
      id
      status
      balance
    }
  }

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  {
          "data": {
                  "invoice": [
                          {
                                  "id": "101",
                                  "status": "Paid",
                                  "balance": 0
                          },
                          {
                          ... more records ...
                  },
                  ... more records ...
          ]
          }
  }