This document outlines the procedure for making API calls to retrieve product bundle data from https://easycms.fi/public_api/get_product_bundles/.
The pid (Product ID) parameter is MANDATORY for this endpoint. You must provide a valid product ID (the parent bundle product) to retrieve bundle data.
Fetch product bundle data effectively using the below API call.
https://easycms.fi/public_api/get_product_bundles/TOKEN (api_key): Your unique API key for authentication. How to Create API Credentials.username: Your login username. password: Your login password. account: Your specific account ID. pid: Product ID (MANDATORY) - The ID of the parent bundle product to retrieve bundle items for. Must be an integer.include_deleted: Set to 1 to include soft-deleted bundle items. Default: 0.start - Specify the starting point for pagination (default: 0).limit - Control the number of bundle items returned (default: 50, max: 50).
curl -X POST 'https://easycms.fi/public_api/get_product_bundles' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=18958'
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://easycms.fi/public_api/get_product_bundles",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'username' => 'USERNAME',
'password' => 'PASSWORD',
'account' => 'ACCOUNT_ID',
'pid' => 18958
]),
CURLOPT_HTTPHEADER => array("Authorization1: TOKEN"),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests
url = "https://easycms.fi/public_api/get_product_bundles"
headers = {"Authorization1": "TOKEN"}
payload = {
'username': 'USERNAME',
'password': 'PASSWORD',
'account': 'ACCOUNT_ID',
'pid': 18958
}
response = requests.post(url, headers=headers, data=payload)
print(response.text)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://easycms.fi/public_api/get_product_bundles"))
.headers("Authorization1", "TOKEN")
.POST(HttpRequest.BodyPublishers.ofString("username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=18958"))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
const https = require('https');
const data = new URLSearchParams({
username: 'USERNAME',
password: 'PASSWORD',
account: 'ACCOUNT_ID',
pid: 18958
}).toString();
const options = {
hostname: 'easycms.fi',
path: '/public_api/get_product_bundles',
method: 'POST',
headers: {
'Authorization1': 'TOKEN',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => { console.log(data); });
});
req.on('error', (e) => { console.error(e); });
req.write(data);
req.end();
import React, { useEffect, useState } from 'react';
function App() {
const [productBundlesData, setProductBundlesData] = useState('');
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://easycms.fi/public_api/get_product_bundles', {
method: 'POST',
headers: {'Authorization1': 'TOKEN', 'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
username: 'USERNAME',
password: 'PASSWORD',
account: 'ACCOUNT_ID',
pid: 18958
}).toString()
});
const data = await response.text();
setProductBundlesData(data);
} catch (error) {
console.error(error);
}
};
fetchData();
}, []);
return ({productBundlesData});
}
export default App;
// Kotlin Example using OkHttp for POST request
import okhttp3.OkHttpClient
import okhttp3.FormBody
import okhttp3.Request
fun main() {
val client = OkHttpClient()
val formBody = FormBody.Builder()
.add("username", "USERNAME")
.add("password", "PASSWORD")
.add("account", "ACCOUNT_ID")
.add("pid", "18958")
.build()
val request = Request.Builder()
.url("https://easycms.fi/public_api/get_product_bundles")
.post(formBody)
.addHeader("Authorization1", "TOKEN")
.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.Threading.Tasks;
class Program
{
static async Task Main()
{
var token = "TOKEN";
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair("username", "USERNAME"),
new KeyValuePair("password", "PASSWORD"),
new KeyValuePair("account", "ACCOUNT_ID"),
new KeyValuePair("pid", "18958")
});
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization1", token);
var response = await httpClient.PostAsync("https://easycms.fi/public_api/get_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:
- `start`: This represents the starting index for the data. In this case, it's set to 0, indicating that the data starts from the first item.
- `limit`: The maximum number of items returned in the response. In this example, the limit is set to 50, meaning that the response will include up to 50 items.
- `count`: The number of items included in the current response. In this case, there are 2 items in the response.
- `total_count`: The total count of items available in the dataset. In this response, there is a total of 2 items available.
- `pid`: The parent product ID that was queried for bundle data.
Each item in the OUTPUT array represents a single component within the bundle:
- `bundle_id`: Unique identifier for the bundle relationship (UUID).
- `parent_pid`: The parent (bundle) product ID.
- `child_pid`: The component product ID inside the bundle.
- `quantity`: Number of units of the child product in the bundle.
- `sort_order`: Display/ordering position.
- `created_at`: When this bundle item was created.
- `updated_at`: When this bundle item was last modified.
- `product`: Object containing child product details:
- `pid`: The child product ID.
- `product_name`: Object with locale-keyed names (e.g., "en_GB", "fi_FI").
- `price`: Selling price.
- `price_buy`: Purchase/buy price.
- `barcode`: Product barcode.
- `prdNumber`: Product reference number.
- `vat`: VAT category ID.
This field is `null` if the child product has been deleted.
These key-value pairs provide comprehensive information about the product bundles and can be used for various purposes in your application.
{
"INFO": {
"start": 0,
"limit": 50,
"count": 2,
"total_count": 2,
"pid": 18958,
"docs": "https://cms.helpostikotisivut.fi/DOCUMENTATION/bt5/get_product_bundles.php"
},
"OUTPUT": [
{
"bundle_id": "3eb365d3-7a1b-4c9f-b8e2-5d6a4f3c2e10",
"parent_pid": "18958",
"child_pid": "11031",
"quantity": 2,
"sort_order": 0,
"created_at": "2026-04-22 17:58:44",
"updated_at": "2026-04-22 17:58:44",
"product": {
"pid": "11031",
"product_name": {"en_GB": "Child Product A", "fi_FI": "Lapsituote A"},
"price": 5.99,
"price_buy": 3.00,
"barcode": "6410001",
"prdNumber": "REF001",
"vat": "55"
}
},
{
"bundle_id": "4fc476e4-8b2c-5d0a-c9f3-6e7b5g4d3f21",
"parent_pid": "18958",
"child_pid": "11045",
"quantity": 1,
"sort_order": 1,
"created_at": "2026-04-22 17:58:44",
"updated_at": "2026-04-22 17:58:44",
"product": {
"pid": "11045",
"product_name": {"en_GB": "Child Product B", "fi_FI": "Lapsituote B"},
"price": 12.50,
"price_buy": 7.00,
"barcode": "6410002",
"prdNumber": "REF002",
"vat": "55"
}
}
]
}
Here are the possible error messages and their meanings:
| Error Code | HTTP Status | Description |
|---|---|---|
pid_parameter_is_required |
400 | The pid parameter is required |
pid_must_be_a_valid_positive_integer |
400 | The pid must be a valid integer |
product_not_found |
404 | Product with specified pid does not exist |
UN-AUTHORIZED! |
401 | Authentication failed |
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 |
Maximum query size is 50 rows per query |
400 | Exceeded maximum limit of 50 rows per query |
{
"status": "error",
"error_code": "pid_parameter_is_required",
"message": "The pid parameter is required"
}
is_bundle filter and include_bundles enrichmentis_bundle != 1, the endpoint still returns its bundle items (they may exist from a previous state)product field is nullsort_order ascending