How it works
After creating an API integration, you authenticate requests with an API key, managed under Settings > Developer > API. Push product data to Cernel’s REST endpoints, and your products appear in the Catalog ready for enrichment. Once Cernel has enriched them, poll the changes endpoint to pull the results back into your own systems.Why you would use this
Custom integrations
Pull enriched content back
Setting up the API integration
Create the integration
- Integration Name - A descriptive name
- Integration Languages - The languages this integration pushes and pulls product data in. You can pick one language or several: the first one you add is marked Primary and is used as the fallback when a property is pushed without a language. Open Edit Languages later from the integration detail panel to change the list.
- Product Identifier Field - The field name used as the unique identifier (e.g.,
id,sku) - Product Title Field - The field name used as the product title (e.g.,
title,name)

locale field: Cernel stores each localized value separately and surfaces it for the matching language. Properties pushed without a locale are stored against the integration’s primary language.Get an API key

API keys are organized into service accounts
Access the API documentation
Building a custom product pipeline
If your products come from an ERP, PIM, custom database, or supplier feed, you can build a fully automated pipeline: push products in via the API, enrich them with AI using Automations, and get the results back programmatically.Pushing products
Use the create products endpoint to push product data from your system:Creating variant structure
Cernel models variants as a parent product with child products beneath it, for example a master style that splits into colours, and a colour that splits further into sizes. This is the one relationship a CSV import can’t build, since a CSV row has no parent column, so push variant structure through the API (or a Shopify or Struct integration) instead. To build the structure through the API:- Link each variant to its parent with
parent_identifier, set to the parent’s own identifier. A variant can itself be a parent, so a colour that splits into sizes is a variant of the master and a parent to its own size variants. - Declare the variant axis on the parent with
child_bound_attributes: the attributes whose values make each child distinct, such as Size or Colour. - Carry the axis values on each variant with
defining_properties: the values for the attributes the parent declared, for examplecolorCode: 3007andcolor: NAVYfor one colour variant.
parent_identifier alone is enough to nest a product under its parent. Without any axis values, though, the child has no variant axis to sit on, so nothing distinguishes it from its siblings the way a Size or Colour would. The FAQ below covers what you get with, and without, those values.
Patching products (partial updates)
Use the patch endpoint when you only need to change a few properties on a product, without re-pushing the full payload:product_id (Cernel’s ID) or by identifier (your system’s identifier, exactly one of the two), then sets, removes, or appends localized property values. Each item in the batch is applied as its own transaction, so a bad operation only fails that one item, not the whole batch.
Use this when you want to update a single field (e.g., a price change) on thousands of products without re-sending every property you’ve already pushed.
Listing products
Use the list products endpoint to fetch products that already exist on the integration, with filters:Getting enriched data back
Poll the changes endpoint to get a chronological list of enrichment updates:Reading a category (taxonomy classification) value
A category attribute, the result of taxonomy classification, comes back as astruct value. Because a product can belong to several categories at once, its data carries a nodes array with one entry per category:
pathis the category’s display path, andnode_idis the category it resolved to.taxonomy_idandtaxonomy_namedescribe the whole value. One value covers one taxonomy, so a product classified in two taxonomies returns one value per taxonomy.- The entries carry equal weight. If you can store only one category, take the first.
nodes array.
A category value that arrived as a path from your side, and that no classification has produced a value for yet, carries node_id, taxonomy_id, and taxonomy_name all null. The three fill in together when a classification replaces the value, so treat a null node_id as unclassified rather than as a state that resolves on its own.
Tracking product completeness
When you poll the changes endpoint, addinclude_summary=true to attach a per-product completeness summary to each change. It answers “how far along is this product?” without a separate lookup:
summary object with:
num_attributes: every attribute attached to the category the product is classified in, including ones this integration has no mapping for. When the product sits in one of your own taxonomies, the count is measured against that category; otherwise it falls back to the product’s Cernel category.num_attributes_with_agents: how many of those attributes an AI agent can fill. The rest are only ever set by an upsert or a manual edit.locale_summaries: anum_attributes_populatedcount per locale, covering every language enabled on your organization. A language with nothing filled in yet reports zero rather than being absent. The attribute totals are the same for every locale, so the per-locale counts share one denominator and are directly comparable.
null only when the product is classified in neither, since there is then no attribute set to measure against.
Listing the attributes a product requires
For a single product, you can list its required attributes directly instead of deriving them from a change summary:attributes list, where each entry describes one required attribute:
attribute_id,attribute_name: the attribute itself.taxonomy_id: the taxonomy the requirement was resolved in. When the same attribute is required in two taxonomies the product is classified in, it appears once per taxonomy.resolved_anchor_id: the category that set the attribute for this product. Attributes set at a parent category automatically apply to all its subcategories, so where several of the product’s categories require it, this names the one that governs.contributing_node_ids: every category the product belongs to that requires the attribute. Read this for a per-category view.is_completed: whether the product holds a value for the attribute in any language.
is_completed is true, and divide the second by the first:
- Whole product: use every entry.
- One taxonomy: keep only entries with that
taxonomy_id. - One category: keep only entries whose
contributing_node_idsinclude that category.
taxonomy_id first if you don’t want it counted twice. If the product has no required attributes there is nothing to divide by, which means nothing is required, not that the product is 0% complete.
Scoping the resolution. Two optional query parameters narrow what gets resolved. taxonomy_id resolves within a single taxonomy only. taxonomy_node_id resolves within one category’s subtree and excludes any category outside it; it requires taxonomy_id, since a subtree lives inside one taxonomy.
Example: ERP to Cernel to e-commerce platform
- Nightly export from your ERP pushes new/updated products to Cernel via API
- Automation enriches each product with descriptions, meta content, and materials
- Morning review: your content team reviews results on the Dashboard and approves
- Changes endpoint: your e-commerce platform polls for approved changes and publishes them
Managing the product lifecycle
Updating products
Updating products
- Full update: push the complete product payload to
POST /products. The identifier field matches against existing products; Cernel replaces the property values you send. - Partial update: send a
PATCH /productsoperation that only includes the properties you want to change. Locate the product byproduct_idoridentifier(exactly one of the two), then set, remove, or append localized values. Each operation runs in its own transaction, so a single failure doesn’t roll back the batch.
Reapplying mappings after a configuration change
Reapplying mappings after a configuration change
- Open the integration from Integrations and click the Settings menu near the top of the detail page.
- Choose Reset Integration.
- Select Reapply mappings and confirm.
Working with multiple languages
Working with multiple languages
locale field. Cernel stores each localized variant separately and exposes the matching language to enrichment, the product UI, and the /changes endpoint. Properties pushed without a locale are stored against the integration’s Primary language.This lets one API integration cover, for example, a Danish reference catalog with English and German translations alongside it, without setting up separate integrations per language.Deleting products
Deleting products
Tracking enrichment changes
Tracking enrichment changes
include_all_properties=true to get the full product snapshot with each change (useful for full syncs, but limited to 10 results per request). Pass include_summary=true to attach a completeness summary (attributes defined, AI-fillable, and populated per locale) to each change without lowering the page size. See Tracking product completeness.Frequently asked questions
Where can I find the full API documentation?
Where can I find the full API documentation?
How do I rotate my API token?
How do I rotate my API token?
How do I get enriched content back out of Cernel over the API?
How do I get enriched content back out of Cernel over the API?
GET /api/v1/integrations:api/{integration_id}/changes. It returns enrichment updates in chronological order, and you use the offset it returns to pick up where you left off on the next poll. There is no push-style webhook delivery on the Public API, so retrieving results is always a poll from your side. See Getting enriched data back.Can I link a variant to its parent without a variant-defining attribute?
Can I link a variant to its parent without a variant-defining attribute?
parent_identifier is enough to make it a child of that parent: a variant-defining attribute isn’t required for the link itself. Cernel accepts the product and nests it under the parent, so it appears among the parent’s children rather than in the flat product list.Without any variant-defining values, though, the child has no variant axis, so nothing distinguishes it from its siblings the way a Size or Colour would. Add defining_properties for the attributes the parent declared as child_bound_attributes when you want each variant identified by its own axis values. See Creating variant structure.Can I integrate a platform like Magento that doesn't have a native connector?
Can I integrate a platform like Magento that doesn't have a native connector?
parent_identifier to nest it under its parent. See Creating variant structure and the ERP to Cernel to e-commerce platform walkthrough, which is the same pattern any custom platform integration follows.Can I create or edit AI Agents and Data Sources through the API?
Can I create or edit AI Agents and Data Sources through the API?
