Marketplaces / WooCommerce Technical Sccope / WooCommerce Product Management / WooCommerce Get Products

WooCommerce Get Products

Version Date Created / Updated Notes
v1.0 ??/05/2025 Hristiyan Georgiev Initial version

We want to be able to use the customer’s store and existing products in order to download & store them in MC Pro.

There are two separate calls for getting products and then getting the product’s variations. We will have to handle both. We can either incorporate them into one cron or build two separate crons. What we have to do is first get the main product ID and then use this ID to query it’s variations. It is up to the devs to decide how to handle this.

All triggers, validations, etc. are as per the abstraction - Get Products General Requirements

Get Product

API Call : GET /wp-json/wc/v3/products?status=publish

API Docs : https://woocommerce.github.io/woocommerce-rest-api-docs/?shell#list-all-products

We pick the status param from Channel WooCommerce > Product Status for Get Products

There is a possibility for pagination so we need to be able to handle this thorugh the page and per_page params. Default per_page is 10 but we want to increase it to 50.

Example Response :

[
    {
        "id": 74,
        "name": "Hoodie with stripes",
        "slug": "hoodie-with-stripes-2",
        "permalink": "https://sociable-sable-b1ae91.instawp.xyz/product/hoodie-with-stripes-2/",
        "date_created": "2025-05-21T13:37:50",
        "date_created_gmt": "2025-05-21T13:37:50",
        "date_modified": "2025-05-23T08:21:23",
        "date_modified_gmt": "2025-05-23T08:21:23",
        "type": "variable",
        "status": "publish",
        "featured": false,
        "catalog_visibility": "visible",
        "description": "<p>WEweweqweqweqweqweqweqweqw</p>\n",
        "short_description": "<p>Test testov testovak</p>\n",
        "sku": "321321",
        "price": "125",
        "regular_price": "",
        "sale_price": "",
        "date_on_sale_from": null,
        "date_on_sale_from_gmt": null,
        "date_on_sale_to": null,
        "date_on_sale_to_gmt": null,
        "on_sale": true,
        "purchasable": true,
        "total_sales": 0,
        "virtual": false,
        "downloadable": false,
        "downloads": [],
        "download_limit": -1,
        "download_expiry": -1,
        "external_url": "",
        "button_text": "",
        "tax_status": "taxable",
        "tax_class": "",
        "manage_stock": true,
        "stock_quantity": 20,
        "backorders": "no",
        "backorders_allowed": false,
        "backordered": false,
        "low_stock_amount": null,
        "sold_individually": false,
        "weight": "150",
        "dimensions": {
            "length": "10",
            "width": "20",
            "height": "30"
        },
        "shipping_required": true,
        "shipping_taxable": true,
        "shipping_class": "",
        "shipping_class_id": 0,
        "reviews_allowed": true,
        "average_rating": "0.00",
        "rating_count": 0,
        "upsell_ids": [],
        "cross_sell_ids": [],
        "parent_id": 0,
        "purchase_note": "",
        "categories": [
            {
                "id": 21,
                "name": "Hoodies",
                "slug": "hoodies"
            },
            {
                "id": 38,
                "name": "Bacho",
                "slug": "bacho"
            },
            {
                "id": 36,
                "name": "Gacho",
                "slug": "gacho"
            }
        ],
        "tags": [
            {
                "id": 20,
                "name": "cool_product",
                "slug": "cool_product"
            },
            {
                "id": 22,
                "name": "mamka ti",
                "slug": "mamka-ti"
            }
        ],
        "images": [
            {
                "id": 80,
                "date_created": "2025-05-21T14:55:08",
                "date_created_gmt": "2025-05-21T14:55:08",
                "date_modified": "2025-05-21T14:55:08",
                "date_modified_gmt": "2025-05-21T14:55:08",
                "src": "https://sociable-sable-b1ae91.instawp.xyz/wp-content/uploads/2025/05/lion-2071739_1280.jpg",
                "name": "lion-2071739_1280",
                "alt": ""
            },
            {
                "id": 81,
                "date_created": "2025-05-21T14:56:28",
                "date_created_gmt": "2025-05-21T14:56:28",
                "date_modified": "2025-05-21T14:56:28",
                "date_modified_gmt": "2025-05-21T14:56:28",
                "src": "https://sociable-sable-b1ae91.instawp.xyz/wp-content/uploads/2025/05/nature-13298_1280.jpg",
                "name": "nature-13298_1280",
                "alt": ""
            }
        ],
        "attributes": [
            {
                "id": 1,
                "name": "Size",
                "slug": "pa_size",
                "position": 0,
                "visible": true,
                "variation": true,
                "options": [
                    "L",
                    "M",
                    "S"
                ]
            }
        ],
        "default_attributes": [
            {
                "id": 21,
                "name": "Color",
                "option": "black"
            }
        ],
        "variations": [
            77,
            78,
            79
        ],
        "grouped_products": [],
        "menu_order": 0,
        "price_html": "<span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#36;</span>125.00</bdi></span> &ndash; <span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#36;</span>140.00</bdi></span>",
        "related_ids": [],
        "meta_data": [
            {
                "id": 146,
                "key": "_children",
                "value": []
            }
        ],
        "stock_status": "instock",
        "has_options": true,
        "post_password": "",
        "global_unique_id": "",
        "brands": [
        {
                "id": 24,
                "name": "Guma",
                "slug": "guma"
            }
        ],
        "_links": {
            "self": [
                {
                    "href": "https://sociable-sable-b1ae91.instawp.xyz/wp-json/wc/v3/products/74",
                    "targetHints": {
                        "allow": [
                            "GET",
                            "POST",
                            "PUT",
                            "PATCH",
                            "DELETE"
                        ]
                    }
                }
            ],
            "collection": [
                {
                    "href": "https://sociable-sable-b1ae91.instawp.xyz/wp-json/wc/v3/products"
                }
            ]
        }
    }
]

