Every product in Channel3 has a category, and every category has a set of structured attributes — machine-extracted features like material, connectivity, power source, and thousands of others. Combining category detail lookup with the attributes search filter lets you express queries that plain text search can’t — for example, finding sofas that have USB charging ports.
The two-step pattern
- Discover the category and its attributes — look up the category detail to see which attribute keys are defined and what values they accept.
- Search with an attribute filter — pass those key/value pairs to
/v1/search to get precisely matched products.
Step 1 — Get a category slug
You need a category slug (for example sofas) before you can inspect its attributes. Either find one by text, or grab it from a product you already have.
Option A — Search for the category
Use the category search endpoint to look up by free text:
import Channel3 from "@channel3/sdk";
const client = new Channel3();
const categoryResults = await client.categories.search({ query: "sofas" });
// Pick the best-matching category
const category = categoryResults.categories[0];
console.log(category.slug); // e.g. "sofas"
console.log(category.title); // "Sofas"
Option B — Grab the category from an existing product
If you already have a representative product — from a search result, lookup, or your own catalog — read its category.slug instead of searching:
const product = await client.products.retrieve("2yh8WH5");
const slug = product.category.slug; // e.g. "sofas"
Step 2 — Retrieve category detail to see its attributes
Call the category detail endpoint with the slug to get the full list of attributes for that category. Each attribute has a handle (the key you’ll pass to the filter) and a list of known values.
const categoryDetail = await client.categories.retrieve("sofas");
// Print all attributes and their example values
for (const attr of categoryDetail.attributes) {
console.log(`${attr.handle}: ${attr.values.slice(0, 5).join(", ")}`);
}
// connectivity: USB, Bluetooth, None
// material: Leather, Velvet, Linen, Microfiber, ...
// seating_capacity: 2, 3, 4, Sectional
// style: Mid-Century Modern, Contemporary, ...
// color: Beige, Gray, Navy, ...
The attributes available vary by category. Always retrieve category detail
first — don’t guess attribute handles.
Step 3 — Search with the attribute filter
Now you have the attribute key and its accepted values. Pass them to POST /v1/search via the attributes filter. The attributes filter takes a map of handle → [values].
const results = await client.products.search({
query: "sofa",
filters: {
category: "sofas",
attributes: {
connectivity: ["USB"],
},
},
limit: 20,
});
console.log(`Found ${results.products.length} sofas with USB charging`);
results.products.forEach((p) => {
console.log(p.title, p.offers[0]?.price);
});
Full end-to-end example
Here’s the complete three-step flow in a single function — discover the category, inspect its attributes, then search:
import Channel3 from "@channel3/sdk";
const client = new Channel3();
async function findSofasWithUSB() {
// 1. Find the category
const { categories } = await client.categories.search({ query: "sofas" });
const slug = categories[0].slug; // "sofas"
// 2. Inspect its attributes
const detail = await client.categories.retrieve(slug);
const connectivityAttr = detail.attributes.find(
(a) => a.handle === "connectivity",
);
if (!connectivityAttr?.values.includes("USB")) {
console.warn("USB not listed as a connectivity value for this category");
}
// 3. Search with the attribute filter
const results = await client.products.search({
query: "sofa",
filters: {
category: slug,
attributes: { connectivity: ["USB"] },
},
limit: 20,
});
return results.products;
}
findSofasWithUSB().then((products) => {
console.log(`Found ${products.length} sofas with USB ports:`);
products.forEach((p) => console.log(" -", p.title));
});
Combining multiple attributes
Pass multiple keys to narrow further. Values within a key are OR’d; keys are AND’d — so the example below finds sofas that are (USB OR Bluetooth) connectivity and Velvet material:
const results = await client.products.search({
query: "sofa",
filters: {
category: "sofas",
attributes: {
connectivity: ["USB", "Bluetooth"],
material: ["Velvet"],
},
},
});
Reading structured_attributes on a product
Products returned from /v1/products/{id} and /v1/lookup include a structured_attributes field — a map of attribute handles to their extracted values for that specific product. Use it to display feature chips on a PDP, or to understand what attributes a specific product carries.
const product = await client.products.retrieve("2yh8WH5");
const attrs = product.structured_attributes;
// {
// connectivity: "USB",
// material: "Velvet",
// color: "Navy Blue",
// seating_capacity: "3",
// }
console.log(`Connectivity: ${attrs.connectivity}`);
console.log(`Material: ${attrs.material}`);
structured_attributes is populated on product detail (GET /v1/products/{id} and POST /v1/lookup). It is not returned on search results.