Skip to main content

Managing Products

Introduction

This guide describes how to query and manage products from the Nautical GraphQL API.

Retrieving a list of products

To fetch a product list, you need to run the products query. The products list is a paginated collection.

You can either retrieve a single product or a list of products. You may require a list of products in many situations, for example, when you need to simply display the catalog in your storefront, or to provide a third party service with a list of products available in your store.

Let's take a look at an example query to fetch a list of products:

GraphQL Example
Query Variables
Request Headers
Documentation Explorer
No Schema Available

In this example, we requested the following fields for each product:

  • id: the unique product ID, most operations will require one.
  • name: the name of the product.

The response returns these fields for two products, because of the first: 2 argument in the query:

{
"data": {
"products": {
"edges": [
{
"node": {
"id": "UHJvZHVjdYo0NTU=",
"name": "Orange Juice"
}
},
{
"node": {
"id": "UHJvZHVjdDo2TzQ=",
"name": "Apple Juice"
}
}
]
}
}
}
Show more ↓

Filtering the list of products

You can filter the results returned by the products query using the optional filter argument. The filter argument accepts filter options from the ProductFilterInput.

Some of the filters that are available include:

  • productTypes: ID — filter by a given product type.
  • sellers: ID — filter by a given seller.
  • attributes: AttributeInput — filter products with a given attribute.
  • features: FeatureFilterInput— filter products with a given feature.
  • price: ... — filter by base price:
    • price: {lte: Float}— price lower than or equal to given value.
    • price: {gte: Float}— price greater than or equal to given value.
  • minimalPrice: ... — filter by minimal variant price:
    • minimalPrice: {lte: Float} — price lower than or equal to given value.
    • minimalPrice: {gte: Float} — price greater than or equal to given value.

Searching products

There are two search filters available when querying products:

  • advancedSearch: Targets specific field(s) for faster performance and tailored results.
  • search: Searches across all fields for broad search results with slower performace.

You can use the advancedSearch parameter with the filter argument for advanced filtering by search term when querying products.

The advancedSearch filter accepts two input fields:

FieldDescription
searchTerm (required)A string to search with.
searchFieldsA comma separated list of fields to search across. If no search fields are defined, the filter defaults to searching only by NAME. The fields you can target for search are defined in the ProductSearchFieldEnum.

Here is an example query that returns the first five products with the term "shiny" in the product name, variant name, description, or category name:

query {
products(
first: 5
filter: {
advancedSearch: {
searchTerm: "shiny"
searchFields: [NAME, VARIANT_NAME, DESCRIPTION, CATEGORY_NAME]
}
}
) {
edges {
node {
id
name
description
}
}
}
}
Show more ↓

You can use the basic search filter for a broad-match search results when querying products. The search filter accepts a string input that will be used to search across all product fields.

tip

If you experience performance issues with the basic search filter, try using advancedSearch instead.

Here is an example query that looks for the first five products that mention the term "juice":

{
products(
first: 5
filter: {
search: "juice"
}
)
{
edges {
node {
id
name
description
}
}
}
}

Sorting the list of products

In products you can also sort the results using two sortBy arguments: field and direction.

  • field: the field to use for sorting the results from several predefined choices:
    • DATE: sort products by last update.
    • MINIMAL_PRICE: sort products by minimal variant price.
    • NAME: sort products by name.
    • PRICE: sort products by base price.
    • PUBLICATION_DATE: sort products by publication date.
    • PUBLISHED: sort products by publication status.
    • TYPE: sort products by product type.
  • direction: The direction for sorting items:
    • ASC: sort ascending.
    • DESC: sort descending.

For all of the available fields to sort by, see the ProductOrder API reference.

This example shows how to sort the products list by the minimal variant price, lowest to highest:

{
products(
first: 2
sortBy: { field: MINIMAL_PRICE, direction: ASC }
) {
edges {
node {
name
minimalVariantPrice {
amount
currency
}
}
}
}
}

Viewing product availability

The isAvailable field on the product object contains the availability status of products.

The product isAvailable field is a boolean that is either true or false, based on the following logic calculation:

IfThen
The product is not published or the publication date is in the futurefalse
The product is not available for purchase or the available for purchase date is in the futurefalse
The stock is not available for the country where the request is madefalse
None of the above false conditions are met and at least one inventory quantity is available in the country where the request is made, based on the warehouse shipping zonestrue
Availability by Country

The stock availability by country is determined based on warehouse shipping zones and the requestor's IP address, which infers the country

For example, if the product Apple Juice is missing a warehouse and a shipping zone for the country where the request is made, the isAvailable field will be false. However, once a warehouse and the Americas shipping zone are assigned to the product, the isAvailable will change to true.

Retrieving a single product

To get details about a single product, use the product query, which requires only one input field:

  • id: the unique product ID.

Here is the example query that fetches a single product:

query {
product(id: "UHJvZHVjdDoxMTU=") {
id
name
}
}

For more details about this query, see the product query API reference.

Retrieving product variants

To obtain product variants, query the variants field on the Product type:

{
products(first: 1) {
edges {
node {
id
name
variants {
id
name
}
}
}
}
}

Like products, here we're asking for two fields from each variant:

  • id: the unique variant ID.
  • name: the name of the variant.

The For more details about the fields you can query under the variants field, see the ProductVariant API reference.

Pricing

Use the pricing field of products and variants to obtain pricing information.

Here are the available fields for product pricing:

type ProductPricingInfo {
priceRange: TaxedMoneyRange
priceRangeUndiscounted: TaxedMoneyRange
discount: TaxedMoney
onSale: Boolean
}

And similar fields for product variants:

type VariantPricingInfo {
price: TaxedMoney
priceUndiscounted: TaxedMoney
discount: TaxedMoney
onSale: Boolean
}

The main difference is that products don't have a price point, instead they offer a price range that includes all of their variant prices.

Here are the money types returned by the above:

type TaxedMoneyRange {
# lowest price
start: TaxedMoney
# highest price
stop: TaxedMoney
}

type TaxedMoney {
# before tax
net: Money!
# after tax
gross: Money!

# gross - net
tax: Money!
# repeated for convenience
currency: String!
}

type Money {
amount: Float!
currency: String!
}
Show more ↓

Description

There are three fields that store the product description, as explained in the following table:

FieldUsage
descriptionHtml

HTML-formatted description. You must enclose all text in valid HTML tagging. For example, all paragraphs must be enclosed in a <p> tag.

If you have text outside of a valid HTML tag, users will experience issues with editing that text in the Dashboard text editor.

descriptionJson

(Deprecated) JSON-formatted description. This is the legacy description field and will not be used going forward. This field will be removed by September 2023.

While this field is being deprecated, you can still use it to pass in JSON-formatted descriptions but we strongly suggest you change your workflows to use the new descriptionHtml field. Any values passed to this field will be converted and populated in the descriptionHtml and description fields.

descriptionPlain text description. When you pass a value to descriptionHtml or descriptionJson, the description is converted to plain text and stored in this field.
HTML syntax

The current implementation of descriptionHtml supports the following HTML tags:

  • Divider: <div>
  • Headings: <h1>, <h2>, <h3>
  • Text block: <p>, <blockquote>
  • Text decoration: <strong>, <u>, <i>, <code>
  • Lists: <ul>, <ol>
  • Text align style attribute: style="text-align: { left | center | justify | right }"

Here's an example query that will return all three description fields:

{
product(id: "UHJvZHVjdDo1MQ==") {
id
name
descriptionHtml
descriptionJson
description
}
}

Images

The Product object contains three fields you can query to return images: thumbnail, images, and imageById.

note

When you request a specific size for an image for the first time, the API may take longer to respond as it needs to generate a new image that meets the requested size requirements. Subsequent requests for the same size should be faster.

Thumbnail

Use the thumbnail field while querying products to return the main image for the product in a square format.

Here's an example query that will return the thumbnail, optimized for display at 100×100px:

{
products(first: 1) {
edges {
node {
id
name
thumbnail(size: 100) {
url
alt
}
}
}
}
}

Size argument

Optionally, specify the size argument with the thumbnail field to return an image of a specific size in pixels.

Thumbnail size

The thumbnail image is always a square image. When you request a specific size for the thumbnail image, it will always generate a square image of that size.

Sub-fields