Response Mapping :

WooCommerce Field MCPro Field Notes
id Listing > Channel Item ID
name Product> Product Title AND
Listing > Listing Title
slug N/A
permalink N/A
date_created N/A
date_created_gmt N/A
date_modified N/A
date_modified_gmt N/A
type Here we have 4 possibilities :

variable, simple, grouped and external. We can implement a logic : -If we have “variable” in this field, we also store the id into Product > Product Variation Group . This way we will know that the product has variations and we need to perform the GET variants call. -If we have “simple” this means it is a single product and there are no variations. If we have “grouped” then this is a bundle item. In this case we want to store the main item with Product > Is Bundle = Yes, and then check the grouped_products > related_ids for the bundle components. When we have the IDs we then save the products as bundle components of this product. -If we have external this means the product is dropshipped and we won’t cover this at the moment. | | status | | | | Listing > Product Status | Options: draft, pending, private and publish.

  • If we receive “draft” we set the product status to Product not created -If we receive “pending” we set status to Awaiting Creation -If we receive “publish” we set product status to Product Published -If we receive private we set product status to “Awaiting Creation” | | featured | | | | N/A | | | catalog_visibility | | | | N/A | | | description | | | | Listing > Description | | | short_description | | | | Listing WooCommerce > Short Description | New field! WooCommerce allows for short descriptions which are displayed on the item separately from the main description. We want to have a logic and if the description field above is empty, we want to store this into Listing > Description instead. | | sku | | | | Product > SKU | | | price | | | | N/A | If the product is variant or grouped here will be displayed the lowest price in the variation or group. If both of the below prices are empty, we want to store this as Listing > Price, in all other cases we don’t map it. | | regular_price | | | | Listing > RRP | We need a logic and if sale_price is empty, we import the regular_price into Listing > Price. If the product is variant or grouped, this will be empty. | | sale_price | | | | Listing > Price | | | date_on_sale_from | | | | Listing WooCommerce > Promotion Date Start | New field! It will be in a format of 2025-05-22T11:49:53 we need to convert it to unix timestamp | | date_on_sale_from_gmt | | | | N/A | | | date_on_sale_to | | | | Listing WooCommerce > Promotion Date End | New field! It will be in a format of 2025-05-22T11:49:53 we need to convert it to unix timestamp | | date_on_sale_to_gmt | | | | N/A | | | on_sale | | | | N/A | | | purchasable | | | | N/A | | | total_sales | | | | N/A | | | virtual | | | | N/A | | | downloadable | | | | N/A | | | downloads | | | | N/A | | | download_limit | | | | N/A | | | download_expiry | | | | N/A | | | external_url | | | | N/A | | | button_text | | | | N/A | | | tax_status | | | | N/A | | | tax_class | | | | N/A | | | manage_stock | | | | N/A | | | stock_quantity | | | | Listing > Quantity | | | backorders | | | | N/A | | | backorders_allowed | | | | N/A | | | backordered | | | | N/A | | | low_stock_amount | | | | N/A | | | sold_individually | | | | N/A | | | weight | | | | Product > Weight | We need a logic based on the Channel > Country : -If it is United States, this field will be in lbs so we need to convert it to grams -If it is any other country, we import it as it is without converting. | | dimensions | | | | | | | | length | | | Product > Length | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | | width | | | Product > Width | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | | height | | | Product > Height | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | shipping_required | | | | N/A | | | shipping_taxable | | | | N/A | | | shipping_class | | | | N/A | | | shipping_class_id | | | | N/A | | | reviews_allowed | | | | N/A | | | average_rating | | | | N/A | | | rating_count | | | | N/A | | | upsell_ids | | | | N/A | | | cross_sell_ids | | | | N/A | | | parent_id | | | | N/A | | | purchase_note | | | | N/A | | | categories | | | | | We may have more than one category. Each additional category will be a separate object.In such case we want to store the category with the lowest id into Primary Category ID and the rest we store into a new field in Listing WooCommerce > More Categories which will be a Table field. | | | id | | | N/A | | | | name | | | Listing > Primary Category ID AND Listing WooCommerce > More Categories | Note! We store into Listing WooCommerce only if we have more than 1 category! | | | slug | | | N/A | | | tags | | | | | | | | id | | | N/A | | | | name | | | Listing WooCommerce > Tags | New field! The field should be table type.We may have more than one tag and for each tag we will have separate object. We want to store each tag as separate row . | | | slug | | | | | | images | | | | | | | | id | | | N/A | | | | date_created | | | N/A | | | | date_created_gmt | | | N/A | | | | date_modified | | | N/A | | | | date_modified_gmt | | | N/A | | | | src | | | Listing Image AND More Images | We store them as per the abstraction - Images Handling Additional Explanation Since we don’t know which image is main, we always store the first image in the images object as Listing Image and the rest we store as More Images . We don’t store Main Image from here. If we are storing a variation, we need to make sure that we store these images across all the products in the variation. | | | name | | | N/A | | | | alt | | | N/A | | | attributes | | | | | | | | id | | | | | | | name | | | Listing > Item Specific Name | We only want to map this if we have type = simple, otherwise we skip it | | | slug | | | N/A | | | | position | | | N/A | | | | visible | | | N/A | | | | variation | | | N/A | | | | options | | | Listing > Item Specific Value | We only want to map this if we have type = simple, otherwise we skip it. | | default_attributes | | | | N/A | | | | id | | | | | | | name | | | Listing > Item Specific Name | We only want to map this if we have type = variable or grouped , otherwise we skip it | | | option | | | Listing > Item Specific Value | We only want to map this if we have type = variable or grouped , otherwise we skip it | | variations | | | | | We could use the values in this array for our next call which is Get Variations | | grouped_products | | | | | If we have bundled products, the components ids will be listed in this array. We could use this to identify the product ids that we need to add as components. | | menu_order | | | | N/A | | | price_html | | | | N/A | | | related_ids | | | | N/A | | | meta_data | | | | N/A | | | | id | | | N/A | | | | key | | | N/A | | | | value | | | N/A | | | stock_status | | | | Listing > Listing Status | Possible values : instock, outofstock, onbackorder. We need a logic : -If we receive instock, we store the listing status as “Active” -If we receive outofstock or onbackorder, we store the listing status as “Inactive” | | has_options | | | | N/A | | | post_password | | | | N/A | | | global_unique_id | | | | N/A | | | brands | | | | | | | | id | | | N/A | | | | name | | | Product > Brand AND Listing WooCommerce > More Brands | It is possible that we receive more than 1 brand. Each will be a separate object in brands. In this case we want to store the one wit the lowest id into Product > Brand and the rest we store into Listing WooCommerce > More Brands as a table field | | | slug | | | N/A | | | _links | | | | | | | | self | | | | | | | | href | | N/A | | | | | targetHints | | | | | | | | allow | N/A | | | | collection | | | | | | | | href | | N/A | |

