Skip to main content
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 assistance?

Ask the Crystallize team or other enthusiasts in our slack community.

Join our slack community