GraphQL is an open-source query language that allows you to pull specified data from multiple sources with one call. For more information about GraphQL, visit graphql.org.
Learn more about how to use GraphQL with Composable Commerce in our self-paced GraphQL module.
Objectives of this guide
By the end of this guide you will have:
Placeholder values
Example code in this getting started guide uses placeholders that should be replaced with these values:
Placeholder | Replace with | From |
---|---|---|
{projectKey} | project_key | your API Client |
{region} | your Region | Hosts |
${BEARER_TOKEN} | your access token | Make your first API call |
Query your Project with GraphQL
The Composable Commerce GraphQL Explorer is available for evaluating and trying out commands.
GraphQL API requests can be executed using a POST call to the /graphql
endpoint.
Use the GraphQL Explorer
To explore the GraphQL API, you can use the GraphQL Explorer in the Merchant Center.
- Log in to the Merchant Center.
- Go to Settings > Developer settings > GraphQL Explorer.
- Enter GraphQL queries in the left panel.
Use autocomplete
When using the GraphQL Explorer, press ctrl
+space
to view a list of valid entries. Use the up/down arrow keys to navigate the list.
Use an API request
This example code shows how to return basic Project information.
POST https://api.{region}.commercetools.com/{projectKey}/graphql/
Authorization: Bearer ${BEARER_TOKEN}
{"query": "query ReturnProjectInformation { project { key createdAt }}"}
{
"data": {
"project": {
"key": "{projectKey}",
"createdAt": "2022-01-23T18:02:58.542Z"
}
}
}
Structure GraphQL requests
The structure of GraphQL calls vary based on whether you want to query existing data, create entities, or update existing entities.
Query existing entities
Querying existing entities within your Project uses query
. A name can be included to describe the call.
# Query existing data
query ReturnCustomers{}
Add an endpoint
In this example, customers
targets all of our Customers. To target a single Customer, use customer
.
query ReturnCustomers{
# Access the Customers endpoint
customers{
}
}
query ReturnASingleCustomer {
# Access the Customer endpoint
customer() {
}
}
Add query parameters
When querying an endpoint such as customers
(where all Customers are targeted) these query parameters can be added based on your requirements.
Parameter | Action | Example use |
---|---|---|
where | Only returns entities that match the Query Predicate. Quotation marks within quotation marks must be escaped. | where: "firstName=\"John\"" |
sort | Changes the order of the returned entities. | sort: "lastName asc" |
limit | The maximum number of results to return. The default value is 20. | limit: 5 |
offset | Used for skipping results. The default value is 0. | offset: 1 |
When querying an endpoint like customer
(where a single Customer is targeted) you must enter a unique identifier for the entity (usually its id
or key
).
Query parameters must be enclosed in ()
next to the endpoint:
query ReturnCustomers {
# Access the Customers endpoint
# Return five Customers named "John", ordered by their surname (ascending), and not including the first result
customers(where: "firstName=\"John\"", sort: "lastName asc", limit: 5, offset: 1) {
}
}
query ReturnASingleCustomer {
# Access the Customer endpoint
# Return a Customer based on their id
customer(id: "{customerID}") {
}
}
Choose what to return
When querying an endpoint such as customers
(where all Customers are targeted) you can return the following:
offset
is the same value you selected in the parameters.count
is the number of entities returned based on thelimit
parameter.total
is the total number of entities in your Project.exists
returns a boolean value to indicate whether a queried entity exists. For example, when checking whether an email address has already been registered by a Customer.results
is the object where you include the values (such asid
orversion
) you want to be returned.
When querying an endpoint like customer
(where a single Customer is targeted), you only choose the values of the entity to return.
# Query existing data
query ReturnCustomers {
# Access the Customers endpoint
# Return five Customers named "John", ordered by their surname (ascending), and not including the first result
customers(
where: "firstName=\"John\""
sort: "lastName asc"
limit: 5
offset: 1
) {
# Display the offset, count, and total
offset
count
total
# The values to return: The Customer's ID, version, email, and name are returned.
results {
id
version
email
firstName
lastName
}
}
}
query ReturnASingleCustomer {
# Access the Customer endpoint
# Return a Customer based on their id
customer(id: "{customerID}") {
id
version
email
firstName
lastName
}
}
Create and update entities
When creating or updating entities within your Project, use mutation
. A name can be included to describe the call.
# Create a new entity
mutation CreateDiscountCode{}
# Update an existing entity
mutation DeactivateDiscountCode{}
Add an action
Instead of requiring an endpoint, the mutation
requires an action. The chosen action determines whether you are creating a new entity or updating an existing one.
If you are using the GraphQL Explorer, use autocomplete to view a full list of actions.
When creating a new entity
Like with the HTTP API, you must post a draft to create a new entity.
You must also include the values you want GraphQL to return once the entity has been created.
# Create a new entity
mutation CreateDiscountCode {
# The action for creating a Discount Code
createDiscountCode(
# The DiscountCodeDraft and its required fields
draft: {
code: "SAVE25"
isActive: true
cartDiscounts: { typeId: "cart-discount", id: "{cartDiscountID}" }
}
) {
# The values to return
code
isActive
}
}
When updating an existing entity
Like with the HTTP API, you must post an array of update actions to modify the data of existing entities.
You must also include the values you want GraphQL to return once the entity has been updated.
# Update an existing entity
mutation DeactivateDiscountCode {
# The action to update an existing entity
updateDiscountCode(
version: 1
id: "{discountCodeID}"
## Include update actions and their required parameters
actions: [{ changeIsActive: { isActive: false } }]
) {
# The values to return
code
isActive
}
}
Delete entities
When deleting entities within your Project, use mutation
. You can include a name to describe the call.
# Delete an existing entity
mutation DeleteDiscountCode {
# The action to delete an existing entity
deleteDiscountCode(version: 1, id: "{discountCodeID}") {
# The values to return
id
code
}
}
Try our example calls
The following GraphQL calls demonstrate how to perform the same example calls as in the Manage Customers and Manage Products pages as well as how to use Product Projection Search.
Manage Customers
Create a Customer
mutation CreateCustomer {
customerSignUp(
# Creating a Customer requires a CustomerDraft which has two required fields: email and password.
draft: { email: "graphql@example.com", password: "examplePassword" }
) {
customer {
# Return the new Customer's ID, version, and email address.
id
version
email
}
}
}
{
"data": {
"customerSignUp": {
"customer": {
"id": "{customerID}",
"version": 1,
"email": "graphql@example.com"
}
}
}
}
Query a Customer
query GetCustomerById {
# Access the Customer's endpoint based on their ID.
customer(id: "{customerID}") {
# Return the Customer's ID, version, email, and name.
id
version
email
}
}
{
"data": {
"customer": {
"id": "{customerID}",
"version": 1,
"email": "graphql@example.com"
}
}
}
Add a Customer name
mutation AddCustomerName {
# The update action
updateCustomer(
# The current version of the Customer. This is 1 for new Customers.
version: 1
# The ID of the Customer to update.
id: "{customerID}"
# An array of update actions.
actions: [
{
# The action to change the first name.
setFirstName: { firstName: "John" }
}
{
# The action to change the last name.
setLastName: { lastName: "Smith" }
}
]
) {
# Return the ID, version, email address, and name of the Customer.
id
version
email
firstName
lastName
}
}
{
"data": {
"updateCustomer": {
"id": "{customerID}",
"version": 3,
"email": "graphql@example.com",
"firstName": "John",
"lastName": "Smith"
}
}
}
Find a Customer by their email address
query GetCustomerByEmail {
# Access the Customers endpoint, filtering results by the "where" query parameter.
customers(where: "email=\"graphql@example.com\"") {
results {
# Return the Customer's ID, version, email, and name.
id
version
email
firstName
lastName
}
}
}
{
"data": {
"customers": {
"results": [
{
"id": "{customerID}",
"version": 3,
"email": "graphql@example.com",
"firstName": "John",
"lastName": "Smith"
}
]
}
}
}
Manage Products
Create a ProductType
mutation CreateProductType {
createProductType(
# Creating a Product Type requires a ProductTypeDraft which has two required fields: name and description.
draft: {
name: "A new Product Type"
description: "Description of the new Product Type"
}
) {
# Return the new Product Type's ID, version, name, and description.
id
version
name
description
}
}
{
"data": {
"createProductType": {
"id": "{productTypeID}",
"version": 1,
"name": "A new Product Type",
"description": "Description of the new Product Type"
}
}
}
Create a Product
mutation CreateProduct {
createProduct(
draft: {
# Creating a Product requires a ProductDraft which has three required fields: name, productType, and slug.
name: { locale: "en", value: "English Product Name" }
productType: { typeId: "product-type", id: "{productTypeID}" }
slug: { locale: "en", value: "english-product-name" }
}
) {
# Return the new Product's id, Product Type, version, and published ("current") name.
id
productType {
id
}
version
masterData {
current {
nameAllLocales {
value
}
}
}
}
}
{
"data": {
"createProduct": {
"id": "{productID}",
"productType": {
"id": "{productTypeID}"
},
"version": 1,
"masterData": {
"current": {
"nameAllLocales": [
{
"value": "English Product Name"
}
]
}
}
}
}
}
Query your Product
query QueryProduct {
# Access the Product endpoint based on its ID.
product(id: "{productID}") {
# Return the Product's ID, version, and published ("current") name.
id
version
masterData {
current {
nameAllLocales {
value
}
}
}
}
}
{
"data": {
"product": {
"id": "{productID}",
"version": 1,
"masterData": {
"current": {
"nameAllLocales": [
{
"value": "{productName}"
}
]
}
}
}
}
}
Create a ProductVariant
mutation AddProductVariant {
# The update action
updateProduct(
# The current version of the Product. This is 1 for new Products.
version: 1
# The ID of the Product to add the Variant to.
id: "{productID}"
# An array of update actions
actions: [
{
# The action to add a Variant
addVariant: {
sku: "myProductVariantSKU"
key: "my-product-variant-key"
# This field is optional. If false it makes the Variant published ("current").
staged: false
}
}
]
) {
# Return the ID, version, and key and SKU of all the published ("current") Product Variants
id
version
masterData {
current {
allVariants {
key
sku
}
}
}
}
}
{
"data": {
"updateProduct": {
"id": "{productID}",
"version": 3,
"masterData": {
"current": {
"allVariants": [
{
"key": "my-product-variant-key",
"sku": "myProductVariantSKU"
}
]
}
}
}
}
}
Retrieve values of enum Attributes in a ProductType
{
productType(key: "product-type-key") {
attributeDefinitions {
results {
name
type {
name
__typename
...enumValues
...localizedEnumValues
}
}
}
}
}
fragment enumValues on EnumAttributeDefinitionType {
values {
results {
key
label
}
}
}
fragment localizedEnumValues on LocalizableEnumAttributeDefinitionType {
values {
results {
key
labelAllLocales {
locale
value
}
}
}
}
{
"data": {
"productType": {
"attributeDefinitions": {
"results": [
{
"name": "creationDate",
"type": {
"name": "datetime",
"__typename": "DateTimeAttributeDefinitionType"
}
},
{
"name": "articleNumberManufacturer",
"type": {
"name": "text",
"__typename": "TextAttributeDefinitionType"
}
},
{
"name": "madeInItaly",
"type": {
"name": "enum",
"__typename": "EnumAttributeDefinitionType",
"values": {
"results": [
{
"key": "yes",
"label": "yes"
},
{
"key": "no",
"label": "no"
}
]
}
}
},
{
"name": "color",
"type": {
"name": "lenum",
"__typename": "LocalizableEnumAttributeDefinitionType",
"values": {
"results": [
{
"key": "black",
"labelAllLocales": [
{
"locale": "en",
"value": "black"
},
{
"locale": "de",
"value": "schwarz"
}
]
},
{
"key": "white",
"labelAllLocales": [
{
"locale": "de",
"value": "weiss"
},
{
"locale": "en",
"value": "white"
}
]
}
]
}
}
}
]
}
}
}
}
Use Product Projection Search
To be able to use the Product Projection Search endpoint, your product catalog must be indexed first. If indexing is deactivated for your Project, a SearchDeactivated error is returned.
To activate the indexing for your Project, choose one of the following options:
- via API using the Change Product Search Indexing Enabled update action on the Project endpoint.
- via the Merchant Center by navigating to Settings > Projects Settings > Storefront search.
- via contacting the Composable Commerce support team and provide your region, Project key, and use case.
Search based on text and locale
query {
productProjectionSearch(staged: true, locale: "en-US", text: "bed") {
total
# Uncomment to return the ID and English name of each result.
# results{
# id
# name(locale:"en-US")
# }
}
}
{
"data": {
"productProjectionSearch": {
"total": 17
}
}
}
Search based on text, locale, and filtering
query {
productProjectionSearch(
queryFilters: [{ string: "published:true" }]
staged: true
locale: "en-US"
text: "bed"
) {
# Return the total number of results.
total
# Uncomment to return the ID and English name of each result.
# results{
# id
# name(locale:"en-US")
# }
}
}
{
"data": {
"productProjectionSearch": {
"total": 17
}
}
}
Search using filters
query {
productProjectionSearch(
staged: true
filters: [
{
model: {
value: { path: "variants.price.centAmount", values: ["1599"] }
}
}
]
) {
total
results {
id
version
}
}
}
{
"data": {
"productProjectionSearch": {
"total": 3,
"results": [
{
"id": "394f20b4-0b21-45f7-81cc-43a4e45ba775",
"version": 1
},
{
"id": "ecc60e5f-ddd7-4137-8b84-fcaa17426549",
"version": 3
},
{
"id": "df65a374-e281-41a1-a370-c4d2591cae39",
"version": 1
}
]
}
}
}
Retrieve facet calculation
query {
productProjectionSearch(
facets: [
{
model: {
range: {
path: "variants.price.centAmount"
ranges: [{ from: "1000", to: "3000" }]
countProducts: false
}
}
}
]
) {
facets {
facet
value {
type
... on RangeFacetResult {
dataType
ranges {
type
... on RangeCountDouble {
from
fromStr
to
toStr
count
productCount
totalCount
total
min
max
mean
}
}
}
}
}
}
}
{
"data": {
"productProjectionSearch": {
"facets": [
{
"facet": "variants.price.centAmount",
"value": {
"type": "range",
"dataType": "number",
"ranges": [
{
"type": "double",
"from": 1000,
"fromStr": "1000.0",
"to": 3000,
"toStr": "3000.0",
"count": 35,
"productCount": null,
"totalCount": 35,
"total": 62065,
"min": 1099,
"max": 2999,
"mean": 1773.2857142857142
}
]
}
}
]
}
}
}
Differentiate between highPrecision and centPrecision money
{
productProjectionSearch(staged: false, locale: "en", text: "blue") {
count
results {
id
masterVariant {
sku
prices {
...productPrice
}
}
}
}
}
fragment productPrice on ProductPriceSearch {
value {
...money
__typename
}
discounted {
value {
...money
__typename
}
__typename
}
}
fragment money on BaseMoney {
type
currencyCode
centAmount
fractionDigits
... on HighPrecisionMoney {
preciseAmount
}
}
{
"data": {
"productProjectionSearch": {
"results": [
{
"id": "500797c7-e719-4d72-8c69-92fdee39d451",
"masterVariant": {
"sku": "M0E20000000E582",
"prices": [
{
"value": {
"type": "highPrecision",
"currencyCode": "USD",
"centAmount": 24875,
"fractionDigits": 11,
"preciseAmount": 24875123456789,
"__typename": "HighPrecisionMoney"
},
"discounted": null
},
{
"value": {
"type": "centPrecision",
"currencyCode": "EUR",
"centAmount": 16311,
"fractionDigits": 2,
"__typename": "Money"
},
"discounted": null
}
]
}
}
]
}
}
}