Skip to content

query

Terminal window
npx skills add https://github.com/crystallizeapi/ai --skill query

Crystallize Query Skill

Query product data, content, and commerce information from Crystallize using GraphQL APIs. This skill covers reading data for storefronts, admin interfaces, product pages, search, and cart operations.

Consultation Approach

Before writing queries, understand the context. Ask clarifying questions:

  1. What data do you need? Products, orders, customers, content, shapes?
  2. Is this for a storefront or admin interface? Discovery/Catalogue for storefronts, Core for admin.
  3. Do you need search/filtering or exact path reads? Discovery for search and faceted navigation, Catalogue for deterministic reads by path.
  4. Do you have authentication configured? Core API requires access tokens. Discovery/Catalogue can be open but should be secured in production.
  5. What volume of results? Pagination strategy matters — cursor-based is recommended for all APIs.

Choosing the Right API

  • Need search, filtering, or faceting? → Discovery API
  • Know the exact path? Need strong consistency? → Catalogue API
  • Admin interface? Orders, customers, shapes? → Core API
  • Cart/checkout operations? → Shop API

How It Works

Crystallize provides four main APIs for querying data:

  1. Core API - Full read/write API with advanced filtering. Best for admin interfaces, customer/order management.
  2. Discovery API - Semantic API for search, browse, filter, and faceting. Best for storefronts.
  3. Catalogue API - Path-based reads for deterministic data access.
  4. Shop API - Cart and checkout queries at the edge.

API Endpoints

APIEndpointAuth RequiredUse For
Corehttps://api.crystallize.com/@{tenant}Yes (access tokens)Admin, customers, orders
Discoveryhttps://api.crystallize.com/{tenant}/discoveryOptional (configurable)Storefront search/filter
Cataloguehttps://api.crystallize.com/{tenant}/catalogueOptional (configurable)Storefront path-based reads
Shop /carthttps://shop-api.crystallize.com/{tenant}/cartYes (JWT)Cart hydration, checkout flows
Shop /orderhttps://shop-api.crystallize.com/{tenant}/orderYes (JWT)Order queries by ID/customer

Usage

Core API (Admin & Advanced Queries)

The Core API provides full read/write access with advanced filtering capabilities:

  • Read items by ID with full component data
  • List items with pagination and filtering
  • Query customers and orders with complex filters
  • Filter orders by customer, SKU, payment provider, metadata
  • Access shape and piece definitions
  • Manage flows and archives
# Example: Get item with components
query GetItem {
item(id: "item-id", language: "en") {
... on Product {
id
name
components {
componentId
content
}
defaultVariant {
sku
price
stock
}
}
}
}
# Example: List orders filtered by customer
query ListOrders {
orders(
tenantId: "tenant-id"
first: 20
filter: { customerIdentifier: "customer@example.com" }
sort: { field: createdAt, direction: desc }
) {
edges {
node {
id
total {
gross
currency
}
customer {
identifier
}
}
}
}
}

See Core API Queries Reference for complete documentation.

The Discovery API is the primary API for frontend development. It supports:

  • Full-text search
  • Filtering by any component or attribute
  • Faceted navigation
  • Sorting and cursor-based pagination

The Discovery API has two entry points: search for full-text queries with facets, and browse for shape-typed access where each shape becomes its own query type.

Note: The Discovery API uses lowercase type names in inline fragments (... on product, ... on category) because types are derived from your shape identifiers. You can still use it for interface (... on Product, ... on Folder).

# Example: Browse products by shape with pagination
{
browse {
product(language: en, pagination: { limit: 25 }) {
summary {
totalHits
hasMoreHits
endCursor
}
hits {
name
path
... on Product {
defaultVariant {
sku
defaultPrice
firstImage {
url
}
}
}
}
}
}
}
# Example: Search with facets and filtering
{
search(
language: en
term: "green"
filters: { type_in: [product] }
facets: { shape: { limit: 5 } }
pagination: { limit: 20 }
) {
summary {
totalHits
hasMoreHits
endCursor
facets
}
hits {
name
path
... on product {
defaultVariant {
defaultPrice
}
}
}
}
}

Catalogue API (Path-Based Reads)

Use for deterministic reads when you know the exact path:

