Checkout Flow Tutorial
This Crystallize tutorial explores three important functions: fetching products, adding to cart using the Shop API, and pushing orders.
The queries mentioned here are not tied to any specific programming language. You’ll use the same queries no matter what language you’re using.
The first step is to fetch a product from Crystallize using the Catalogue API. By default, it’s an open endpoint.
Catalogue API endpoint:
https://api.crystallize.com/your-tenant-identifier/catalogue
Here’s an example query to fetch minimal details about a product:
query GetProduct {
catalogue(language: "en", path: "/shop/kitchen/smeg-robot") {
id
name
path
... on Product {
variants {
name
sku
isDefault
priceVariants {
identifier
price
}
stockLocations {
identifier
stock
}
attributes {
attribute
value
}
}
}
}
}
There are two variables required for the above query: language and path. Additionally, you can also pass in version. By default, the published version is fetched, but you can also fetch the draft version.
The query above fetches pertinent information about the product such as the VAT type and all its variants. Going a bit deeper into the variants, we fetch the name, all the price variants, attributes, stock locations, and whether or not the variant is a default variant. You can expand this query further to fetch more information as per your requirements.
Now that we have our product, let’s see how to hydrate a cart using the Shop API. The Shop API requires authentication; refer to the Shop API docs for more information on how to access it.
Shop API endpoint:
https://shop-api.crystallize.com/your-tenant-identifier/cart
NOTE: Before we hydrate the cart with items, please make sure that the item is published in the language you are hydrating it in and that it has a price variant. You can set both of those via the context field in the hydrate mutation as follows (a more detailed list of all the fields included in the context are provided in our introductory doc for the API) :
mutation {
hydrate(input: {
context: {
language: "no"
price: {
selectedVariantIdentifier: "dollar"
fallbackVariantIdentifiers: ["euro", "nok"]
pricesHaveTaxesIncludedInCrystallize: true
}
}
}) {
id
}
}
Here’s a simple mutation to hydrate the cart using the Shop API:
mutation {
hydrate(input: {items: [{sku: "smeg-robot-pink-standard", quantity: 1}]}) {
id
items {
name
price {
net
gross
taxAmount
}
}
total {
gross
net
taxAmount
currency
}
state
}
}
Let’s go through the mutation to understand it better.
- hydrate - This takes in some input arguments. An important thing here is the sku. The SKU is what tells the Shop API which item from the catalogue you would like to add to your cart (SKUs in Crystallize are unique).
- The Shop API takes care of calculations for you. As you can see, when you run the above mutation, you provide the SKU and quantity. The API calculates the net price, gross price, and the tax amount for you.
- state - There is also a field named state here that specifies the state of the cart. This can be one of two values, cart or placed. The former means that the cart can still be edited; you can add and remove items as you wish. However, once you set the state to placed, it becomes immutable and cannot be edited any further.
The query above takes the cart ID as an argument. Keep in mind that you cannot create an order intent for a cart that has not been placed yet. Before doing this, you must place the cart using this mutation:
mutation {
place(id: "CART_ID"){
state
}
}
You have now fetched the product details and added it to your cart. Now, you want to push an order to the Order API once the user places the cart. The Order API requires authentication, and you’ll need access tokens for this purpose.
Order API endpoint:
https://api.crystallize.com/your-tenant-identifier/orders
Here’s an example mutation to push an order to Crystallize:
mutation createOrder {
orders {
create(
input: {
customer: {
firstName: "Legolas"
lastName: "Greenleaf"
identifier: "legolasgreenleaf@fellowship.com"
addresses: [
{
type: billing
streetNumber: "16"
street: "Greenwood"
city: "Woodland Realm"
country: "Ithilien"
postalCode: "9999"
email: "legolasgreenleaf@fellowship.com"
}
]
}
cart: {
name: "Bow of the Galadhrim"
sku: "bow-galadhrim"
imageUrl: "https://media.crystallize.com/lotr/23/1/27/6/@200/bow-galadhrim.avif"
quantity: 1
price: {
gross: 1000
net: 800
tax: { name: "Tax", percent: 25 }
currency: "EUR"
}
}
payment: {
provider: custom
custom: {
properties: { property: "payment_method", value: "Invoice" }
}
}
total: {
gross: 1000
net: 800
currency: "EUR"
tax: { name: "Tax", percent: 25 }
}
}
) {
id
}
}
}
The createOrder mutation takes a few input arguments. This includes the information about the customer: name, address (can be multiple, the example only has billing address for simplicity’s sake), customer identifier, etc. It includes information about the cart such as items and meta information. The cart here only has one item, but it can be an array of items. It also includes information about the payment and the total price of the cart items.
You as the user have full control over the information provided to the Order API. Behind the scenes, it doesn’t interact with any other API. It returns exactly what you provide to it.
In case you’re using JavaScript, we have helper functions in our JS API Client that make it easier to interact with the APIs. The documentation for the package and how to use it can be found at our JS API Client page. You can also access the JS API Client Github repository.