thumbnail supports the following sub-fields:

  • url: the image's URL.
  • alt: the alternative text to include when displaying the image.

All images

Use the images field while querying products to return all associated product images.

Here's an example query that will return all images, with the largest dimension set to 100px for each:

{
products(first: 1) {
edges {
node {
id
name
images {
url(size: 100)
alt
id
}
}
}
}
}

Sub-fields

images supports the following sub-fields:

  • url: the image's URL.
    Size Argument:
    • Optionally, specify the size argument with the url field to return images in a specific size in pixels.
      Image size

      When you request images of a specific size through the url field, the API generates a new image if the size doesn't match the original image dimensions. The image's largest dimension (width or height) is resized to match the specified size in pixels, while maintaining the original aspect ratio.

      • For a portrait-oriented image with a height is greater than its width, the new image's width will be equal to the requested size, and its height will be resized to maintain the aspect ratio.
      • For a landscape-oriented image with a width is greater than its height, the new image's height will be equal to the requested size, and its width will be resized to maintain the aspect ratio.
  • alt: the alternative text to include when displaying the image.
  • id: the ID of the image

Specific image

Use the imageById field while querying a product to return an image matching a specified ID.

Here's an example query that returns a specific image on a given product with the largest dimension set to 100px:

{
product(id: "UHJvZHVjdDo0NTU=") {
id
name
imageById(id: "UHJvZHVjdEltYWdlOjExODg=") {
url(size: 100)
alt
}
}
}

ID argument

The id argument is required to specify the ID of the target image.

Sub-fields

imageById supports the following sub-fields:

  • url: the image's URL.
    Size Argument:
    • Optionally, specify the size argument with the url field to return images in a specific size in pixels.
      Image size

      When you request images of a specific size through the url field, the API generates a new image if the size doesn't match the original image dimensions. The image's largest dimension (width or height) is resized to match the specified size in pixels, while maintaining the original aspect ratio.

      • For a portrait-oriented image with a height greater than its width, the new image's width will be equal to the requested size, and its height will be resized to maintain the aspect ratio.
      • For a landscape-oriented image with a width greater than its height, the new image's height will be equal to the requested size, and its width will be resized to maintain the aspect ratio.
  • alt: the alternative text to include when displaying the image.

Example query

Here's a more complex GraphQL query that combines all of the above information:

{
products(first: 2, sortBy: { field: NAME }) {
edges {
node {
id
name
pricing {
priceRange {
start {
gross {
amount
currency
}
}
}
discount {
gross {
amount
currency
}
}
priceRangeUndiscounted {
start {
gross {
amount
currency
}
}
}
}
thumbnail {
url
}
}
}
}
}
Show more ↓

Create a Product

Here is an example of creating a product:

mutation {
productCreate(
input: {
name: "Thingamajig"
description: "This product is a thing"
productType: "UHJvZHVjdFR5cGU6MTg="
seller: "U2VsbGVyOjI="
basePrice: 99.99
seo: { title: "My seo title", description: "My seo description" }
}
) {
product {
id
name
description
seoTitle
seoDescription
status
subStatus
productType {
id
name
}
seller {
id
companyName
}
}
productErrors {
field
code
message
}
}
}
Show more ↓

Create Product

In order to assign the product the desired product type and to the desired seller, you'll need the base 64 encoded IDs of each, respectively. You can find these IDs by querying product types and sellers.

Update a Product

In order to update a Product, you'll need its ID. In our example, it is "UHJvZHVjdDoxMDE=".

Now let's say we wanted to update the product to make its isPublished field true (it's false by default on product creation). In order to publish the product, it needs to be assigned a product type (which we already did) and it also needs to be assigned a category (which we haven't done yet). In order to assign the product a category, we'll need the category's ID.

Let's use the category ID of "Q2F0ZWdvcnk6MjM=".

Here is an example of updating a product, in this case updating it with a new category and then publishing it:

{
productUpdate(
id: "UHJvZHVjdDoxMDE="
input: { isPublished: true, category: "Q2F0ZWdvcnk6MjM=" }
) {
product {
id
name
isPublished
category {
id
name
}
}
productErrors {
field
message
code
}
}
}
Show more ↓

Update Product

Was this page helpful?