{
catalogue(language: "en", path: "/shop/plants") {
name
... on Product {
variants {
sku
name
price
}
}
}
}

Shop API Queries

Retrieve cart and order intent data:

query {
cart(id: "cart-id") {
id
items {
sku
name
quantity
price {
gross
net
}
}
total {
gross
net
}
}
}

Best Practices

  1. Choose the right API - Core for admin, Discovery for storefront search, Catalogue for path-based reads
  2. Use Discovery API for storefronts - It’s optimized for performance and supports search/filter
  3. Include deterministic sorting - Always add a secondary sort field (like itemId) for stable pagination
  4. Request only needed fields - GraphQL allows precise field selection to minimize payload
  5. Handle async updates - Discovery API may have sub-second delay for recently published content
  6. Protect APIs in production - Configure authentication for sensitive data
  7. Use Core API for complex filters - Only Core API supports filtering orders by customer, SKU, payment provider

References


Reference Details

Catalogue API Reference

The Catalogue API provides path-based access to items in your Crystallize tenant. It offers strong consistency for deterministic reads.

Base URL

https://api.crystallize.com/{tenant-identifier}/catalogue

Replace {tenant-identifier} with your tenant name.

Authentication

By default, the API is accessible without authentication. You can configure access in the Crystallize App:

  1. Go to Settings → API Access
  2. Choose your preferred access level
  3. Save changes

When to Use Catalogue API

Use the Catalogue API when you need:

  • Deterministic exports - Payload must reflect exact current state
  • Path-based reads - You know the exact path to the item
  • Strong consistency - Cannot tolerate async delays

For search, filtering, and faceting, use the Discovery API instead.

Query Structure

Basic Path Query

{
catalogue(language: "en", path: "/shop/plants") {
name
path
type
}
}

Product Query with Variants

{
catalogue(language: "en", path: "/shop/furniture/dining-chair") {
name
... on Product {
variants {
sku
name
price
stock
attributes {
attribute
value
}
}
}
}
}

Folder with Children

{
catalogue(language: "en", path: "/shop/plants") {
name
... on Folder {
children {
name
path
type
}
}
}
}

Document Query

{
catalogue(language: "en", path: "/blog/welcome-post") {
name
... on Document {
components {
id
name
content {
... on RichTextContent {
html
}
}
}
}
}
}

cURL Example

Terminal window
curl \
-X POST \
-H "Content-Type: application/json" \
--data '{ "query": "{ catalogue(language: \"en\", path: \"/shop/plants\") { name } }" }' \
https://api.crystallize.com/furniture/catalogue

Limitations

The Catalogue API does not support:

  • Full-text search
  • Filtering
  • Faceting
  • Sorting across multiple items

Use the Discovery API for these capabilities.

Core API Queries Reference

The Core API provides comprehensive read access to items, customers, orders, shapes, and tenant configuration. Use this for admin interfaces, reporting, and complex filtering needs.

Table of Contents

Base URL

https://api.crystallize.com/@{tenant-identifier}

Note the @ prefix before the tenant identifier.

Authentication

Authentication is required. Use access tokens generated in the Crystallize App:

Terminal window
curl -X POST 'https://api.crystallize.com/@your-tenant' \
-H 'Content-Type: application/json' \
-H 'X-Crystallize-Access-Token-Id: YOUR_TOKEN_ID' \
-H 'X-Crystallize-Access-Token-Secret: YOUR_TOKEN_SECRET' \
-d '{"query": "..."}'

Core API vs Other APIs

Use Core API for:

  • Admin interfaces and dashboards
  • Complex order filtering (by customer, SKU, payment provider)
  • Reading shape/piece definitions
  • Customer management
  • Bulk data access

Use Discovery/Catalogue API for:

  • Storefront product listings
  • Search and filtering
  • Public content access

Item Queries

Get Item by ID

query GetItem {
item(id: "item-id", language: "en") {
... on Product {
id
name
shapeIdentifier
tree {
path
parentId
}
components {
componentId
content
}
defaultVariant {
sku
name
price
stock
images {
url
altText
}
}
variants {
sku
name
price
stock
}
}
... on Document {
id
name
shapeIdentifier
components {
componentId
content
}
}
... on Folder {
id
name
shapeIdentifier
children {
id
name
type
}
}
... on ItemNotFoundError {
errorName
message
}
}
}