As advised above, we also need to perform another call in order to get the product’s variants.

Get Variants

API Call : GET /wp-json/wc/v3/products/{productId}/variations

API Docs : https://woocommerce.github.io/woocommerce-rest-api-docs/?shell#list-all-product-variations

There is a possibility for pagination so we need to be able to handle this thorugh the page and per_page params. Default per_page is 10 but we want to increase it to 50.

Depending on if we are handling this in one cron or two separate, we either pick the productId from the id in the response from the above call, or if we have a separate cron we pick it from Product > Product Variation Group

Example response :

[
    {
        "id": 79,
        "type": "variation",
        "date_created": "2025-05-21T13:45:04",
        "date_created_gmt": "2025-05-21T13:45:04",
        "date_modified": "2025-05-22T11:49:53",
        "date_modified_gmt": "2025-05-22T11:49:53",
        "description": "<p>Wow Pretty Much Wow Variant 3</p>\n",
        "permalink": "https://sociable-sable-b1ae91.instawp.xyz/product/hoodie-with-stripes-2/?attribute_pa_size=s",
        "sku": "SKU456",
        "global_unique_id": "",
        "price": "129",
        "regular_price": "130",
        "sale_price": "129",
        "date_on_sale_from": null,
        "date_on_sale_from_gmt": null,
        "date_on_sale_to": null,
        "date_on_sale_to_gmt": null,
        "on_sale": true,
        "status": "publish",
        "purchasable": true,
        "virtual": false,
        "downloadable": false,
        "downloads": [],
        "download_limit": -1,
        "download_expiry": -1,
        "tax_status": "taxable",
        "tax_class": "",
        "manage_stock": "parent",
        "stock_quantity": 20,
        "stock_status": "instock",
        "backorders": "no",
        "backorders_allowed": false,
        "backordered": false,
        "low_stock_amount": null,
        "weight": "150",
        "dimensions": {
            "length": "10",
            "width": "20",
            "height": "30"
        },
        "shipping_class": "",
        "shipping_class_id": 0,
        "image": {
            "id": 80,
            "date_created": "2025-05-21T14:55:08",
            "date_created_gmt": "2025-05-21T14:55:08",
            "date_modified": "2025-05-21T14:55:08",
            "date_modified_gmt": "2025-05-21T14:55:08",
            "src": "https://sociable-sable-b1ae91.instawp.xyz/wp-content/uploads/2025/05/lion-2071739_1280.jpg",
            "name": "lion-2071739_1280",
            "alt": ""
        },
        "attributes": [
            {
                "id": 1,
                "name": "Size",
                "slug": "pa_size",
                "option": "S"
            }
        ],
        "menu_order": 3,
        "meta_data": [],
        "name": "S",
        "parent_id": 74,
        "_links": {
            "self": [
                {
                    "href": "https://sociable-sable-b1ae91.instawp.xyz/wp-json/wc/v3/products/74/variations/79",
                    "targetHints": {
                        "allow": [
                            "GET",
                            "POST",
                            "PUT",
                            "PATCH",
                            "DELETE"
                        ]
                    }
                }
            ],
            "collection": [
                {
                    "href": "https://sociable-sable-b1ae91.instawp.xyz/wp-json/wc/v3/products/74/variations"
                }
            ],
            "up": [
                {
                    "href": "https://sociable-sable-b1ae91.instawp.xyz/wp-json/wc/v3/products/74"
                }
            ]
        }
    }
]

