Square GraphQL Basics

Learn about the concepts, practices, and patterns you should be familiar with when working with Square GraphQL.

Link to section

Schema

A schema describes the objects and fields you can query for in the data model (graph), as well as the entry points, arguments, hierarchical relationships, and type information that determine valid query syntax. The following are some related concepts and terminology:

  • Fields - A property or attribute, such as phoneNumber or birthday. Each graph has one or more top-level fields that act as an entry point for graph data, such as merchants for the Merchants graph or inventoryChanges and inventoryCounts for the Inventory graph.
  • Objects - A collection of fields. The data type of a field can be a scalar, complex type, or enum, as a single value or an array. For example, the Customer.phoneNumber field is a String type and the Customer.address field is an Address type.
  • Enums - Defines a set of valid values for fields of the given enum type. For example, the Currency enum defines all possible values for the Money.currency field.
  • Interfaces - Defines fields that must be included in objects that implement the interface. For example, CatalogItem and CatalogCategory implement the CatalogObject interface, so both objects include all CatalogObject fields. The Catalog sample query in GraphQL Explorer shows how to use inline fragments to request fields based on different implementations.
  • Non-Null - An exclamation mark (!) appended to the data type of a field, which indicates that the value of the field must not be null when returned or when provided as an argument.

You can browse the schema in the Documentation Explorer pane in GraphQL Explorer.

Link to section

Queries

A query operation retrieves specified data. Queries are enclosed in curly braces ({ }). Lines that begin with a # character are treated as comments and ignored. For example, a simple query might use the following format:

# A simple query format where `field` is a graph entry point { field(arg: "value") { subfield } }

Every query contains at least one graph entry point and specifies the fields to return. Most graph entry points accept query arguments used to filter and sort the query or to navigate through paged responses. You can check the schema for valid query syntax.

The following example query requests the status and mainLocation fields for a given merchant:

Note

For graphs that follow the GraphQL Cursor Connection Specification (such as Payments and Refunds), you specify a top-level edges list of node objects in your query instead of the top-level nodes. You can check the schema to find the valid syntax for each entry point.

Because mainLocation is a complex type, you must also specify the Location subfields that you want to retrieve. If successful, the query returns results similar to the following:

GraphQL requests can contain multiple queries against different entry points. For example, the following query gets information about the merchant and a list of customers in the same request:

Link to section

Query responses

Responses can contain a data object, an extensions object, and an errors list. GraphQL responses don't return numeric response codes.

The data object in a response contains the query results.