List Items with Pagination

query ListItems {
items(
language: "en"
first: 20
after: "cursor"
filter: {
shapeIdentifiers: ["product", "bundle"]
# path: { prefix: "/shop" }
# includeDescendants: true
}
sort: { field: updatedAt, direction: desc }
) {
edges {
cursor
node {
id
name
type
shapeIdentifier
createdAt
updatedAt
... on Product {
defaultVariant {
sku
price
stock
}
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
}
}

Get Item Component

Read a specific component from an item:

query GetItemComponent {
item(id: "item-id", language: "en") {
... on Item {
id
component(id: "description") {
componentId
content
}
}
}
}

Check Identifier Availability

query CheckIdentifier {
isIdentifierAvailable(tenantId: "tenant-id", identifier: "new-product-slug") {
... on IdentifierAvailability {
available
}
}
}

Customer Queries

Get Customer by Identifier

query GetCustomer {
customer(identifier: "customer@example.com") {
... on Customer {
id
identifier
tenantId
... on IndividualCustomer {
firstName
lastName
email
phone
}
... on OrganizationCustomer {
name
taxId
organizationNumber
}
addresses {
type
firstName
lastName
street
street2
city
state
postalCode
country
phone
email
}
meta {
key
value
}
}
... on CustomerNotFoundError {
errorName
message
}
}
}

List Customers

query ListCustomers {
customers(
tenantId: "tenant-id"
first: 20
filter: {
email: { contains: "@example.com" }
# customerType: individual
}
) {
edges {
node {
id
identifier
... on IndividualCustomer {
firstName
lastName
email
}
... on OrganizationCustomer {
name
}
}
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}

Get Customer Groups

query GetCustomerGroup {
customerGroup(id: "group-id") {
... on CustomerGroup {
id
name
customerIdentifiers
}
}
}
query ListCustomerGroups {
customerGroups(tenantId: "tenant-id", first: 20) {
edges {
node {
id
name
customerIdentifiers
}
}
}
}

Order Queries

Get Order by ID

query GetOrder {
order(id: "order-id") {
... on Order {
id
createdAt
updatedAt
customer {
identifier
... on IndividualCustomer {
firstName
lastName
email
}
}
cart {
sku
name
quantity
price {
net
gross
currency
}
imageUrl
}
total {
net
gross
currency
}
payment {
provider
... on StripePayment {
paymentIntentId
}
}
meta {
key
value
}
}
... on OrderNotFoundError {
message
}
}
}

List Orders with Filtering

The Core API supports advanced order filtering by customer, SKU, payment provider, and metadata:

query ListOrders {
orders(
tenantId: "tenant-id"
first: 20
filter: {
customerIdentifier: "customer@example.com"
# sku: "PROD-123"
# paymentProvider: "stripe"
# meta: [{ key: "source", value: "mobile-app" }]
}
sort: { field: createdAt, direction: desc }
) {
edges {
cursor
node {
id
createdAt
total {
gross
currency
}
customer {
identifier
}
cart {
sku
name
quantity
price {
gross
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}

Filter Options:

  • customerIdentifier - Filter by customer email/identifier
  • sku - Filter orders containing specific SKU
  • paymentProvider - Filter by payment method (stripe, klarna, etc.)
  • meta - Filter by metadata key/value pairs
  • createdAt - Date range filtering

Shape and Piece Queries

Get Shape Definition

query GetShape {
shape(identifier: "product") {
... on Shape {
identifier
name
type
components {
id
name
type
config
}
variantComponents {
id
name
type
config
}
}
}
}

List All Shapes

query ListShapes {
shapes(tenantId: "tenant-id") {
identifier
name
type
itemCount
}
}

Get Piece Definition

query GetPiece {
piece(identifier: "seo") {
... on Piece {
identifier
name
components {
id
name
type
config
}
}
}
}

List All Pieces

query ListPieces {
pieces(tenantId: "tenant-id", first: 100) {
edges {
node {
identifier
name
components {
id
name
type
}
}
}
}
}

Flow Queries

Get Flow

query GetFlow {
flow(id: "flow-id") {
... on Flow {
id
name
stages {
id
name
position
}
}
}
}

Get Flow Content

List items in a flow stage:

query GetFlowContent {
flowContent(flowId: "flow-id", stageId: "stage-id", language: "en", first: 20) {
edges {
node {
item {
id
name
type
}
assignedTo {
id
email
}
dueDate
}
}
}
}

Archive Queries

Get Archived Version

query GetArchive {
archive(id: "archive-id") {
... on ArchivedItemVersion {
id
number
name
archivedAt
archivedBy {
email
}
item {
id
name
}
}
}
}

List Archived Versions

query ListArchives {
archives(itemId: "item-id", language: "en", first: 10, sort: { field: number, direction: desc }) {
edges {
node {
id
number
name
archivedAt
archivedBy {
email
}
}
}
}
}

Bulk Task Queries

Get Bulk Task Status

query GetBulkTask {
bulkTask(id: "task-id") {
... on BulkTask {
id
type
status
createdAt
startedAt
stoppedAt
info
actor {
email
}
}
}
}

List Bulk Tasks

query ListBulkTasks {
bulkTasks(tenantId: "tenant-id", first: 20, filter: { status: running }) {
edges {
node {
id
type
status
createdAt
}
}
}
}

File and Image Queries

Get Image

query GetImage {
image(key: "image-key") {
... on Image {
key
url
altText
caption
variants {
url
width
height
}
}
}
}

List Images

query ListImages {
images(tenantId: "tenant-id", first: 20, filter: { path: { prefix: "/products/" } }) {
edges {
node {
key
url
altText
createdAt
}
}
}
}

Error Handling

The Core API uses union return types. Always handle potential errors:

query {
item(id: "item-id", language: "en") {
... on Product {
id
name
}
... on ItemNotFoundError {
errorName
message
}
... on UnauthorizedError {
errorName
message
}
}
}

Common error types:

  • UnauthorizedError - Invalid or missing credentials
  • ItemNotFoundError - Item doesn’t exist
  • CustomerNotFoundError - Customer doesn’t exist
  • OrderNotFoundError - Order doesn’t exist
  • BasicError - Generic error

TypeScript Types

Use generated types for type safety:

import { Query, GetItemQuery, GetCustomerQuery, ListOrdersQuery } from "@/generated/core";

Types are generated from the Core API schema via GraphQL Code Generator.

Discovery API Reference

The Discovery API is the primary API for powering storefronts with product information and marketing content. It is a read-only API optimized for high performance.

Base URL

https://api.crystallize.com/{tenant-identifier}/discovery

Replace {tenant-identifier} with your tenant name.

Authentication

By default, the Discovery API is open. If you configure restricted access for your Catalogue API, you need to provide authentication:

  • Static token via header
  • Access tokens for programmatic access

Important: Always secure your API with authentication in production environments.

Key Features

Semantic Schema

The Discovery API follows the structure of your shapes and components. Field names in queries match your shape definitions, making the API intuitive to use.

One query model for both browsing categories and searching products. This simplifies frontend development.

Filtering and Faceting

Filter by any attribute, component, or price range. Get facet counts for building filter UIs.

Query Structure

{
search(language: en, filters: { type_in: [product] }, pagination: { limit: 20, after: "XXXX" }) {
summary {
totalHits
facets
endCursor: endToken
}
hits {
id
name
path
}
}
}

Filtering by Shape

{
search(language: en, filters: { shape: { equals: "sneaker" } }) {
hits {
name
path
}
}
}

Price Range Filter

{
search(language: en, filters: { price_sales: { range: { gte: 20, lte: 20 } } }) {
hits {
name
path
}
}
}
{
search(language: en, term: "plop") {
hits {
name
path
}
}
}

Browse Queries

The browse API provides shape-typed access — each shape becomes its own query type with all component fields available directly. This is the recommended approach for storefronts.

Browse by Shape

{
browse {
product(language: en, pagination: { limit: 25 }) {
hits {
name
path
defaultVariant {
sku
defaultPrice
firstImage {
url
}
}
}
}
}
}

Browse by Path (Folder Listing)

{
browse {
category(language: en, path: "/shop/*") {
hits {
name
path
children(language: en) {
hits {
... on product {
name
path
defaultVariant {
sku
defaultPrice
}
}
}
}
}
}
}
}
  • Use path: "/shop/*" for direct children (wildcard)
  • Use path: "/shop/exact-item" for a specific item
  • Use aliases to combine multiple browse queries in one request

Combined Query with Aliases

{
folder: browse {
category(language: en, path: "/shop") {
hits {
name
path
}
}
}
products: browse {
product(language: en, path: "/shop/*") {
hits {
name
path
defaultVariant {
sku
defaultPrice
}
}
}
}
}

Pagination

Use paginationToken (returned as endCursor in summary) for efficient, consistent pagination:

{
browse {
product(language: en, pagination: { limit: 25, after: "CURSOR_FROM_PREVIOUS_PAGE" }) {
summary {
totalHits
hasMoreHits
endCursor
}
hits {
name
path
}
}
}
}

Flow:

  1. First request: omit after (or set to null)
  2. Use summary.endCursor as the after value for the next page
  3. Stop when summary.hasMoreHits is false

Note: skip-based pagination is deprecated. Use cursor-based pagination (after) for all new implementations. skip becomes increasingly expensive on large result sets.

The same cursor pattern works with search:

{
search(language: en, pagination: { limit: 20, after: "CURSOR" }) {
summary {
totalHits
hasMoreHits
endCursor
}
hits {
name
path
}
}
}

Faceting

Get counts for filter values:

{
search(language: en, term: "blue", facets: { shape: { limit: 5 } }) {
summary {
facets
}
hits {
name
path
}
}
}

Async Updates

The Discovery API is asynchronously updated from your published data and therefore eventually consistent:

  • Typical delay: under 1 second
  • Large imports may take longer to surface

For cases requiring exact current state, use the Catalogue API instead.

Shop API Order Queries Reference

The Shop API /order scope provides queries for retrieving orders. This is a separate endpoint from the /cart scope.

Base URL

https://shop-api.crystallize.com/{tenant-identifier}/order

Important: Order queries use the /order endpoint, NOT /cart.

Authentication

Requires JWT token with the order scope.

Authorization: Bearer YOUR_JWT_TOKEN

See the Shop API Queries Reference for token generation details.

Get a Single Order

Retrieve an order by its Shop API UUID.

query GetOrder($id: UUID!) {
order(id: $id) {
id
coreId
reference
type
paymentStatus
createdAt
updatedAt
additionalInformation
customer {
identifier
firstName
lastName
email
phone
companyName
type
addresses {
type
street
city
postalCode
country
}
}
items {
name
sku
productId
quantity
type
imageUrl
price {
gross
net
taxAmount
taxPercent
currency
}
subTotal {
gross
net
taxAmount
currency
}
}
total {
gross
net
taxAmount
taxPercent
currency
discounts {
amount
}
taxBreakdown {
taxRate
amount
}
}
payments {
provider
transactionId
amount
method
createdAt
}
pipelines {
identifier
stage
}
appliedPromotions {
identifier
name
}
meta
metaProperty(key: "fulfillment_status")
}
}

Variables:

{
"id": "order-uuid-here"
}

Get Orders by Customer

Retrieve orders for a specific customer with pagination.

query GetCustomerOrders($customerIdentifier: String!, $limit: Int, $skip: Int) {
orders(customerIdentifier: $customerIdentifier, limit: $limit, skip: $skip) {
id
coreId
type
paymentStatus
createdAt
total {
gross
net
currency
}
items {
name
sku
quantity
price {
gross
net
}
}
pipelines {
identifier
stage
}
}
}

Variables:

{
"customerIdentifier": "john@example.com",
"limit": 10,
"skip": 0
}

Order Response Types

Order

FieldTypeDescription
idUUID!Shop API order ID
coreIdStringCore API order ID (for PIM operations)
referenceStringOrder reference number
typeOrderTypestandard, draft, creditNote, etc.
additionalInformationStringFree-text additional info
stockLocationIdentifierStringStock location identifier
relatedOrderIds[String]IDs of related orders
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp
contextHashMapOrder context (pricing, language)
customerCustomerCustomer details
items[Item]Order line items
totalTotalPrice!Order totals
paymentStatusOrderPaymentStatuspaid, unpaid, refunded, etc.
payments[Payment]Payment records
pipelines[Pipeline]Pipeline/workflow stage assignments
appliedPromotions[PromotionSlim!]Applied promotion details
metaHashMapAll metadata as key-value map
metaProperty(key)StringSingle metadata value by key

Item (Order Line Item)

FieldTypeDescription
nameString!Item display name
skuStringProduct SKU
productIdStringCrystallize product ID
quantityPositiveIntQuantity ordered
groupStringItem grouping
typeCartItemTypestandard, shipping, fee, etc.
imageUrlStringItem image URL
priceItemPrice!Unit price
subTotalItemPrice!Line total (price × quantity)
subscriptionContractIdStringSubscription contract reference
subscriptionSubscriptionSubscription details
metaHashMapItem-level metadata

ItemPrice / TotalPrice

FieldTypeDescription
grossFloat!Price including tax
netFloat!Price excluding tax
taxAmountFloat!Tax amount
taxPercentFloat!Tax percentage
currencyString!Currency code
discounts[Discount!]Applied discounts

TotalPrice also includes:

FieldTypeDescription
taxBreakdown[TaxBreakdownEntry!]Tax by rate

Customer

FieldTypeDescription
isGuestBoolean!Whether customer is guest
identifierStringUnique customer ID
firstNameStringFirst name
lastNameStringLast name
middleNameStringMiddle name
emailStringEmail address
phoneStringPhone number
birthDateDateTimeDate of birth
companyNameStringCompany name
taxNumberStringTax/VAT number
typeCustomerTypeindividual or organization
externalReferenceStringExternal reference
externalReferencesHashMapMultiple external refs
addresses[Address]Customer addresses
metaHashMapCustomer metadata

Payment

FieldTypeDescription
providerStringPayment provider (e.g., “stripe”)
transactionIdStringTransaction reference
amountFloatPayment amount
methodStringPayment method (e.g., “card”)
createdAtStringPayment timestamp
metaHashMapPayment metadata

Pipeline

FieldTypeDescription
identifierStringPipeline identifier
stageStringCurrent stage

Shop API Queries Reference

The Shop API handles cart and checkout operations at the edge for low-latency commerce experiences.

Base URL

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

The endpoint also serves as a GraphQL playground for documentation.

Authentication

The Shop API requires a JWT token. Obtain tokens from:

POST https://shop-api.crystallize.com/{tenant-identifier}/auth/token

Getting a Token

Terminal window
curl -X POST 'https://shop-api.crystallize.com/YOUR_TENANT/auth/token' \
-H 'Accept: application/json' \
-H 'x-crystallize-access-token-id: YOUR_ACCESS_TOKEN_ID' \
-H 'x-crystallize-access-token-secret: YOUR_ACCESS_TOKEN_SECRET' \
-H 'Content-Type: application/json' \
-d '{"scopes":["cart","cart:admin","order"],"expiresIn":18000}'

Token Scopes

ScopeDescription
cartManage a single cart
cart:adminManage multiple carts
orderCreate and manage orders (/order endpoint)
usageAccess usage/metrics API
lockAcquire/release locks

Using the Token

Include in request headers:

Authorization: Bearer YOUR_JWT_TOKEN

Cart Queries

Retrieve Cart

query {
cart(id: "cart-id-here") {
id
state
isStale
isExpired
createdAt
updatedAt
items {
sku
name
quantity
managed
origin
images {
url
}
price {
gross
net
taxAmount
}
}
total {
gross
net
taxAmount
}
}
}

Cart as Order Intent

Retrieve cart formatted for order creation:

query {
cartAsOrderIntent(id: "cart-id-here") {
customer {
firstName
lastName
email
}
cart {
sku
name
quantity
price {
gross
net
}
}
total {
gross
net
}
}
}

This format can be pushed directly to the Order API without transformation.

Cart Concepts

Hydration

The process where Shop API fetches and computes data on your behalf to construct or update the cart.

Cart Items

Two types of items can be in a cart:

  1. SKU Items - Items with a SKU that exist in Crystallize
  2. External Items - Items that don’t exist in Crystallize (e.g., shipping)

Managed vs Unmanaged Items

  • Managed (true): Shop API fetches info from Crystallize
  • Managed (false): You provide all item information

SKU items start as managed but become unmanaged if you override properties like pricing.

Expiration

  • You can set cart expiration time
  • Carts without updates for 3+ months are automatically deleted


Crystallize AI