Inventory & Products | Products | Bundles | Set Product Bundles

Setting Product Bundles

This endpoint allows you to create, update, or delete product bundle items via the Public API. Bundle items define the child products that make up a bundle product.

Endpoint and Method

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



Authentication

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



Operation Modes

The API supports multiple operations for managing product bundle items:

Add Bundle Items

Provide pid and an items array without bundle_id to create new bundle items.

Update Bundle Items

Provide pid and an items array with bundle_id to update existing bundle items.

Delete Bundle Items

Provide pid and a delete array of bundle_id strings to soft-delete bundle items.

Replace All Bundle Items

Set replace_all: true with items to delete all existing bundle items and create new ones.



Request Body Parameters

Parameter Type Required Description
username string Yes API username
password string Yes API password
account string Yes Account domain
pid integer Yes Parent product ID (the bundle)
items array No* Array of bundle items to create/update
delete array No* Array of bundle_id strings to soft-delete
replace_all boolean No If true, soft-deletes all existing items first

*At least one of items or delete must be provided (or replace_all with items).



items Array Structure

Field Type Required Description
child_pid integer Yes The component product PID
quantity double No Default: 1
sort_order integer No Default: auto-increment from last
bundle_id string No If provided, updates existing bundle row



Call Examples in Different Languages


curl -X POST 'https://easycms.fi/public_api/set_product_bundles/' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
    "username": "USERNAME",
    "password": "PASSWORD",
    "account": "ACCOUNT_ID",
    "pid": 18958,
    "items": [
        {"child_pid": 11031, "quantity": 2, "sort_order": 0},
        {"child_pid": 4110, "quantity": 1, "sort_order": 1}
    ]
}'

$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/set_product_bundles/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode([
    'username' => 'USERNAME',
    'password' => 'PASSWORD',
    'account' => 'ACCOUNT_ID',
    'pid' => 18958,
    'items' => [
        ['child_pid' => 11031, 'quantity' => 2, 'sort_order' => 0],
        ['child_pid' => 4110, 'quantity' => 1, 'sort_order' => 1]
    ]
  ]),
  CURLOPT_HTTPHEADER => array(
    "Authorization1: TOKEN",
    "Content-Type: application/json"
  ),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;

import requests
import json

url = "https://easycms.fi/public_api/set_product_bundles/"
headers = {
    "Authorization1": "TOKEN",
    "Content-Type": "application/json"
}
payload = {
    "username": "USERNAME",
    "password": "PASSWORD",
    "account": "ACCOUNT_ID",
    "pid": 18958,
    "items": [
        {"child_pid": 11031, "quantity": 2, "sort_order": 0},
        {"child_pid": 4110, "quantity": 1, "sort_order": 1}
    ]
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.text)

import java.net.URI;
import java.net.http.*;

HttpClient client = HttpClient.newHttpClient();
String jsonBody = """
{
    "username": "USERNAME",
    "password": "PASSWORD",
    "account": "ACCOUNT_ID",
    "pid": 18958,
    "items": [
        {"child_pid": 11031, "quantity": 2, "sort_order": 0},
        {"child_pid": 4110, "quantity": 1, "sort_order": 1}
    ]
}
""";
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://easycms.fi/public_api/set_product_bundles/"))
    .headers("Authorization1", "TOKEN", "Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
    .build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

const https = require('https');
const data = JSON.stringify({
  username: 'USERNAME',
  password: 'PASSWORD',
  account: 'ACCOUNT_ID',
  pid: 18958,
  items: [
    { child_pid: 11031, quantity: 2, sort_order: 0 },
    { child_pid: 4110, quantity: 1, sort_order: 1 }
  ]
});
const options = {
  hostname: 'easycms.fi',
  path: '/public_api/set_product_bundles/',
  method: 'POST',
  headers: {
    'Authorization1': 'TOKEN',
    'Content-Type': 'application/json',
    'Content-Length': data.length
  }
};
const req = https.request(options, (res) => {
  let body = '';
  res.on('data', (chunk) => { body += chunk; });
  res.on('end', () => { console.log(body); });
});
req.on('error', (e) => { console.error(e); });
req.write(data);
req.end();

import React, { useEffect, useState } from 'react';
function App() {
  const [responseData, setResponseData] = useState('');
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://easycms.fi/public_api/set_product_bundles/', {
          method: 'POST',
          headers: {
            'Authorization1': 'TOKEN',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            username: 'USERNAME',
            password: 'PASSWORD',
            account: 'ACCOUNT_ID',
            pid: 18958,
            items: [
              { child_pid: 11031, quantity: 2, sort_order: 0 },
              { child_pid: 4110, quantity: 1, sort_order: 1 }
            ]
          })
        });
        const data = await response.text();
        setResponseData(data);
      } catch (error) {
        console.error(error);
      }
    };
    fetchData();
  }, []);
  return (<div>{responseData}</div>);
}
export default App;

