The cart is where you manage the checkout process for your customers. It holds products, quantities, and customer information before an order is placed.
The Shop API requires a valid JWT token. To obtain one, send a POST request to https://shop-api.crystallize.com/your-tenant-identifier/auth/token.
The POST request must include a JSON body with the scopes you want the token to grant access to. Each scope maps to a Shop API domain, and the matching :admin variant grants administrative access to that domain (managing and querying many resources rather than a single one):
In order to issue a JWT token, the Shop API needs a way to authenticate against the Crystallize PIM API.
curl -X POST 'https://shop-api.crystallize.com/YOUR_TENANT_IDENTIFIER/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"],"expiresIn":18000}'
curl -X POST 'https://shop-api.crystallize.com/YOUR_TENANT_IDENTIFIER/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"],"expiresIn":18000}'That returns a JWT token valid for 5 hours (the expiresIn value, in seconds) for yourtenant on the cart and cart:admin scopes. If you omit expiresIn, the token defaults to 24 hours.
Once you have a token, pass it as a header in every Shop API request: Authorization: Bearer THE_TOKEN.
Each domain is exposed under its own base URL, scoped to your tenant — for example https://shop-api.crystallize.com/your-tenant-identifier/cart. A token only grants access to the endpoints that match its scopes (a cart token cannot call the order endpoint). See the overview below for the full list of domains.
It is not recommended to fetch the token from the frontend, as credentials to the PIM API must remain secret.
The JWT token of the Shop API does not provide any authentication or authorization on the PIM API.
You control the expiration time of the Shop API JWT token. You should find a way in your process to rotate that token to handle revocation (if necessary).
If you have secured your Catalogue API, you need to provide the x-crystallize-static-auth-token or the couple x-crystallize-access-token-id/x-crystallize-access-token-secret in each subsequent request to the Shop API on top of the Shop API token.
The Shop API token is used to check your permissions to use the Shop API. Those additional headers grant the Shop API permission to access the other APIs on the other token's behalf.
The Shop API is organized into domains, each exposed as its own GraphQL endpoint under your tenant identifier. Opening an endpoint in a browser loads the GraphQL playground, which documents every available query and mutation; the same URL also accepts your GraphQL requests.
The GraphQL playground serves as documentation for each domain, and we've put as much information there as we could.
Locking is a mechanism for managing access to shared resources in concurrent situations, or for ensuring that certain operations are atomic. In a multi-server (node) situation, you would need some way of storing the locks' states. The Shop API provides this for you.
Acquiring a lock: This operation is used to obtain a lock on a resource. If the lock is available (i.e. not held by another process), the lock store grants the lock to the requester and marks the resource as locked. If the lock is not available, the requester can either be blocked until the lock becomes available or fail immediately with an indication that the lock could not be acquired.
Release (or Unlock): This operation is used to release a previously acquired lock, making the resource available for locking by others. After a lock is released, any other process waiting for the lock can acquire it.
The lock endpoint https://shop-api.crystallize.com/your-tenant-identifier/lock gives you 2 mutations that return either `true` or `false` based on the action. The acquire mutation also accepts a time to live (TTL) if you want to auto-release the lock, the default being 60 seconds.
The Shop API keeps its orders, customers, and subscription contracts in sync with the Crystallize Core API, and can stream changes to your own services in real time.
The Cart Admin domain exposes a Server-Sent Events (SSE) channel at https://shop-api.crystallize.com/your-tenant-identifier/cart/admin/channel. Subscribe to it to receive a live stream of changes as they happen — useful for building admin dashboards or reacting to buyer activity without polling.
Orders, customers, and subscription contracts are synchronized in both directions with the Core API:
Carts, orders, customers, and subscription contracts can carry arbitrary metadata as key/value pairs. When you set metadata, you control how it is applied with a merge flag: with merge enabled (the default), the new keys are merged into the existing metadata; with merge disabled, the new set replaces the existing metadata entirely.
The Shop API is multilingual and multi-currency. You provide a language and a currency in the context of each cart, order, or subscription contract, and localized content (such as product and variant names) is fetched in that language. Both default to language en and currency eur. Currency is used for reference and display and does not affect calculations — pricing is driven by the selected price variant.
The Shop API does not track stock itself; stock and availability are delegated to the Catalogue API. Provide a stock location where relevant, and query availability through the Catalogue API.
You can inspect the exact shape of the API's core structures at https://shop-api.crystallize.com/json-schema/:type. The supported types are cart, cart-input, promotion, and promotions. Each returns a JSON Schema you can use for validation or code generation.