GraphQL API
Access commercetools Composable Commerce via GraphQL.
The GraphQL API provides queries and mutations to the resources stored on commercetools Composable Commerce with the same API Clients that are used for the REST API.
This page explains how to:
- Formulate a GraphQL API request
- Apply scopes
- Determine query complexity
- Achieve Reference Expansion
- Query project-specific dynamic data such as Custom Fields and Attributes
This page does not document the standard types and fields that the GraphQL API provides. You can retrieve this information either from the GraphQL schema via the introspection system or by using the Documentation Explorer in the GraphQL console. For more information about the types and fields that are currently in public beta, see the Public beta functionalities section.
The introspection system also lets you discover features that are currently in early access and are intended for customers taking part in the early evaluation phase for upcoming features. Be aware that those features are not covered by our SLAs and can either change or be removed without public notice. The GraphQL schema that is publicly available on GitHub contains all the officially released API features which are covered by our SLAs.
Learn more about how to use GraphQL with Composable Commerce in our self-paced GraphQL module.
Get started
You can learn how to create and structure GraphQL requests in our get started guide.
Interactive GraphQL console
To explore the GraphQL API, you can use the GraphQL Explorer in the Merchant Center.
Application of scopes
Access to resources is granted by the same scopes that are used on the REST API endpoints. This page does not explain about scopes in detail, but you can follow these guidelines to find the most suitable scope for a specific use case:
Use case | GraphQL service | Scope |
---|---|---|
query for a particular resource | Query.{resourceType} | view_{resourceType}s:{projectKey} |
query for resources of a certain type | Query.{resourceType}s | view_{resourceType}s:{projectKey} |
create a resource of a certain type | Mutation.create{resourceType} | manage_{resourceType}s:{projectKey} |
update a particular resource | Mutation.update{resourceType} | manage_{resourceType}s:{projectKey} |
delete a particular resource | Mutation.delete{resourceType} | manage_{resourceType}s:{projectKey} |
For example, manage_products:{projectKey}
is required for updating a Product with the Mutation.updateProduct
service. The view_products:{projectKey}
scope would not be sufficient for this.
The view_published_products:{projectKey}
scope can be used by the Query.products
service to retrieve data in masterData.current
, but not in masterData.staged
. The same applies for the Query.productProjectionSearch
service that only returns data with this scope when the staged
parameter is set to false
in such queries.
Store-specific scopes are required to query or mutate Store-specific resources. For example, the service Query.inStore
requires view_{resourceType}s:{projectKey}:{storeKey}
.
Representations
GraphQLRequest
The query, operation name, and variables that are sent to the GraphQL API.
query String | String representation of the Source Text of the Document that is specified in the Language section of the GraphQL specification. |
operationName String | Name of the operation, if you defined several operations in |
variables | JSON object that contains key-value pairs in which the keys are variable names and the values are variable values. |
{"query": "query getProductByKey($productKey: String!) { product(key: $productKey) { id version }}","operationName": "getProductByKey","variables": {"productKey": "a-product-key"}}
GraphQLVariablesMap
The variables that the GraphQL query uses.
// Any string parameter matching this regular expression | JSON object that contains key-value pairs in which the keys are variable names and the values are variable values. |
{"productKey": "a-product-key"}
GraphQLResponse
error
is present in the response only if the GraphQL query was unsuccessful.
data Any | JSON object that contains the results of a GraphQL query. |
errors Array of GraphQLError | Errors that the GraphQL query returns. |
{"data": {"product": {"id": "35d33405-2d39-4528-b195-fa3ab6beb927","version": 2}}}
Query GraphQL
GraphQL uses HTTP POST requests to both query and mutate data.
Execute a GraphQL request.
view_products:{projectKey}
region String | Region in which the Project is hosted. |
projectKey String |
|
application/json
application/json
curl https://api.{region}.commercetools.com/{projectKey}/graphql -i \--header "Authorization: Bearer ${BEARER_TOKEN}" \--header 'Content-Type: application/json' \--data-binary @- << DATA{"query" : "query getProductByKey($productKey: String!) { product(key: $productKey) { id version }}","operationName" : "getProductByKey","variables" : {"productKey" : "a-product-key"}}DATA
{"data": {"product": {"id": "35d33405-2d39-4528-b195-fa3ab6beb927","version": 2}}}
Errors
If a GraphQL request is unsuccessful, the GraphQLResponse returns an array of GraphQLError.
GraphQLError
Contains an error message, the location of the code that caused the error, and other information to help you correct the error.
message String | Detailed description of the error explaining the root cause of the problem and suggesting how to correct the error. |
locations Array of GraphQLErrorLocation | Location within your query where the error occurred. |
path Array of Any | Query fields listed in order from the root of the query response up to the field in which the error occurred. |
extensions | Dictionary with additional information where applicable. |
{"message": "Object 35d33405-2d39-4528-b195-fa3ab6beb927 has a different version than expected. Expected: 1 - Actual: 2.","path": ["deleteProduct"],"locations": [{"line": 2,"column": 3}],"extensions": {"code": "ConcurrentModification","currentVersion": 2}}
GraphQLErrorLocation
Represents the location within your query where the error occurred.
line Int | Line number of the query where the error occurred. |
column Int | Position in |
GraphQLErrorObject
Represents a single error.
code String | One of the error codes that is listed on the Errors page. |
// Any string parameter matching this regular expression | Error-specific additional fields. |
Query Attributes, Custom Objects, and Custom Fields
Product Attributes, Custom Objects, and Custom Fields contain Project-specific dynamic data that can be accessed by using raw GraphQL fields.
Retrieve Product Attributes
The contents of the value
field reflect the data type that is used by the Product Attribute. For more information, see AttributeType. You must determine the data type yourself.
Example query and response for raw Product Attributes:
query {product(id: "3ba12359-f03e-4fa1-9c7e-7fbdb5393ec5") {masterData {current {variants {...variantFields}}}}}fragment variantFields on ProductVariant {skuattributesRaw {namevalue}}
{"data": {"product": {"masterData": {"current": {"variants": [{"sku": "M0E20000000E218","attributesRaw": [{"name": "productSupported","value": true},{"name": "supportContact","value": {"en": "english@example.com","de": "german@example.com"}}]}]}}}}}
Retrieve Custom Fields
The contents of the value
field reflect the data type that is used by the Custom Field. For more information, see FieldType. You must determine the data type yourself.
Example query and response for raw Custom Fields:
{product(id: "3ba12359-f03e-4fa1-9c7e-7fbdb5393ec5") {masterData {current {variants {prices {...customFields}}}}}}fragment customFields on ProductPrice {custom {customFieldsRaw {namevalue}}}
{"data": {"product": {"masterData": {"current": {"variants": [{"prices": [{"custom": {"customFieldsRaw": [{"name": "kiloPrice","value": {"type": "centPrecision","currencyCode": "EUR","centAmount": 95,"fractionDigits": 2}}]}}]}]}}}}}
Create Product Attributes, Custom Fields, and Custom Objects
To set values for Product Attributes, Custom Objects, and Custom Fields, you must use their corresponding input object types. For each of these, the value
field should be a string containing escaped JSON.
Examples for the value
field on ProductAttributeInput
:
"{\"type\": \"centPrecision\", \"currencyCode\": \"USD\", \"centAmount\": 1000, \"fractionDigits\": 2}"
"\"yellow\""
Examples for the value
field on CustomFieldInput
:
"[\"This is a string\", \"This is another string\"]"
"{\"id\": \"b911b62d-353a-4388-93ee-8d488d9af962\", \"typeId\": \"product\"}"
Example for the value
field on CustomObjectDraft
:
"{ \"stringField\": \"myVal\", \"numberField\": 123, \"boolField\": false, \"nestedObject\": { \"nestedObjectKey\": \"anotherValue\" }, \"dateField\": \"2018-10-12T14:00:00.000Z\" }"
Check if resources exist
For use cases where you only want to check whether at least one result exists that matches your query, use the boolean exists
field in your query. This will optimize the query and result in a shorter response time.
The API either returns true
if there is at least one result matching the query condition, or false
if there are none.
query {# As the quotation marks are within quotation marks, they must be escapedproducts(where: "productType(id=\"55e43a8a-b130-4ea3-9d90-4fd97bf90ab9\")") {exists}}
{"data": {"products": {"exists": true}}}
Reference Expansion
The GraphQL API supports Reference Expansion, just like the HTTP API.
By convention, the GraphQL API offers two fields for each expandable reference:
<fieldName>Ref
- Fetches the Reference or KeyReference to the resource only (lower query complexity).<fieldName>
- Fetches the expanded resource that is referenced (higher query complexity).
Returnsnull
if the referenced resource is not found.
Expanding a reference in the GraphQL API impacts the performance of the request, and adds to the complexity score. If you don't need the expanded reference for your use case, you should use the <fieldName>Ref
to get a better performance on your query.
For example, to retrieve the number of child Categories for a specific Category and the identifiers for its ancestors:
{category(id: "7bcd33e6-c1c7-4b96-8d70-9b9b18b19b70") {children {id}ancestors {id}}}
{"data": {"category": {"children": [{"id": "7900ab4b-c01c-4e73-8f10-557b84de55f5"},{"id": "93aa3372-310f-4fa7-8ab2-986036382e4f"},{"id": "0938dbd3-766e-48c2-b86b-31a3a3d820da"}],"ancestors": [{"id": "1fbfdc4b-b6c7-4f06-9db4-cbd4179f2a17"}]}}}
The total number of child Categories is the size of the children
array. The identifiers for ancestors are listed in the ancestors
field.
However, it is possible to reduce the complexity of the previous example. If you only need the number of child Categories, use the childCount
field. Also, if you only need the identifiers for the ancestors, it is better to use the ancestorsRef
field.
{category(id: "7bcd33e6-c1c7-4b96-8d70-9b9b18b19b70") {childCountancestorsRef {id}}}
{"data": {"category": {"childCount": 3,"ancestorsRef": [{"id": "1fbfdc4b-b6c7-4f06-9db4-cbd4179f2a17"}]}}}
Custom Fields BETA
Reference Expansion for Custom Fields of CustomFieldReferenceType and for the CustomFieldSetType is supported in public beta.
If, for example, a Category has a Custom Field that holds a Reference to a Custom Object, the following query expands the referenced Custom Object and retrieves the value
of the referenced Custom Object in the same query.
query {category(id: "7bcd33e6-c1c7-4b96-8d70-9b9b18b19b70") {custom {customFieldsRaw(includeNames: ["categoryCustom"]) {referencedResource {... on CustomObject {value}}}}}}
{"data": {"category": {"custom": {"customFieldsRaw": [{"referencedResource": {"value": {"extraCategoryData": "This is extra Category data"}}}]}}}}
Product Attributes BETA
Reference Expansion for Product Attributes is supported in public beta.
You can include referencedResource
(for single references) and referencedResourceSet
(for sets of references) under attributesRaw
for allVariants
or masterVariant
:
{product(id: "3ba12359-f03e-4fa1-9c7e-7fbdb5393ec5") {masterData {current {allVariants {attributesRaw {referencedResource {## If a referenced Product exists, return its name, SKUs, and key... on Product {masterData {current {slug(locale: "en")}}skuskey}## If a referenced ProductType exists, return the Attributes names and ProductType name... on ProductTypeDefinition {attributeDefinitions {results {name}}name}}referencedResourceSet {## If a set of referenced Products exists, return their names, SKUs, and keys... on Product {masterData {current {slug(locale: "en")}}skuskey}## If a set of referenced ProductTypes exists, return their Attribute names and ProductType names... on ProductTypeDefinition {attributeDefinitions {results {name}}name}}}}}}}}
Product Search Attributes BETA
Reference Expansion for Product Search Attributes are supported in public beta.
You can include referencedResource
(for single references) and referencedResourceSet
(for sets of references) under attributesRaw
for masterVariant
:
{productProjectionSearch(staged: true) {results {masterVariant {attributesRaw(includeNames: "{includedAttributes}"excludeNames: "{excludedAttributes}") {namevaluereferencedResource {id... on Product {skus}}referencedResourceSet {id... on Product {skus}}}}}}}
Query complexity
You can fetch a lot of useful information in a single HTTP request using GraphQL. This is really helpful to avoid parsing unused fields, and remove the unnecessary network overhead by reducing the number of requests. At the same time, it is important to remember that a single query can potentially generate a lot of database operations. Hence, you cannot assume that the response time for a query increases linear with the number of fields in the query.
The GraphQL schema defines a "cost" per field, which you can analyze by inspecting the x-graphql-query-complexity
response header and its value.
QueryComplexityLimitExceeded
To prevent complex queries from having a negative impact on the overall performance, we block queries equal to or higher than the complexity limit of 20 000
. In such cases, queries return a QueryComplexityLimitExceeded error code with the HTTP status code 400
.
code String | "QueryComplexityLimitExceeded" |
message String | |
// Any string parameter matching this regular expression | Error-specific additional fields. |
Public beta functionalities BETA
Find below a list of functionality that is currently in beta.
createdBy
andlastModifiedBy
onVersioned
MultiBuyLineItemsTarget
andMultiBuyCustomLineItemsTarget
onCartDiscount
stores
onCartDiscount
- everything related to
MyCart
,MyOrder
,MyPayment
,MyProfile
,MyShoppingList
,MyBusinessUnit
,MyQuote
,MyQuoteRequest
NestedTypes
onProductType
referencedResource
andreferencedResourceSet