// Kotlin Example using OkHttp for JSON POST request
import okhttp3.OkHttpClient
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Request

fun main() {
    val client = OkHttpClient()
    val json = """
    {
        "username": "USERNAME",
        "password": "PASSWORD",
        "account": "ACCOUNT_ID",
        "pid": 18958,
        "items": [
            {"child_pid": 11031, "quantity": 2, "sort_order": 0},
            {"child_pid": 4110, "quantity": 1, "sort_order": 1}
        ]
    }
    """.trimIndent()

    val body = json.toRequestBody("application/json".toMediaType())
    val request = Request.Builder()
        .url("https://easycms.fi/public_api/set_product_bundles/")
        .post(body)
        .addHeader("Authorization1", "TOKEN")
        .addHeader("Content-Type", "application/json")
        .build()

    client.newCall(request).execute().use { response ->
        if (!response.isSuccessful) throw IOException("Unexpected code $response")
        println(response.body?.string())
    }
}

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        var token = "TOKEN";
        var jsonBody = @"{
            ""username"": ""USERNAME"",
            ""password"": ""PASSWORD"",
            ""account"": ""ACCOUNT_ID"",
            ""pid"": 18958,
            ""items"": [
                {""child_pid"": 11031, ""quantity"": 2, ""sort_order"": 0},
                {""child_pid"": 4110, ""quantity"": 1, ""sort_order"": 1}
            ]
        }";
        var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Add("Authorization1", token);
            var response = await httpClient.PostAsync("https://easycms.fi/public_api/set_product_bundles/", content);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseData);
            }
            else
            {
                Console.WriteLine($"Error: {response.StatusCode}");
            }
        }
    }
}




Handling Endpoint Results

When you make a request to the endpoint, you receive a JSON response containing various keys and values. Here's an explanation of the response keys and their meanings:


- `status`: The result status. "success" indicates the operation completed.
- `message`: A human-readable description of the result.
- `data.pid`: The parent product ID that was targeted.
- `data.is_bundle`: The current bundle flag (1 = is a bundle, 0 = not a bundle).
- `data.items_created`: Number of new bundle items created.
- `data.items_updated`: Number of existing bundle items updated.
- `data.items_deleted`: Number of bundle items soft-deleted.
- `data.bundle_items`: Array of current bundle items after the operation.
  - `bundle_id`: UUID primary key of the bundle item.
  - `child_pid`: The component product PID.
  - `quantity`: Quantity of the component product.
  - `sort_order`: Display/ordering position.
    

{
  "status": "success",
  "message": "Product bundles updated successfully",
  "data": {
    "pid": 18958,
    "is_bundle": 1,
    "items_created": 2,
    "items_updated": 0,
    "items_deleted": 0,
    "bundle_items": [
      {
        "bundle_id": "new-uuid-here",
        "child_pid": 11031,
        "quantity": 2,
        "sort_order": 0
      },
      {
        "bundle_id": "another-uuid",
        "child_pid": 4110,
        "quantity": 1,
        "sort_order": 1
      }
    ]
  }
}
      

Error Handling

Here are the possible error messages and their meanings:

Error Code HTTP Status Description
MISSING_PID 200 The pid parameter is required
INVALID_PID 200 The pid must be a valid positive integer
PRODUCT_NOT_FOUND 200 Product with specified pid does not exist
NO_ACTION 200 At least one of items, delete, or replace_all must be provided
SELF_REFERENCE 200 A product cannot be a bundle of itself
CHILD_NOT_FOUND 200 The specified child_pid product does not exist
UN-AUTHORIZED - _user_name_password_is_set_but_wrong_value! 401 Incorrect username or password
this_account_does_not_exist_or_your_credentials_do_not_match_this_account 401 The account doesn't exist or mismatched credentials
UN-AUTHORIZED - header is set but the header value is not correct! 401 Incorrect authorization header value

Error Response Example

{
  "status": "error",
  "error_code": "MISSING_PID",
  "message": "The pid parameter is required"
}

Notes

  • When items are added and the parent product's is_bundle flag is 0, it is automatically set to 1
  • When all bundle items are deleted and none remain, is_bundle is automatically set to 0
  • A product cannot be a bundle of itself (child_pid cannot equal pid)
  • Bundle items use UUID primary keys (bundle_id)
  • sort_order auto-increments if not provided

Related Endpoints