{ "data": { # query results } }

If any errors are encountered while processing the query, Square returns an errors list.

{ "errors": [ { # error details } ] }

If the query partially succeeds, a response can contain both data with partial query results and errors.

{ "errors": [ { # error details } ], "data": { # query results } }

If you request the query's complexity score by including the x-graphql-include-debug header in the query, the response contains a top-level extensions field with debug information. Currently, only the requestId and complexityScore fields are returned.

{ "data": { # query results }, "extensions": { # debug fields } }
Link to section

Query components

The following sections describe features, syntax, and patterns you can use in your queries:

Note

Square also supports other GraphQL features, such as using aliases to rename fields in the response and the @skip and @include directives to conditionally return fields. For more information, see Introduction to GraphQL at Graphql.org.

You can specify the query operation type and an operation (or query) name. This syntax is required when sending multiple queries in a single request and recommended in general because naming your queries can help with reuse, debugging, and logging.

The following example query includes the query operation type and StatusAndCapabilities operation name:

You can filter a query to conditionally retrieve data based on specified criteria. All graph entry points (except currentMerchant) accept a filter query argument. Each entry point exposes a top-level input type that defines valid filtering criteria.

For example, the following cardsOnFile query uses the customerId, includeDisabled, and merchantId filter fields (defined in the CardOnFileFilter input type) to a customer's cards on file that are enabled for payments:

Note

Many Square GraphQL filters are equivalent to filters used for list and search endpoints in Square APIs.

Link to section

Required merchant ID filter

All graph entry points (except currentMerchant) require a merchant ID filter. You can query currentMerchant to get the merchant ID and other merchant-related fields, as shown in the following example:

{ currentMerchant { id status mainLocation { id } } }
Link to section

Retrieve a specific object

Most graph entry points allow you to specify an id filter that lets you retrieve a specific object. The following example query uses the id filter to retrieve a specific payment:

You can use variables to replace static or dynamic values in query arguments. For example, by using a variable for the merchant ID that's required to access Square data, you can easily reuse the query for different merchants.

The format for a variable is $variableName (a dollar sign followed by the variable name). To use a variable in a query, you must:

  1. Declare that the variable is used in the query.
  2. Replace the value in the query with the variable.
  3. Define the value of the variable.

The following example cURL query uses two variables, $merchantId and $searchText:

curl https://connect.squareupsandbox.com/public/graphql \ -X POST \ -H 'Authorization: Bearer <ACCESS_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "query CatalogTextSearch($merchantId: ID!, $searchText: [String!]!) { catalog(filter: { merchantId: { equalToAnyOf: [$merchantId]}, text: { value: $searchText}}) { nodes { id ... on CatalogItem { name }}}}", "variables": { "merchantId": "8QJT7EXAMPLE", "searchText": ["gluten", "free"]} }'

Note how the variables are used in the example query:

  • The variables and their types are declared as arguments for the query operation:

query CatalogTextSearch($merchantId: ID!, $searchText: [String!]!)

  • The $merchantId variable is used by the merchantId filter in the query:

merchantId: { equalToAnyOf: [$merchantId] }

  • The $searchText variable is used by the text filter in the query:

text: { value: $searchText }

  • The values for both variables are defined in the variables object:

"variables": { "merchantId": "8QJT7EXAMPLE", "searchText": ["gluten", "free"] }

Values are passed in a separate, transport-specific (usually JSON) variables dictionary. You can also use a separate JSON file to pass in variable values.

In GraphQL Explorer and similar interfaces, the query is entered in the query pane. As in the preceding example, variables are declared in query arguments using the $variableName format:

query CatalogTextSearch($merchantId: ID!, $searchText: [String!]!) { catalog( filter: { merchantId: {equalToAnyOf: [$merchantId] } text: {value: $searchText} } ) { nodes { id ... on CatalogItem { name } } } }

Variable values are defined in the Query Variables pane.

{ "merchantId": "8QJT7EXAMPLE", "searchText": ["gluten", "free"] }

Note

The sample queries available in GraphQL Explorer also show how to use variables in queries and pass in their values.

Fragments are reusable snippets used to request the same set of predefined fields for an object. Fragments can help simplify and organize queries and make them easier to maintain. Fragments are defined outside of a query and referenced from the query using the ... fragmentName syntax.

The following example query defines a set of fields for a contactInfo fragment and then references the fragment from Customer objects in the query:

Inline fragments are embedded in the query and let you independently request fields for implementations of a polymorphic object. For example, the CatalogObject object in the Catalog graph can represent one of many catalog object implementations, such as:

  • CatalogCategory
  • CatalogImage
  • CatalogItem
  • CatalogItemVariation
  • CatalogModifier
  • CatalogTax

Each implementation inherits some fields from the base CatalogObject object and also exposes its own type-specific fields. The following example query uses the ... on typeName syntax to request type-specific fields for CatalogCategory, CatalogItem, and CatalogItemVariation subtypes.

For another example of using inline fragments to request fields based on different implementations, see the Catalog sample query in GraphQL Explorer.

Pagination is used to retrieve all the results of a query using paged responses. Square GraphQL uses the cursor method of pagination. You retrieve pages of data by optionally specifying the page size and then use a pointer (cursor) to keep track of where the next page of data should be retrieved from.

The following example query uses pagination to retrieve all orders for a given merchant and location:

  • The first field specifies the page size, which is the maximum number of items to return in each response page. If you omit this field, the default page size is used.
  • The pageInfo field requests hasNextPage and endCursor to use for forward pagination.

The following is an example paged response:

If more pages of data are available, hasNextPage is true and endCursor contains the cursor.

In your next query, include the after field and provide the cursor from the previous response, as shown in the following example:

Continue using the cursor from each response page in a subsequent query until you retrieve all response pages.

In the last response page, hasNextPage is false and endCursor is null, as shown in the following example:

The pagination process might vary depending on the Square graph being queried. For example, payments and refunds can also be paginated in a backward direction using the last and before fields with startCursor.

In addition, valid first and last page size values might vary depending on the graph or the complexity score of the query.

Link to section

See also