Response Mapping :

WooCommerce Field MCPro Field Notes
id Listing WooCommerce > Variant ID New field!
type N/A
date_created N/A
date_created_gmt N/A
date_modified N/A
date_modified_gmt N/A
description Listing > Listing Title
permalink N/A
sku Product > SKU
global_unique_id N/A
price If for any reason regular_price and sale_price are empty, we want to import this into Listing > Price. In all other cases we ignore it.
regular_price Listing > RRP We need a logic and if sale_price is empty, we import the regular_price into Listing > Price.
sale_price Listing > Price
date_on_sale_from N/A
date_on_sale_from_gmt Listing WooCommerce > Promotion Date Start New field!
It will be in a format of 2025-05-22T11:49:53 we need to convert it to unix timestamp
date_on_sale_to N/A
date_on_sale_to_gmt Listing WooCommerce > Promotion Date End New field!
It will be in a format of 2025-05-22T11:49:53 we need to convert it to unix timestamp
on_sale N/A
status Listing > Product Status Options: draft, pending, private and publish.
  • If we receive “draft” we set the product status to Product not created -If we receive “pending” we set status to Awaiting Creation -If we receive “publish” we set product status to Product Published -If we receive private we set product status to “Awaiting Creation” | | purchasable | | | | N/A | | | virtual | | | | N/A | | | downloadable | | | | N/A | | | downloads | | | | N/A | | | download_limit | | | | N/A | | | download_expiry | | | | N/A | | | tax_status | | | | N/A | | | tax_class | | | | N/A | | | manage_stock | | | | N/A | | | stock_quantity | | | | Listing > Quantity | | | stock_status | | | | Listing > Listing Status | Possible values : instock, outofstock, onbackorder. We need a logic : -If we receive instock, we store the listing status as “Active” -If we receive outofstock or onbackorder, we store the listing status as “Inactive” | | backorders | | | | N/A | | | backorders_allowed | | | | N/A | | | backordered | | | | N/A | | | low_stock_amount | | | | N/A | | | weight | | | | Product > Weight | We need a logic based on the Channel > Country : -If it is United States, this field will be in lbs so we need to convert it to grams -If it is any other country, we import it as it is without converting. | | dimensions | | | | | | | | length | | | Product > Length | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | | width | | | Product > Width | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | | height | | | Product > Height | We need a logic based on the Channel > Country : -If it is United States, this field will be in inches so we need convert it to cm -If it is any other country, we import it as it is without converting. | | shipping_class | | | | N/A | | | shipping_class_id | | | | N/A | | | image | | | | | | | | id | | | N/A | | | | date_created | | | N/A | | | | date_created_gmt | | | N/A | | | | date_modified | | | N/A | | | | date_modified_gmt | | | N/A | | | | src | | | Main Image AND More Images | As per the abstraction - Images Handling Additional Explanation In case we have more than one image for the variation, we store the first one as Main Image and the rest as More Images. We need to have a check and if we already have stored the More Images (from the get product call) we don’t want to overwrite them but rather skip them. | | | name | | | N/A | | | | alt | | | N/A | | | attributes | | | | | | | | id | | | N/A | | | | name | | | Listing > Item Specific Name | Since we can’t identify if an attribute is variation or item level, we keep everything as item attribute. | | | slug | | | N/A | | | | option | | | Listing > Item Specific Value | Since we can’t identify if an attribute is variation or item level, we keep everything as item attribute. | | menu_order | | | | N/A | | | meta_data | | | | N/A | | | name | | | | N/A | | | parent_id | | | | Listing > Listing Variation Group | | | _links | | | | | | | | self | | | | | | | | href | | N/A | | | | | targetHints | | | | | | | | allow | N/A | | | | collection | | | | | | | | href | | N/A | | | | up | | | | | | | | href | | N/A | |

Apart from the mapping we will have to set as default also some of the internal fields because we are not receiving them from the marketplace.

MCPro field Default Value
Listing > Dispatch Time Max -1
Listing > Immediate Payment Yes
Listing > VAT -1
Is this article helpful?
0 0 0