Inventory & Products | Products | Attributes | Get Product Attributes

Getting Product Attributes

This document outlines the procedure for making API calls to retrieve attribute-set definitions (the tenant's attribute catalog) and a product's attribute configuration via https://easycms.fi/public_api/get_product_attributes/.

Important Notes

  • All parameters marked as MANDATORY are required
  • Read-only endpoint — attribute definitions are maintained in the CMS product editor's Attributes tab
  • The definition catalog is tenant-global (shared by every product) and changes rarely — fetch it once, cache it client-side, and use pid mode for each product screen
  • A product may attach multiple attribute sets; the first attached set is mirrored to the legacy attributeset_id column the cash register uses
  • Text fields are returned twice: name (resolved in the account's main language) and name_ml (the raw {lang_code: text} map when the stored text is multilingual) — resolve other languages client-side
  • An attribute with an empty values array is a free-text attribute (no predefined options)

Modes

Mode Trigger Returns
Product pid given The product's attached set ids + isverpatrib flag, plus the fully-resolved definitions of those sets
Catalog pid omitted Every attribute set in the tenant with its attributes, values and picker configuration

Endpoint and Method

  • Endpoint: https://easycms.fi/public_api/get_product_attributes/
  • Method: GET or POST

Parameters | Payload

  • 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.

Common Parameters

Parameter Type Required Description
pid integer No Product ID — switches to product mode
attributeset_id string (UUID) No Catalog mode only: return just this one set
start integer No Pagination start (default 0, catalog mode only)
limit integer No Page size (default 50, max 50, catalog mode only)



Response Structure

Product mode

{
  "INFO": { "mode": "product", "pid": 25327, "count": 1, "total_count": 1 },
  "PRODUCT": {
    "pid": 25327,
    "isverpatrib": 1,
    "attributeset_ids": ["f37c7663-1a60-4134-ac48-75bd3f27b3e1"],
    "attributeset_id": "f37c7663-1a60-4134-ac48-75bd3f27b3e1"
  },
  "OUTPUT": [ { "...one set object, see below" : "..." } ],
  "success": true,
  "message": "Data returned successfully"
}
  • PRODUCT.isverpatrib — 1 = the merchant asks for attribute values when the product is added to order/invoice lines
  • PRODUCT.attributeset_ids — attached sets in attachment order (first = legacy mirror)
  • OUTPUT — full definitions of the attached sets only

Set object (both modes)

{
  "set_id": "f37c7663-1a60-4134-ac48-75bd3f27b3e1",
  "name": "Pizza options",
  "name_ml": { "fi": "Pizzavalinnat", "en_gb": "Pizza options" },
  "sort": 1,
  "product_count": 14,
  "attributes": [
    {
      "use_id": "a82a4ace-...",
      "attribute_id": "0f61d2c4-...",
      "attribute_name": "Included toppings",
      "attribute_ml": null,
      "lineno": 1,
      "select_type": 1,
      "max_allowed_options": 3,
      "default_value_ids": ["c1d0f5aa-...", "e9b8d701-..."],
      "default_value_texts": ["Ground beef", "Onion"],
      "values": [
        { "value_id": "c1d0f5aa-...", "value": "Ground beef", "value_ml": null },
        { "value_id": "e9b8d701-...", "value": "Onion", "value_ml": null }
      ]
    }
  ]
}
  • select_type — 0 = single choice, 1 = multi select
  • max_allowed_options — maximum selectable values (0 = unlimited)
  • default_value_ids / default_value_texts — the pre-selected values
  • values — the offered options; [] = free-text attribute

Errors

error / message When
product_not_found_or_not_visible pid unknown, deleted, or hidden from this API channel
pid_must_be_a_valid_positive_integer non-numeric pid
maximum_query_size_is_50_rows_per_query limit over 50
NOT AUTHORIZED! authentication failed



Call Examples in Different Languages


# Full tenant catalog (cache this — it changes rarely)
curl -X POST 'https://easycms.fi/public_api/get_product_attributes' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
  "username": "USERNAME",
  "password": "PASSWORD",
  "account": "ACCOUNT_ID"
}'

# One product's attribute configuration
curl -X POST 'https://easycms.fi/public_api/get_product_attributes' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
  "username": "USERNAME",
  "password": "PASSWORD",
  "account": "ACCOUNT_ID",
  "pid": 25327
}'

# Refresh a single set after a change notification
curl -X POST 'https://easycms.fi/public_api/get_product_attributes' \
-H 'Authorization1: TOKEN' \
-H 'Content-Type: application/json' \
-d '{
  "username": "USERNAME",
  "password": "PASSWORD",
  "account": "ACCOUNT_ID",
  "attributeset_id": "f37c7663-1a60-4134-ac48-75bd3f27b3e1"
}'

$ch = curl_init('https://easycms.fi/public_api/get_product_attributes');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization1: TOKEN', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'username' => 'USERNAME',
        'password' => 'PASSWORD',
        'account'  => 'ACCOUNT_ID',
        'pid'      => 25327
    ])
]);
$response = json_decode(curl_exec($ch), true);
foreach ($response['PRODUCT']['attributeset_ids'] as $setId) {
    // find the set definition in $response['OUTPUT'] by set_id
}

const res = await fetch('https://easycms.fi/public_api/get_product_attributes', {
  method: 'POST',
  headers: { 'Authorization1': 'TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    username: 'USERNAME', password: 'PASSWORD',
    account: 'ACCOUNT_ID', pid: 25327
  })
});
const data = await res.json();
// data.PRODUCT.attributeset_ids -> attachment order
// data.OUTPUT[] -> set definitions for the picker UI

val body = """{"username":"USERNAME","password":"PASSWORD",
  "account":"ACCOUNT_ID","pid":25327}"""
val req = Request.Builder()
    .url("https://easycms.fi/public_api/get_product_attributes")
    .header("Authorization1", "TOKEN")
    .post(body.toRequestBody("application/json".toMediaType()))
    .build()
val data = JSONObject(client.newCall(req).execute().body!!.string())
val attached = data.getJSONObject("PRODUCT").getJSONArray("attributeset_ids")