Inventory & Products | Products | Product Data | Set Product

set_product API Endpoint (Unified)

This endpoint allows you to create, update, or bulk process multiple products in a single API call via the Public API.

Endpoint and Method

  • Endpoint: https://easycms.fi/public_api/set_product/
  • Method: POST
  • Content-Type: application/json



Authentication

  • Header: Authorization1: {API_TOKEN}
  • Body parameters: username, password, account



Operation Modes

The API automatically detects the operation mode based on the request structure:

  • Single Product Mode: When no products array is provided in the request
  • Bulk Product Mode: When a products array is provided in the request



Request Body Parameters (Single Product Mode)

Parameter Type Required Description
username string Yes API username
password string Yes API password
account string Yes Account domain
pid integer No Product ID - if provided and exists, updates existing product; if provided but doesn't exist, creates new product with specified PID; if not provided, creates new product
cid integer Conditional Category ID - required when creating a new product
bid integer Conditional Brand ID - required when creating a new product
price float Conditional Net price - required when creating a new product, always rounded to 3 decimals
price_gross float Conditional Gross price (including VAT) - alternative to price, net price will be calculated automatically
vatId integer Conditional VAT ID - required when creating a new product. Maps to the vat column in the database.
barcode string Conditional Product barcode - auto-generated if not provided when creating
prdNumber string Conditional Product reference number - auto-generated if not provided when creating
product_name string or object No Product name. Pass as a string for single-language ("My Product") or as a language map ({"en_GB": "Product", "fi_FI": "Tuote"}).
product_desc string or object No Product description. Pass as a string or as a language map. The alias description is also accepted.
prdStatus integer No Product status. 1 = published (default), 0 = unpublished/invisible. The alias status is also accepted.
stock_data array No Stock data for specific locations
products_multi array No Product multi data for different locations/suppliers — per-row pricing, barcodes, scheduled pricing and discount ladder flags (see Products Multi Structure and Set Products Multi)
costs array No Product costs data (flat associative array)
images_add array No Product images to add (base64 or URL). See Image Management.
images_delete array No Array of image IDs (iid values) to delete. See Image Management.
images_set_visible array No Array of visibility changes {iid, visible}. See Image Management.
images_sort array No Ordered array of image IDs (iid values) to reorder. See Image Management.
api_visible_b2c_wp integer No Visibility in B2C WordPress API. 1 = visible (default), 0 = hidden.
api_visible_b2b_app integer No Visibility in B2B Mobile App API. 1 = visible (default), 0 = hidden.
api_visible_inventory_app integer No Visibility in Inventory Manager App API. 1 = visible (default), 0 = hidden.
bottle_deposit_pid int/null No CMS product ID of the bottle deposit product to link. Set to null or omit to clear. A product cannot reference itself as its own deposit. The deposit's price must not exceed the product's effective selling price (price after discount) — attaching a deposit worth more than the product is rejected with BOTTLE_DEPOSIT_EXCEEDS_PRODUCT.
bottle_deposit_included integer No Deposit mode: 1 = the product's price field already INCLUDES the deposit (the stored price stays untouched; order/invoice lines carve price − deposit and add the deposit as its own line). 0 (default) = the deposit is added on top of the price at sale.
is_bundle integer No Bundle flag. Managed automatically by the set_product_bundles endpoint. You can also set it directly, but using the dedicated endpoint is recommended.



Request Body Parameters (Bulk Product Mode)

Parameter Type Required Description
username string Yes API username
password string Yes API password
account string Yes Account domain
products array Yes Array of product objects to create, update, or upsert



Product Object Structure

Each product object follows the same structure for both single and bulk modes:

For UPDATE (pid provided and exists):

  • pid: Product ID to update
  • Any product fields to update (only provided fields will be updated)
  • stock_data: Array of stock modifications
  • products_multi: Array of multi-location price/barcode data
  • costs: Array of product cost data (flat associative array)
  • images_add: Array of images to add (base64 or URL)
  • images_delete: Array of image IDs (iid values) to delete
  • images_set_visible: Array of visibility toggles {iid, visible}
  • images_sort: Ordered array of image IDs to reorder

