Using queries
A GraphQL query retrieves data from the Magento server in a similar manner as a REST GET call. The current set of Magento GraphQL queries allow a mobile app or browser to render a wide variety of information, including the following:
- A set of products to be displayed. This can include the entire catalog or those that match customer-specified criteria.
- Customer data. With a customer token, a query can retrieve basic information about a customer as well as billing and shipping addresses, wish lists, order history, and other sensitive data.
- Shopping cart contents. GraphQL supports both guest and logged-in customer carts.
- Store configuration values, including theme and CMS settings, the currency code, and supported countries.
The Magento REST GET endpoints retrieve a wide variety of information on behalf of the merchant. Many of these endpoints are for retrieving backend information. For example, the GET /V1/customers/search
endpoint can be used to find a subset of customers that meet certain criteria, such as those that live in a particular state or have a birthday this month. Likewise, the GET /V1/invoices
endpoint can return all the recently-generated invoices. This type of functionality is not required for the frontend, so it is not available in GraphQL queries. The queries are designed to improve the customer’s user experience by quickly retrieving the data needed to render pages.
Over time, the Magento GraphQL queries will duplicate the functionality of all storefront-facing GET calls, while making it possible to query more data in one request. The main difference will be that GraphQL will support storefront use cases, while REST will support admin use cases.
Structure of a query
A query contains the following elements:
- The optional keyword
query
. If no keyword is specified at the beginning of a request, the processor assumes the request is a query. - An operation name for your local implementation. This name is required if you include variables. Otherwise, it is optional.
- The query name
- The terms to search for. The terms can be in the form of objects, attributes, or a combination. Queries that don’t require search terms obtain their context from the customer’s authorization token or store ID, both of which are specified in the header of the call.
- The output object, which specifies which data the query returns.
The following example shows the structure of the cart
query:
1
2
3
query myCartQuery{
cart(cart_id: String!): Cart
}
In the preceding example, myCartQuery
identifies your implementation of the cart
query. cart_id
is a non-nullable string that defines the cart to query. (The exclamation point indicates the value is non-nullable.) The Cart
output object defines which fields to return.
Now let’s fully define a query:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
query myCartQuery{
cart(cart_id: "1WxKm8WUm3uFKXLlHXezew5WREfVRPAn") {
items {
id
quantity
}
billing_address {
firstname
lastname
postcode
}
shipping_addresses {
firstname
lastname
postcode
}
}
}
In this example, we’ve supplied a cart ID as input, (which was generated by the createEmptyCart
mutation). The output includes the cart_id
as well as selected information about the items in the cart and the billing and shipping addresses.
The following example shows the query 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
{
"data": {
"cart": {
"items": [
{
"id": "5",
"quantity": 1
}
],
"billing_address": {
"firstname": "Veronica",
"lastname": "Costello",
"postcode": "49628-7978"
},
"shipping_addresses": [
{
"firstname": "Veronica",
"lastname": "Costello",
"postcode": "49628-7978"
}
]
}
}
}
Magento will not run a query that is too complex. The number of fields, objects, and nodes are factors in determining the complexity of a query.
Query variables
Specifying variables in a query can help increase code re-use. Consider the following requirements when generating a query that contains one or more variables:
- All variables must be declared up-front, immediately after the operation name.
- Variables are typed: they can be scalar or an object.
- You must use all declared variables. Object variables are defined in JSON.
The following example declares the $cart_id
variable. It is referenced in the input
statement.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
query myCartQueryWithVariable($cart_id: String!) {
cart(cart_id: $cart_id) {
items {
id
quantity
}
billing_address {
firstname
lastname
postcode
}
shipping_addresses {
firstname
lastname
postcode
}
}
}
Variables are defined separately in JSON:
1
2
3
{
"cart_id": "1WxKm8WUm3uFKXLlHXezew5WREfVRPAn"
}
Staging queries
Magento GraphQL allows you to use certain queries to return preview information for staged content. Staging, a Magento Commerce feature, allows merchants to schedule a set of changes to the storefront that run for a prescribed time in the future. These changes, also known as a campaign, are defined within the Admin. Customers do not have access to staged content, and as a result, staging queries have requirements that do not apply to traditional queries and mutations.
Content Staging in the Merchant User Guide describes how to create a campaign.
You can use the following queries to return staged preview information.
categoryList
products
The products
query does not support full text search in the context of staging, because staged content is not indexed. Therefore, omit the search
input attribute in your staging products
queries.
A staging query requires two specialized headers:
Header name | Description |
---|---|
Authorization Bearer: <authorization_token> |
An admin token. Use the GET /V1/integration/admin/token REST endpoint to generate this token. |
Preview-Version |
A timestamp (seconds since January 1, 1970) that is inside the range of dates of the campaign you are querying. |
Magento returns an authorization error if you specify an invalid token or do not include both headers. If the specified timestamp does not correspond to a date in a scheduled campaign, the query results reflect the current storefront settings.
Magento also returns an error if you specify these headers with any other query or any mutation.
Example campaign
The example staging queries in this section are based on a simple campaign that creates a custom category and catalog sales rule using the Luma sample data. By default, the custom category and sales rule are disabled but become enabled when the campaign takes effect.
The following steps describe how to create this example campaign.
- Create a subcategory of Sale named End of Year Sale. Set the Enable Category field to No.
- Add several products to the subcategory.
- Schedule an update named End of Year Sale Update for the subcategory that takes effect at a later date. Configure the update so that the Enable Category field is set to Yes.
- Create a catalog sales rule with the following properties:
- Set the Active switch to No.
- In the Conditions section, define the condition as **Category is
**. - In the Actions section, set the Apply field to Apply a percentage of original and the Discount Amount field to 25.
- Schedule an update for the catalog sales rule and assign it to the End of Year Sale Update. In this update, set the Active switch to Yes.
Staging products
query
The following query returns information about a product (24-UG05
) in the End of Year Sale campaign. The Preview-Version
header contains the timestamp for a date that is within the duration of the campaign. When you include the proper headers, the query returns prices with applied discounts. Without the headers, the query returns only default prices.
Headers:
1
2
Authorization: Bearer hoyz7k697ubv5hcpq92yrtx39i7x10um
Preview-Version: 1576389600
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
products(filter: {sku: {eq: "24-UG05"}}) {
items {
name
sku
price_range {
minimum_price {
discount {
percent_off
amount_off
}
final_price {
value
currency
}
regular_price {
value
}
}
}
}
}
}
Response with headers:
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
{
"data": {
"products": {
"items": [
{
"name": "Go-Get'r Pushup Grips",
"sku": "24-UG05",
"price_range": {
"minimum_price": {
"discount": {
"percent_off": 25,
"amount_off": 4.75
},
"final_price": {
"value": 14.25,
"currency": "USD"
},
"regular_price": {
"value": 19
}
}
}
}
]
}
}
}
Response without headers:
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
{
"data": {
"products": {
"items": [
{
"name": "Go-Get'r Pushup Grips",
"sku": "24-UG05",
"price_range": {
"minimum_price": {
"discount": {
"percent_off": 0,
"amount_off": 0
},
"final_price": {
"value": 19,
"currency": "USD"
},
"regular_price": {
"value": 19
}
}
}
}
]
}
}
}
Staging categoryList
query
In this example campaign, the End of Year Sale subcategory and a catalog price rule are disabled when the campaign is not in effect. When you specify valid headers, the categoryList
query returns full details about the custom category. Otherwise, the query returns an empty array.
Headers:
1
2
Authorization: Bearer hoyz7k697ubv5hcpq92yrtx39i7x10um
Preview-Version: 1576389600
Request:
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
{
categoryList(filters: {ids: {eq: "43"}}) {
name
level
products(
sort: {
price: ASC
}
pageSize: 20
currentPage: 1
) {
total_count
items {
name
sku
price_range {
minimum_price {
discount {
amount_off
percent_off
}
final_price {
value
}
regular_price {
value
}
}
}
}
}
}
}
Response with headers:
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
79
80
81
82
83
84
85
86
87
{
"data": {
"categoryList": [
{
"name": "End of Year Sale",
"level": 3,
"products": {
"total_count": 4,
"items": [
{
"name": "Solo Power Circuit",
"sku": "240-LV07",
"price_range": {
"minimum_price": {
"discount": {
"amount_off": 3.5,
"percent_off": 25
},
"final_price": {
"value": 10.5
},
"regular_price": {
"value": 14
}
}
}
},
{
"name": "Quest Lumaflex™ Band",
"sku": "24-UG01",
"price_range": {
"minimum_price": {
"discount": {
"amount_off": 4.75,
"percent_off": 25
},
"final_price": {
"value": 14.25
},
"regular_price": {
"value": 19
}
}
}
},
{
"name": "Go-Get'r Pushup Grips",
"sku": "24-UG05",
"price_range": {
"minimum_price": {
"discount": {
"amount_off": 4.75,
"percent_off": 25
},
"final_price": {
"value": 14.25
},
"regular_price": {
"value": 19
}
}
}
},
{
"name": "Gabrielle Micro Sleeve Top",
"sku": "WS02",
"price_range": {
"minimum_price": {
"discount": {
"amount_off": 7.00,
"percent_off": 25
},
"final_price": {
"value": 21
},
"regular_price": {
"value": 28
}
}
}
}
]
}
}
]
}
}
Response without headers:
1
2
3
4
5
{
"data": {
"categoryList": []
}
}
Introspection queries
Introspection queries allow you to return information about the schema. For example, you might want a list of Magento GraphQL queries or details about a specific data type. The GraphQL specification determines the structure of introspection queries. See Introspection for more information.
A Magento introspection query returns the same result whether or not you assign it an operation name, such as IntrospectionQuery
.
Example introspection queries
Return a list of Magento queries
The following query returns a list of Magento queries.
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
query IntrospectionQuery {
__schema {
queryType {
fields {
name
description
type{
name
kind
}
}
}
}
}
Return a list of Magento mutations
The following query returns a list of Magento mutations.
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
query IntrospectionQuery {
__schema {
mutationType {
fields {
name
description
type{
name
kind
}
}
}
}
}
Get details about a data type
The following introspection query returns details about the ProductAttributeFilterInput
data type.
Request:
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
query IntrospectionQuery {
__type(name: "ProductAttributeFilterInput") {
name
kind
description
inputFields {
name
description
defaultValue
}
fields {
name
args {
name
description
type {
kind
name
}
}
type {
kind
name
}
}
}
}
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
{
"data": {
"__type": {
"name": "ProductAttributeFilterInput",
"kind": "INPUT_OBJECT",
"description": "ProductAttributeFilterInput defines the filters to be used in the search. A filter contains at least one attribute, a comparison operator, and the value that is being searched for.",
"inputFields": [
{
"name": "category_id",
"description": "Filter product by category id",
"defaultValue": null
},
{
"name": "description",
"description": "Attribute label: Description",
"defaultValue": null
},
{
"name": "name",
"description": "Attribute label: Product Name",
"defaultValue": null
},
{
"name": "price",
"description": "Attribute label: Price",
"defaultValue": null
},
{
"name": "short_description",
"description": "Attribute label: Short Description",
"defaultValue": null
},
{
"name": "sku",
"description": "Attribute label: SKU",
"defaultValue": null
},
{
"name": "url_key",
"description": "The part of the URL that identifies the product",
"defaultValue": null
}
],
"fields": null
}
}
}