More in Learn

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.

Fetching a Product

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.

Hydrating the Cart

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

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.

Order Intent via Shop API

The Shop API also has a query that takes the Cart and returns an order intent. The query for that is as follows:

query {
  orderIntent(id:"CART_ID") {
order
  }
}

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
  }
}

Pushing an Order

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.

JS API Client

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.

Check Out Our Checkout Flow Tutorial Livestream

People showing thumbs up

Need further help?

Join and ask our
slack community.

Join our slack community