For CREATE/UPSERT (pid provided but doesn't exist OR pid NOT provided):

  • cid: Category ID (required)
  • bid: Brand ID (required)
  • price OR price_gross: Net price or Gross price (required)
  • vatId: VAT ID (required)
  • barcode: Product barcode (auto-generated if not provided)
  • prdNumber: Reference number (auto-generated if not provided)
  • Other product fields (optional)
  • stock_data: Initial stock data (optional)
  • products_multi: Multi-location data (optional)
  • costs: Product cost data (optional)
  • images_add: Images to add (optional)



Stock Data Structure

{
    "stock_data": [
        {
            "reason": 1,
            "stock": 10.0,
            "location_id": 1,
            "shelf_id": 1,
            "best_before_date": "2026-12-31",
            "coming_to_stock": "2026-03-15"
        }
    ]
}



Products Multi Structure

Each products_multi item accepts the same fields as Set Products Multi: pricing/barcode fields, scheduled pricing fields (stime, etime, sdate, edate, days_list) and — on platform version 3.89+ — the discount ladder flags (discount_lock, ignore_qty_discount, ignore_bxgx, booleans). price is the net sell price (3 decimals); row_num sets the priority order.

{
    "products_multi": [
        {
            "location_id": 1,
            "code": "ABC123",
            "boxcode": "BOX456",
            "supplier_id": 1,
            "pricebuy": 10.00,
            "price": 15.00,
            "discount": 5.0,
            "discount_lock": true,
            "ignore_qty_discount": false,
            "ignore_bxgx": false,
            "stime": "11:00",
            "etime": "14:00",
            "days_list": "mon,tue,wed,thu,fri",
            "row_num": 1
        }
    ]
}



Costs Structure

{
    "costs": {
        "customs_fees": 2.50,
        "transportation_costs": 1.20,
        "transit_insurance": 0.50,
        "handling_fees": 0.30,
        "warehousing": 0.10,
        "handling_labor": 0.20,
        "inventory_write_offs": 0.05,
        "shrinkage": 0.02,
        "administrative_overheads": 0.15,
        "utilities": 0.08,
        "taxes_on_inventory": 0.10,
        "packaging_costs": 0.25,
        "marketing_and_promotion": 0.05,
        "returns_management": 0.10,
        "financial_costs": 0.03
    }
}



Image Management

The API supports full product image management that mirrors the admin panel's media tab. Images are stored in multiple size variants (original, big, small, thumbnail) and are fully compatible with the admin inventory editor.


Image Size Variants

When you upload an image, the API automatically generates the following size variants (matching the admin system):

Variant Prefix Max Dimension Usage
Original (none) Full size Source file
Large big_ 900px Product page, preview
Medium small_ 500px Product cards
Thumbnail thumb_ 180px Product lists, galleries
Mini sthumb_ 50px Tiny thumbnails, icons

All variants are created using the same resizing logic as the admin panel.


Supported Image Formats

Format MIME Type Extension
JPEG image/jpeg .jpg, .jpeg
PNG image/png .png
GIF image/gif .gif
WebP image/webp .webp


Image Data Storage

Each image is stored with the following metadata (compatible with admin):

{
    "iid": "1728061058670f0c30b9fd",
    "visible": 1,
    "imgName": "1728061058670f0c30b9fd.jpg",
    "imgNameOriginal": "product_photo.jpg",
    "imgdate": "17280610586",
    "iNumber": 1,
    "iLink": "",
    "slider": 0
}
Field Type Description
iid string Unique image identifier (auto-generated from timestamp + unique ID)
visible integer 1 = published, 0 = hidden
imgName string Stored filename (auto-generated)
imgNameOriginal string Original filename as uploaded by the user
imgdate string Upload timestamp
iNumber integer Sort order position (1-based)
iLink string External link (reserved, always empty)
slider integer Slider flag (reserved, always 0)


images_add — Adding Images

Each entry in the images_add array can be provided in two formats: base64-encoded or URL-based.

Base64 Format

Field Type Required Description
base64 string Yes* Base64-encoded image data (with or without data URI prefix)
type string No MIME type (image/jpeg, image/png, image/gif, image/webp). Auto-detected from base64 header if not provided.
original_name string No Original filename for reference. Defaults to auto-generated name.

*Either base64 or url is required.

URL Format

Field Type Required Description
url string Yes* URL to fetch the image from
type string No MIME type. If not provided, detected from URL extension or response headers.
original_name string No Original filename for reference. Defaults to URL filename.

*Either base64 or url is required.

{
    "images_add": [
        {
            "base64": "iVBORw0KGgoAAAANSUhEUgAA...",
            "type": "image/jpeg",
            "original_name": "product_front.jpg"
        },
        {
            "base64": "data:image/png;base64,iVBORw0KGgo...",
            "original_name": "product_back.png"
        },
        {
            "url": "https://example.com/images/product_side.jpg",
            "original_name": "product_side.jpg"
        }
    ]
}

Response:

{
    "changes": {
        "images_add": {
            "success": true,
            "images_added": 3,
            "message": "3 image(s) added successfully",
            "details": [
                {
                    "iid": "1728061058670f0c30b9fd",
                    "imgName": "1728061058670f0c30b9fd.jpg",
                    "imgNameOriginal": "product_front.jpg",
                    "iNumber": 1
                },
                {
                    "iid": "1728061059670f0c30b9fe",
                    "imgName": "1728061059670f0c30b9fe.png",
                    "imgNameOriginal": "product_back.png",
                    "iNumber": 2
                },
                {
                    "iid": "1728061060670f0c30b9ff",
                    "imgName": "1728061060670f0c30b9ff.jpg",
                    "imgNameOriginal": "product_side.jpg",
                    "iNumber": 3
                }
            ]
        }
    }
}


images_delete — Deleting Images

Pass an array of image IDs (iid values) to delete. All size variants (original, big_, small_, thumb_, sthumb_) are removed from disk.

{
    "pid": 123,
    "images_delete": ["1728061058670f0c30b9fd", "1728061059670f0c30b9fe"]
}

Response:

{
    "changes": {
        "images_delete": {
            "success": true,
            "images_deleted": 2,
            "message": "2 image(s) deleted successfully"
        }
    }
}


images_set_visible — Toggle Image Visibility

Hide or show individual images without deleting them. This mirrors the admin panel's publish/unpublish button on each image.

{
    "pid": 123,
    "images_set_visible": [
        {"iid": "1728061058670f0c30b9fd", "visible": 0},
        {"iid": "1728061060670f0c30b9ff", "visible": 1}
    ]
}
Field Type Required Description
iid string Yes Image ID to update
visible integer Yes 1 = published/visible, 0 = hidden

Response:

{
    "changes": {
        "images_set_visible": {
            "success": true,
            "updated": 2,
            "message": "2 image(s) visibility updated",
            "details": [
                {"iid": "1728061058670f0c30b9fd", "visible": 0},
                {"iid": "1728061060670f0c30b9ff", "visible": 1}
            ]
        }
    }
}


images_sort — Reorder Images

Reorder images by passing an ordered array of iid values. The first item becomes iNumber: 1, the second iNumber: 2, and so on. Any images not included in the sort array retain their existing position.

{
    "pid": 123,
    "images_sort": [
        "1728061060670f0c30b9ff",
        "1728061058670f0c30b9fd",
        "1728061059670f0c30b9fe"
    ]
}

Response:

{
    "changes": {
        "images_sort": {
            "success": true,
            "message": "3 image(s) reordered",
            "order": [
                {"iid": "1728061060670f0c30b9ff", "iNumber": 1},
                {"iid": "1728061058670f0c30b9fd", "iNumber": 2},
                {"iid": "1728061059670f0c30b9fe", "iNumber": 3}
            ]
        }
    }
}


Combining Image Operations

All image operations can be combined in a single request and are processed in this order:

  1. images_add — Add new images first
  2. images_delete — Remove specified images
  3. images_set_visible — Toggle visibility
  4. images_sort — Reorder remaining images
{
    "pid": 123,
    "images_add": [
        {"base64": "...", "type": "image/jpeg", "original_name": "new_photo.jpg"}
    ],
    "images_delete": ["1728061058670f0c30b9fd"],
    "images_set_visible": [
        {"iid": "1728061059670f0c30b9fe", "visible": 0}
    ],
    "images_sort": [
        "1728061060670f0c30b9ff",
        "1728061059670f0c30b9fe"
    ]
}



Response Formats

Single Product Response:

{
    "status": "success",
    "message": "Product created/updated successfully",
    "data": {
        "pid": 123,
        "product": {...}
    },
    "changes": {...}
}

Bulk Product Response:

{
    "status": "success",
    "message": "All products processed successfully",
    "summary": {
        "total": 2,
        "successful": 2,
        "failed": 0
    },
    "results": [
        {
            "index": 0,
            "status": "success",
            "message": "Product created successfully",
            "data": {
                "pid": 123,
                "product": {...}
            },
            "changes": {...}
        },
        {
            "index": 1,
            "status": "success", 
            "message": "Product updated successfully",
            "data": {
                "pid": 124,
                "product": {...}
            },
            "changes": {...}
        }
    ]
}



Examples

Create a new product:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "cid": 1,
    "bid": 2,
    "price": 29.99,
    "vatId": 1,
    "product_name": "New Product",
    "product_desc": "Product description"
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'cid' => 1,
    'bid' => 2,
    'price' => 29.99,
    'vatId' => 1,
    'product_name' => 'New Product',
    'product_desc' => 'Product description'
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Update an existing product:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "pid": 123,
    "price": 24.99,
    "stock_data": [
        {
            "reason": 1,
            "stock": 50,
            "location_id": 1,
            "shelf_id": 1
        }
    ]
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'pid' => 123,
    'price' => 24.99,
    'stock_data' => [
        [
            'reason' => 1,
            'stock' => 50,
            'location_id' => 1,
            'shelf_id' => 1
        ]
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Upsert a product (create with specific PID if not exists, update if exists):

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "pid": 999,
    "cid": 1,
    "bid": 2,
    "price": 35.99,
    "vatId": 1,
    "product_name": "Upsert Product"
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'pid' => 999,
    'cid' => 1,
    'bid' => 2,
    'price' => 35.99,
    'vatId' => 1,
    'product_name' => 'Upsert Product'
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Bulk create and update products:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass", 
    "account": "myaccount.com",
    "products": [
        {
            "cid": 1,
            "bid": 2, 
            "price": 29.99,
            "vatId": 1,
            "product_name": "New Product 1"
        },
        {
            "pid": 123,
            "price": 24.99
        },
        {
            "pid": 999,
            "cid": 1,
            "bid": 3,
            "price": 45.99,
            "vatId": 1,
            "product_name": "Upsert Product"
        }
    ]
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'products' => [
        [
            'cid' => 1,
            'bid' => 2,
            'price' => 29.99,
            'vatId' => 1,
            'product_name' => 'New Product 1'
        ],
        [
            'pid' => 123,
            'price' => 24.99
        ],
        [
            'pid' => 999,
            'cid' => 1,
            'bid' => 3,
            'price' => 45.99,
            'vatId' => 1,
            'product_name' => 'Upsert Product'
        ]
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Create a product with images (base64):

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "cid": 1,
    "bid": 2,
    "price": 29.99,
    "vatId": 1,
    "product_name": "Product With Photos",
    "images_add": [
        {
            "base64": "'$(base64 -w0 product_front.jpg)'",
            "type": "image/jpeg",
            "original_name": "product_front.jpg"
        },
        {
            "base64": "'$(base64 -w0 product_back.png)'",
            "type": "image/png",
            "original_name": "product_back.png"
        }
    ]
}'
$image1 = base64_encode(file_get_contents('product_front.jpg'));
$image2 = base64_encode(file_get_contents('product_back.png'));

$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'cid' => 1,
    'bid' => 2,
    'price' => 29.99,
    'vatId' => 1,
    'product_name' => 'Product With Photos',
    'images_add' => [
        [
            'base64' => $image1,
            'type' => 'image/jpeg',
            'original_name' => 'product_front.jpg'
        ],
        [
            'base64' => $image2,
            'type' => 'image/png',
            'original_name' => 'product_back.png'
        ]
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Create a product with images from URL:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "cid": 1,
    "bid": 2,
    "price": 29.99,
    "vatId": 1,
    "product_name": "Product With External Photos",
    "images_add": [
        {
            "url": "https://example.com/images/product_main.jpg",
            "original_name": "product_main.jpg"
        }
    ]
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'cid' => 1,
    'bid' => 2,
    'price' => 29.99,
    'vatId' => 1,
    'product_name' => 'Product With External Photos',
    'images_add' => [
        [
            'url' => 'https://example.com/images/product_main.jpg',
            'original_name' => 'product_main.jpg'
        ]
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Manage images on an existing product (delete, hide, reorder):

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "api_user",
    "password": "api_pass",
    "account": "myaccount.com",
    "pid": 123,
    "images_add": [
        {
            "base64": "iVBORw0KGgoAAAANSUhEUg...",
            "type": "image/jpeg",
            "original_name": "new_additional_photo.jpg"
        }
    ],
    "images_delete": ["1728061058670f0c30b9fd"],
    "images_set_visible": [
        {"iid": "1728061059670f0c30b9fe", "visible": 0}
    ],
    "images_sort": [
        "1728061060670f0c30b9ff",
        "1728061059670f0c30b9fe"
    ]
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'api_user',
    'password' => 'api_pass',
    'account' => 'myaccount.com',
    'pid' => 123,
    'images_add' => [
        [
            'base64' => base64_encode(file_get_contents('new_photo.jpg')),
            'type' => 'image/jpeg',
            'original_name' => 'new_additional_photo.jpg'
        ]
    ],
    'images_delete' => ['1728061058670f0c30b9fd'],
    'images_set_visible' => [
        ['iid' => '1728061059670f0c30b9fe', 'visible' => 0]
    ],
    'images_sort' => [
        '1728061060670f0c30b9ff',
        '1728061059670f0c30b9fe'
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;



Set a bottle deposit on a product:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "your_username",
    "password": "your_password",
    "account": "your_account",
    "pid": 123,
    "bottle_deposit_pid": 456
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'your_username',
    'password' => 'your_password',
    'account' => 'your_account',
    'pid' => 123,
    'bottle_deposit_pid' => 456
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;


Clear a bottle deposit from a product:

curl -X POST 'https://easycms.fi/public_api/set_product/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "your_username",
    "password": "your_password",
    "account": "your_account",
    "pid": 123,
    "bottle_deposit_pid": null
}'
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'your_username',
    'password' => 'your_password',
    'account' => 'your_account',
    'pid' => 123,
    'bottle_deposit_pid' => null
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;




Error Responses

Possible error codes include:

  • MISSING_REQUIRED_FIELDS: When required fields are missing for new product
  • UPDATE_FAILED: When updating the product fails
  • CREATE_FAILED: When creating the product fails
  • INVALID_STOCK_DATA: When stock data is invalid
  • PRODUCT_NOT_FOUND: When updating a product that doesn't exist (deprecated - now creates with specified PID)

Image-Specific Errors

Images that fail to process are skipped gracefully — the product operation still succeeds, but individual image failures are reported in the response:

{
    "changes": {
        "images_add": {
            "success": true,
            "images_added": 2,
            "images_failed": 1,
            "message": "2 image(s) added successfully, 1 failed",
            "details": [
                {"iid": "...", "imgName": "...", "iNumber": 1, "status": "added"},
                {"iid": "...", "imgName": "...", "iNumber": 2, "status": "added"},
                {"status": "failed", "error": "Invalid image type: image/tiff"}
            ]
        }
    }
}

Common image failure reasons:

  • Invalid file type: Only jpg, jpeg, png, gif, webp are accepted
  • Invalid base64: Corrupted or malformed base64 data
  • URL fetch failed: Remote image URL returned error or timed out
  • Image too large: File exceeds maximum allowed size

Partial Success Response (Bulk Operations)

For bulk operations, when some products fail, the API returns a 207 status code with partial success information:

{
    "status": "partial_success",
    "message": "Some products failed to process",
    "summary": {
        "total": 3,
        "successful": 2, 
        "failed": 1
    },
    "results": [...]
}




Notes

  • When updating, only fields provided in the request will be updated
  • For new products, if price_gross is provided, net price will be calculated automatically
  • Product reference and barcode are auto-generated if not provided
  • Stock changes are tracked in the stock diary
  • Product costs are stored in a separate table (tbl_products_cost)
  • Product multi data allows different prices/barcodes per location
  • When pid is provided but the product doesn't exist, the API creates a new product with the specified PID (upsert behavior)
  • Bulk operations process all products in the array and return detailed results for each

Image Notes

  • Uploaded images are automatically resized to 5 variants: original, big_ (900px), small_ (500px), thumb_ (180px), sthumb_ (50px)
  • Images are stored in the same format as the admin panel, ensuring full compatibility with the inventory media tab
  • Image IDs (iid) are auto-generated — you receive them in the response after adding images
  • You can get existing image IDs from the get_products endpoint (the images field in the response)
  • Deleting an image removes all size variants from disk (original + 4 resized copies)
  • Image operations are processed in order: add → delete → set visible → sort
  • Images added via API are immediately visible in the admin panel's media tab
  • The original_name field is preserved as imgNameOriginal for reference in the admin

Field Name Aliases

The API accepts some common aliases that map to the actual database column names:

Alias (accepted) Actual DB column Notes
vatId vat VAT rate reference ID
description product_desc Product description
status prdStatus Product publish status (1=published, 0=unpublished)

Both the alias and the actual column name are accepted. Using the actual column name is preferred.

Multilingual Fields

Fields that support multiple languages (product_name, product_desc, productDetails, productDelivery) accept either:

  • A simple string: "My Product" — stored as {"en_GB": "My Product"}
  • A language map: {"en_GB": "Product", "fi_FI": "Tuote", "sv_SE": "Produkt"} — stored with all provided languages

Product Visibility

Setting prdStatus to 0 makes the product invisible to get_products by default. To retrieve invisible products, use the show_invisible=1 parameter with get_products. This allows you to re-publish products by setting prdStatus back to 1.


Product Bundles

Product bundles are managed through a dedicated endpoint. Use Set Product Bundles to create, update, or delete bundle items. The is_bundle flag is automatically managed when bundle items are added or removed.

Related Endpoints