Develop with GraphQL

GraphQL is an API query language that simplifies client-side requests. Apps can do a lot of work with just a single query, such as query multiple resources and entities, request data in a specific format, or get the server to perform several operations.

“At its simplest, GraphQL is about asking for specific fields on objects.” - from GraphQL.org

All queries go to a single endpoint on the server. The server parses queries and returns only the requested data in the requested format.

Visit GraphQL.org for a deeper dive. Check out courses from edx.org.

Create queries to request data

In GraphQL, queries can fetch data for single or multiple fields, apply filters, and get conditional data. If you’re familiar with the REST API, this is very similar to the GET operation. However, queries in GraphQL are always POST operations.

GraphQL queries are very efficient. When apps send requests with queries, the server only returns the requested data. The response will be the same shape and format as the query.

Server responses are clean, specific, and easy to work with. This also boosts app performance. Servers don’t slow down to fetch unusable or extraneous data.

How to create queries

For the QuickBooks Payroll API, use queries to get data for accounts, transactions, and other resources. Specify the exact fields you want the server to return in the query body.

Here’s a simple query to get company information:

1
2
3
4
5
6
7
8
9
          query RequestEmployerInfo {
                  payrollEmployerInfo {
                     businessInfo {
                         name {
                             legalName
                          }
                          }
                  }
          }

The server returns values for the legalName field.

Learn more about queries from GraphQL.org.

Use mutations to modify data

Mutations are what apps use to perform operations to change, update, or delete data on the server.

In GraphQL, you can use mutations to modify multiple fields with a single request. If you’re familiar with the REST API, mutations are similar to the POST, PUT, and DELETE operations.

While it’s possible to create and update data with queries in GraphQL, it’s best practice to use mutations to change or update data. And unlike queries, mutations run in series instead of in parallel.

How to use mutations

For the QuickBooks Payroll API, you’ll use mutations often for things like transactions and invoices.

Here’s a simple mutation to create an employer deduction:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
          mutation {
            createEmployerDeduction (
              deduction: {
                name: "My plan deduction"
                statutoryDeductionPolicy: "Annual max is 10k"
              }
            ) {
              id
              name
            }
          }

Mutations typically take input data and define fields based on the response the server returns.

In this example, the mutation took the deduction argument and let the server define the id and name fields based on the response.

Create fragments for sets of fields

Fragments are reusable sets of fields you can use across queries.

In GraphQL, you can define and group sets of fields into fragments. Instead of repeating individual fields, simply call the fragment to utilize all the fields and related data at once.

This lets you organize code into modular, bite-sized “chunks.”

How to create and use fragments

For the QuickBooks Payroll API, fragments are useful for queries that constantly reuse the same sets of fields.

Here’s an example of defining a fragment and using it in a query:

1
2
3
4
5
6
7
          query
            queryName {
              fieldName1
              fieldName2 {
                ...fragmentName
              }
            }

We put fragmentName in fieldName2.

Now define the fragment and corresponding set of fields:

1
2
3
4
5
6
          fragment
            fragmentName on FieldName {
              field1
              field2
              field3
            }

Now, instead of entering each individual field, you can just use fragmentName.

Use pagination to fetch subsets of data

Pagination lets you quickly search and request subsets of data within larger datasets.

In GraphQL, you can use the pageInfo object and cursor-based pagination (endCursor and startCursor) to set criteria or collect data after a certain point in the response. This typically yields smaller payloads and faster server responses.

For more about GraphQL pagination, see GraphQL Cursor Connections Specification.

Implement pagination

When querying a group of records, we recommend implementing pagination to avoid timeout errors. We suggest requesting 10 records at a time. The general format for pagination is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
          query queryName {
            fieldName1
            fieldName2(pagination: {first: numOfRecords, after: cursorValue}) {
             pageInfo {
                hasNextPage
                startCursor
                endCursor
                hasPreviousPage
              }
              field1
              field2
            }
          }

In this example, numOfRecords is the number of records you want returned by the query. The field cursorValue is the pointer to the first element that the count should begin from. numRecords is an Integer field and cursorValue is a String field.

Let’s take an example where there are 20 employees in the system and you want to read 5 at a time. The first time you send a request, set your cursorValue to null. Your query will look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
          query readAllEmployeePayslips {
                  company {
                          employees(
                                  pagination: { first: 5, after: null }
                          ) {
                                  pageInfo {
                                          hasNextPage
                                          startCursor
                                          endCursor
                                          hasPreviousPage
                                  }
                                  nodes {
                                          firstName
                                  }
                          }
                  }
          }

The response will return records 1 - 5:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
          {
            "data": {
              "company": {
                     "employees": {
                            "pageInfo": {
                                    "hasNextPage": true,
                                    "startCursor": "0",
                                    "endCursor": "4",
                                    "hasPreviousPage": false
                            },
                            "nodes": [
                               <5 employee nodes with data>
                            ]
                      }
                    }
             }
          }

From this response, if hasNextPage = true, get the value of endCursor and in your next query to read records 6 - 10, increment and pass this value as the cursorValue. So your next query will look like this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
          query readAllEmployeePayslips {
            company {
                  employees(
                    pagination: { first: 5, after: "5" }
                  ) {
                          pageInfo {
                            hasNextPage
                            startCursor
                            endCursor
                            hasPreviousPage
                          }
                          nodes {
                            firstName
                          }
                    }
             }
          }

This will return records 6 - 10. You continue to do this as long as there are more records to be read. The field hasNextPage in the response is an indicator of whether there are more records left to be read or not. Once the last set of records are reached, the value of hasNextPage will be false.

Adopt the QuickBooks Payroll API best practices

GraphQL is a powerful and efficient API language. Here are a few ways you can structure and craft your code to build world-class apps.

GraphQL best practices

Only query for the data your app needs In GraphQL, less is more. Create queries that only request the specific fields and data required for your QuickBooks integration to be fully functional. You can change queries later and add more fields as needed.

Log frequently during development Take the time to properly log your app development process. It saves time in the long-run. Logging every execution may impact app performance, so prioritize what matters most.

Tip: Always log the value of the intuit_tid field in the server response. It will help our support team quickly find and address any reported issues.

Use aliases to query the same field with different arguments Aliases let you rename the results of identical object fields so you can query the same field for different arguments. You can pass multiple queries at once and get responses for both fields without conflict.

Always include operation names to avoid confusion Consciously use operation names to make your code crystal clear, concrete, and unambiguous.

Create fragments to speed up code writing Instead of querying frequently used fields individually, create and reuse fragments whenever possible. This makes code modular and easier to scale.

Pagination lets you quickly navigate large datasets. If you expect a query to return lots of data, use pagination to fetch specific subsets.

QuickBooks Payroll API best practices

Learn about API throttling For information about throttling, see API call limits and throttles.

Single endpoints Let’s say you want to build an invoicing app. It needs to constantly request data for a specific set of invoices. The invoices contain particular items for a specific date range. And, the app needs current business addresses for each customer.

With the REST API, you’d need to make several queries to different endpoints: one for the invoice, one for each customer, and one for each item.

GraphQL only requires a single query, sent to a single endpoint.

Get only the data you need GraphQL queries are highly customizable. You specify the exact fields and values you want the server to return. Apps only get the data you query for–there’s no over-fetching or under-fetching.

Develop with any language GraphQL is language-independent. You can use it with any backend framework or programming language implementation.

Simple data hierarchies GraphQL requests and responses are structured the same way. It naturally follows relationships between attributes.