Crystallize logo

Checkout Flow: Leveraging Crystallize APIs

Psst: we are hiring remote frontend developers and backend developers.

Illustration of backend developer holding a laptop against a designer holding a picture of cat

This post explores three important functions: fetching products, adding to a cart using our brand-new Shop API and pushing orders. The queries mentioned in this post are not tied to any language; you will use the same queries regardless of your language.

Fetching a Product

The first step is to fetch a product from Crystallize using the Catalogue API. This read-only endpoint provides essential details about products, such as variants, attributes, pricing, and much more. By default, it is an open endpoint. To change that, head to Settings.

API endpoint:

https://api.crystallize.com/your-tenant-identifier/catalogue

Alright, let’s take a look at how we can fetch a product. I’ll fetch minimal details about a single product from our demo tenant:

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 the version. The published version is fetched by default, 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.

Adding to Cart

Now that we have our product let’s see how to hydrate a cart using the Shop API. The Shop API is the new cool kid in town, and you can read more about how to access it in the learn section as you need to pass in a bearer token to access it.

API endpoint:

https://shop-api.crystallize.com/your-tenant-identifier/cart

Here is 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 - hydrate takes in some input arguments. An important thing here is the sku. The SKU is what tells the Shop API which item from the catalog 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. What does it do? The state specifies the state of the cart; this can be one of the two - 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 it cannot be edited any further.

[note]💡Note.

I recommend going to the endpoint (https://shop-api.crystallize.com/your-tenant/cart) https://shop-api.crystallize.com/your-tenant/cartand playing around with the queries and mutations. The docs within the playground are easy to comprehend, and if you have any questions, you can always contact us on Slack.

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. Remember 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. Cool! Now, you want to push an order to Crystallize once the user places the cart. The Order API serves as the gateway for managing customer information, cart details, and payment methods.

API endpoint:

<https://api.crystallize.com/your-tenant-identifier/orders>

The Order API requires authentication, and you will need to have access tokens for this purpose. More on how to do this is provided in the docs for the Order API. The API has queries to fetch a single order or multiple orders, including a mutation to create an order. Since we are focusing on pushing an order to Crystallize, here is an example mutation:

mutation createOrder {
orders {
create(
input: {
customer: {
firstName: "Legolas"
lastName: "Greenleaf"
identifier: "lego@example.com"
addresses: [
{
type: billing
streetNumber: "16"
street: "Greenwood"
city: "Woodland Realm"
country: "Ithilien"
postalCode: "9999"
email: "legolasgreenleaf@example.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
}
}
}

Time to break down the mutation! The create order mutation takes in 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. It includes information about the cart - items, meta information, etc. 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.

[note]💡Note.

You, as a user, have full control over the information provided to the Order API. Behind the scenes, it does not interact with any other API, it returns exactly what you provide.

In case you are using JavaScript, we have helper functions in the 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 in the learn section, and here is the Github repository for the package.