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.
https://easycms.fi/public_api/set_product_bundles/application/json
Authorization1: {API_TOKEN}username, password, account
The API supports multiple operations for managing product bundle items:
Provide pid and an items array without bundle_id to create new bundle items.
Provide pid and an items array with bundle_id to update existing bundle items.
Provide pid and a delete array of bundle_id strings to soft-delete bundle items.
Set replace_all: true with items to delete all existing bundle items and create new ones.
| 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 |
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}");
}
}
}
}
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
}
]
}
}
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 |
{
"status": "error",
"error_code": "MISSING_PID",
"message": "The pid parameter is required"
}
is_bundle flag is 0, it is automatically set to 1is_bundle is automatically set to 0child_pid cannot equal pid)bundle_id)sort_order auto-increments if not providedis_bundle filter and include_bundles enrichment