FacetFlux

FacetFlux

verified 22 may 2026
editor's choice  ]

The Particle Accelerator for Product Data

Pricing: Contact Us - Available upon request (Targeting $20M+ GMV brands) Company: FacetFlux Founded: 2024 Last verified: 2026-05-22
Visit Website Verified Vendor Updated

TL;DR

FacetFlux is an API-first, headless Product Information Management (PIM) platform designed for mid-market e-commerce brands ($20M–$200M GMV). It differentiates itself through a graph-based architecture and a unique 'Dirty Data' staging layer that uses AI to clean and map messy supplier data before it reaches the core system.

What Users Actually Pay

No user-reported pricing yet.

Our Take

Where most PIMs treat product data as documents to author, FacetFlux treats it as a schema problem — a typed graph that supplier feeds map into, with a staging layer that lets messy CSVs and PDFs land without touching the golden record. Built for the mid-market e-commerce team that outgrew Excel years ago but finds enterprise PIMs too rigid to keep pace with shifting category trees and attribute sets. The "columns, not rows" framing is the bet: schema-first wins when the model itself is the thing changing. Strongest fit for teams onboarding suppliers continuously rather than maintaining a static catalog.

Pros

  • + AI-driven 'Dirty Data' staging eliminates the need for pre-import data cleaning in Excel.
  • + Graph-based architecture supports complex, non-linear product data models without performance lag.
  • + Ultra-fast 200ms synchronization is ideal for real-time inventory and pricing across multiple channels.
  • + A modern, spreadsheet-like browser interface simplifies bulk editing for non-technical merchandising teams.

Cons

  • - Currently lacks the extensive third-party plugin ecosystem found in more mature platforms like Akeneo.
  • - Implementation requires more development resources than 'all-in-one' monolithic PIM solutions.
  • - High entry price point ($20M+ GMV target) makes it inaccessible for small-to-midsize businesses.
  • - Relatively new to the market, which may cause hesitation for risk-averse enterprise IT departments.

Sentiment Analysis

+0.83Very PositiveUpdated Apr 30, 2026

Sentiment has remained stable since last capture. Sentiment is highly positive, showing a slight increase from the previous 0.82. Users are particularly impressed by the speed and the AI staging features, though some 'early adopter' friction regarding the breadth of native integrations is noted.

Sentiment Over Time

By Source

Reddit+0.85

12 mentions

Sample quotes (2)
  • "The 'Dirty Data' layer is a game-changer for those of us dealing with messy dropshipping feeds."
  • "Finally a headless PIM that doesn't feel like it was built in the 2000s."
X (Twitter)+0.90

25 mentions

Sample quotes (2)
  • "FacetFlux is basically the Linear of PIMs. Fast, focused, and actually understands the modern e-comm workflow."
  • "Seeing 200ms sync times for a 50k SKU catalog is wild."
Capterra+0.75

2 mentions

Sample quotes (2)
  • "Powerful API and very fast, but still early days for native integrations."
  • "Exactly what we needed for our headless Shopify build."

Agent Readiness

52/100

FacetFlux is highly agent-ready due to its 'API-first' and 'Headless' architecture. The combination of comprehensive REST/GraphQL APIs, OAuth2 support, and extensive webhook capabilities allows AI agents to perform complex data orchestration, mapping, and synchronization tasks with minimal friction. Its graph-based backend makes it particularly well-suited for autonomous agents that need to navigate complex product hierarchies.

API Surface85
Public APIRESTGraphQLopenApi
Protocol Support0
SDK Availability0
Integration Ecosystem75
ZapierMakeWebhooksShopifyMiraklWooCommerceAmazon Marketplace
Developer Experience100
Docs: excellentSandboxVersioningChangelogStatus Page

Last checked Apr 30, 2026

MCP Integrations

1 server44 tools
FacetFlux MCPrevuo:facetflux
self-registeredRemoteHigh match

Allows AI tools like Codex, Claude Code et al. to help manage your product data

44 tools
  • pim.schemas.set.productNumberTemplateSet the schema's product-number template. C = category code character, N = sequential digit, any other character = literal. Example: 'CCCC-NNNNNNNN' renders 'PUMP-00000001'. Pass null to clear. Response: { schemaId, productNumberTemplate }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.byExternalId.getGet a single product by its source system + externalId. Useful for reconciling products imported from a supplier feed or upstream system without first calling pim.products.search. Same response shape as pim.products.get. Response: { product?: {...}, attributes?: [...], variants?: [...], channelStatuses?: [...] }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.attributeDefinitions.createCreate an attribute definition in a schema, or return the existing one if `code` already exists. DataType is required and immutable once values exist. Optional fields: traitId (binds the def to a trait), unit, scope (product|variantDefining|perVariant), role (None|Name|Description|Brand|...), isRequired, isTranslatable, isSearchable, isFilterable. To populate enum allowed values use pim.attributeDefinitions.allowedValues.set after creation. Response: { attributeDefinition: {...}, created: bool }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.traits.createCreate a trait in a schema, or return the existing one if `code` already exists. Traits are reusable groups of attribute definitions; products opt in to traits to gain their attributes. To bind attribute definitions to the trait after creation, use pim.traits.attributes.add (or set `traitId` directly when creating attribute definitions). Response: { trait: {...}, created: bool }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.products.traits.addAssign one or more traits to a product. Traits add their attribute definitions to the product's editable surface. Idempotent. Response: { productId, traitIds, added: count }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.batch.createBulk create-or-upsert products by (sourceSystem, externalId). All inputs share the same schemaId and sourceSystem. Up to 200 products per call; route larger payloads through the Phase-3 imports.* path. Per-row results report which were created vs updated. Channel-code application is a second pass — per-row failures appear in `channelWarnings` (typically: an unknown channel code) without failing the batch; the product itself is still created/updated. Response: { sourceSystem, schemaId, results: [{ productId, externalId, action }], channelWarnings: [{ externalId, productId, message }] }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.products.categories.removeRemove product from one or more categories. Idempotent — non-assigned categories are no-ops. Response: { productId, categoryIds, removed: count }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.channels.addPublish product on one or more channels. Channel codes must already exist for the tenant (otherwise the underlying invariant rejects the write). Idempotent. Response: { productId, channelCodes, added: count }. Errors: { error: { code: 'not_found' | 'unprocessable', ... } }.
  • pim.traits.getGet a trait by id, with its trait-scoped attribute definitions resolved. Response: { trait: {...}, attributeDefinitions: [...] }. Errors: { error: { code: 'not_found', ... } }.
  • imports.smartImports.deleteDelete a SmartImport record. Does NOT delete any PIM data created during execution — only the import record itself. Response: { smartImportId, deleted: bool }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.traits.removeUnassign one or more traits from a product. Note: existing attribute values for the trait's attributes are NOT deleted automatically — call pim.products.attributes.set with mode=replace afterwards if you want to drop them. Idempotent. Response: { productId, traitIds, removed: count }. Errors: { error: { code: 'not_found', ... } }.
  • imports.mappings.applyPure transform: apply column→attribute mappings to a list of source records and return per-row attribute payloads ready for downstream writes. NO DB writes happen here. Each rule maps `sourceColumn` (a key in the record) to `destinationAttributeDefinitionId` (an attribute definition in the target schema), with an optional `role` tag (uniqueIdentifier, productGroup, name, brand, category, mainImage, productType). The mapping engine performs type coercion against the destination's DataType (e.g. string '42' → 42 for Number) and reports per-row errors and warnings. Recommended downstream flow: use the role-tagged values (especially uniqueIdentifier) as the externalId for `pim.products.batch.create`, then write the per-row attributes via `pim.products.attributes.set`. Response: { targetSchemaId, ruleCount, recordCount, skippedRules: [{ ruleIndex, reason }], items: [{ rowIndex, isSuccess, attributes: [{ attributeDefinitionId, code, dataType, value }], roles: { [role]: value }, errors: [...], warnings: [...] }] }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • imports.smartImports.listList SmartImports for the current tenant, newest first. Excludes the heavy `rawProducts` list from each entry — call imports.smartImports.get to fetch one in full. Optional `status` filter narrows by lifecycle state. Response: { smartImports: [{ id, status, mode, originalFileName, productCount, variantCount, createdAt, updatedAt }] }. Errors: { error: { code: 'bad_input', ... } }.
  • jobs.getPoll a background job's state. Status values: queued, processing, success, failed. `progress` is a 0.0–1.0 fraction (null when the job hasn't reported any). Tenant-scoped: agents can only see jobs in their own tenant. Response: { jobId, kind, status, progress, retryCount, started, lastAlive, cancellationRequested }. Errors: { error: { code: 'not_found', ... } }.
  • pim.attributeDefinitions.allowedValues.setReplace the allowed-value list for an enum/multiEnum attribute definition. Idempotent on `value`: values present in input but not in storage are inserted, values present in both have their labels/sortOrder/isActive updated, values present in storage but absent from input are deleted. After this call HasAllowedValues is true iff the resulting list is non-empty. Response: { attributeDefinitionId, added, updated, deleted }. Errors: { error: { code: 'not_found' | 'unprocessable', ... } }.
  • pim.products.categories.addAdd product to one or more categories. Idempotent — already-assigned categories are no-ops. Response: { productId, categoryIds, added: count }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.channels.removeUnpublish product from one or more channels. Idempotent. Response: { productId, channelCodes, removed: count }. Errors: { error: { code: 'not_found', ... } }.
  • pim.schemas.getGet a PIM schema by id, with productTypes, traits, attributeDefinitions, and channels embedded. Use the optional `fields` param to limit the response to specific top-level keys when the full payload is too large. Allowed `fields` values: schema, productTypes, traits, attributeDefinitions, channels. Response: { schema?: {...}, productTypes?: [...], traits?: [...], attributeDefinitions?: [...], channels?: [...] }. Errors: { error: { code: 'not_found' | 'forbidden', ... } }.
  • imports.smartImports.startUpload + analyze inline file content. Supported formats: 'csv' (text/csv) and 'wawiJson' (WAWI-style JSON product feed with FTITLES/FVALUES/DETAIL fields). XLSX is intentionally not supported via MCP in v1 — agents that need XLSX should convert to CSV client-side or use the HTTP API. Returns a SmartImport in Analyzed state with field inventory ready for inference. Response: { smartImport: {...} }. Errors: { error: { code: 'bad_input' | 'unprocessable', ... } }.
  • pim.products.attributes.setSet or merge attribute values on a product (or a specific variant). `mode=merge` (default) upserts only the provided values; existing values for other attributes are left untouched. `mode=replace` upserts the provided values AND deletes any other existing attribute values on the entity, leaving exactly the provided set. Each value is sent as native JSON matching its definition's DataType (string for Text, number for Number/Decimal, bool for Boolean, ["..."] for MultiEnum / arrays, {"en":"...","de":"..."} for translatable Text). When `variantId` is set, the variant must belong to `productId` and the same tenant; attribute scope must match the target entity (product-scoped defs onto product, variantDefining/perVariant defs onto variant) — mismatches are reported in `skipped` with reason `scope_mismatch`. Other skip reasons: `missing_attribute_definition_id`, `definition_not_in_schema`, `value_parse_error: <detail>`. In `mode=replace`, attributes the caller listed but whose value couldn't parse are NOT deleted — only attributes the caller didn't mention at all. Response: { productId, variantId, applied, deleted, skipped: [{ attributeDefinitionId, reason }] }. Errors: { error: { code: 'not_found' | 'bad_input' | 'unprocessable', ... } }.
  • pim.products.status.setSet the product's lifecycle status. Allowed values: draft, active, archived, requiresAttention. Use this for 'soft delete' (status=archived); there is no hard delete via MCP in v1. Response: { productId, status }. Errors: { error: { code: 'not_found', ... } }.
  • pim.productTypes.listList product types in a schema. ProductTypes are the flat product classification within a schema (NOT to be confused with categories, which are sales navigation). Response: { productTypes: [{ id, schemaId, code, labels, defaultTraitIds, parentCode, level, isActive, productCount }] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.traits.attributes.removeUnbind attribute definitions from a trait — clears their `traitId` only when it equals the given trait. Definitions bound to other traits are left untouched. Idempotent. Response: { traitId, attributeDefinitionIds, unbound: count, skipped: [{ id, reason }] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.channels.attributeConfig.setReplace the channel's per-attribute config overlay. Each entry binds an attribute definition to per-channel `isRequired`, `labelOverrides`, `exportKey`, and `sortOrder`. The channel's underlying schema must contain every referenced attribute definition; mismatches are skipped. Pass [] to clear the overlay (the channel falls back to the schema's defaults). Response: { channelId, applied: count, skipped: [{ attributeDefinitionId, reason }] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.searchSearch products in the current tenant. At most one filter dimension is honored at a time (in priority order: query > schemaId > productTypeId > categoryId > channelCode > traitId). If none are set, returns the tenant's products in default order. Pagination: 1-indexed `page` + `pageSize` (max 50). Response: { products: [{ id, schemaId, primaryTypeId, traitIds, categoryIds, channelCodes, skuList, productNumber, status, purpose, sourceSystem, sourceSystemProductId, updatedAt }], page, pageSize, totalCount, totalPages }. Errors: { error: { code: 'bad_input', ... } }.
  • pim.attributeDefinitions.getGet an attribute definition by id, with full metadata (validation rules, allowed-value count, guidance text, unit conversion config). To enumerate the actual allowed values, call pim.attributeDefinitions.allowedValues.list (Phase 2). Response: { attributeDefinition: {...} }. Errors: { error: { code: 'not_found', ... } }.
  • pim.productTypes.createCreate a product type in a schema, or return the existing one if `code` already exists in the schema. ProductType is the flat product classification within a schema (NOT category/sales nav). Response: { productType: {...}, created: bool }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.schemas.set.defaultChannelsSet the schema's default channel codes — the codes auto-assigned to new products in this schema. This replaces the existing list. Pass [] to clear. Response: { schemaId, defaultChannelCodes }. Errors: { error: { code: 'not_found', ... } }.
  • pim.schemas.listList PIM schemas in the current tenant. By default returns only tenant-owned, editable schemas (Master + Recipient). To inspect Import (file-import) or Standard (eClass/ETIM/UNSPSC) or Connector schemas, pass `kind` explicitly. Response: { schemas: [{ id, name, kind, contentLanguage, productTypeCount, traitCount, categoryCount, attributeDefinitionCount, isReadOnly, updatedAt }] }. Errors: { error: { code: 'bad_input', ... } }.
  • pim.channels.createCreate a channel for the current tenant, or return the existing one if `code` already exists. Channels are thin distribution-target overlays on a master schema. To customize per-channel attribute requirements after creation, use pim.channels.attributeConfig.set. Response: { channel: {...}, created: bool }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • imports.smartImports.reviewReplace the SmartImport's inferred schema with the agent's adjusted version, transitioning the import to Reviewed. The schema shape is the same one returned in imports.smartImports.get's `inferredSchema` field — typically the agent fetches it, edits names/codes/grouping in its own context, and submits the result here. Response: { smartImport: {...} }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • imports.smartImports.runInferenceEnqueue the AI inference job for a SmartImport. The SmartImport must be in Analyzed state; transitions to Inferring. Inference runs as a background job — poll imports.smartImports.get periodically until status becomes Inferred (or Failed). Response: { smartImport: {...} }. Errors: { error: { code: 'not_found' | 'unprocessable', ... } }.
  • pim.attributeDefinitions.aliases.setReplace the attribute definition's alias list. Aliases are alternate names used during import matching (e.g. 'Gewicht' as a German alias for 'weight'). Pass [] to clear. Response: { attributeDefinitionId, aliases }. Errors: { error: { code: 'not_found', ... } }.
  • pim.products.getGet a single product with its variants and resolved attribute values. Use the optional `fields` whitelist to skip heavy sections when payload size matters. Allowed `fields` values: product, attributes, variants, channelStatuses. Attribute values are returned in their native JSON shape (string/number/bool/{lang:value}/["..."]) matching the PimValue wire format used by the HTTP API. Each attribute carries its definition code + dataType so the agent can interpret the value without a separate lookup. Response: { product?: {...}, attributes?: [{ attributeDefinitionId, code, dataType, scope, unit, value, updatedAt }], variants?: [{ id, sku, name, ean, gtin, attributes: [...] }], channelStatuses?: [...] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.attributeDefinitions.listList attribute definitions in a schema. Pass `traitId` to scope to a single trait, or pass `includeGlobalOnly=true` to get only global (non-trait-scoped) attributes. Response: { attributeDefinitions: [{ id, schemaId, traitId, code, labels, dataType, unit, isRequired, isTranslatable, scope, role, hasAllowedValues, allowedValueCount }] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.traits.listList traits in a schema. Traits are reusable groups of attribute definitions; products opt in to traits to gain their attributes. Response: { traits: [{ id, schemaId, code, labels, sortOrder, isActive }] }. Errors: { error: { code: 'not_found', ... } }.
  • pim.channels.listList channels (distribution targets) for the current tenant. Optionally scope to a single schema. Response: { channels: [{ id, code, labels, country, schemaId, minReadinessPercent, tags, isActive, attributeConfigCount }] }. Errors: { error: { code: 'bad_input', ... } }.
  • pim.products.archiveSoft-archive a product. Equivalent to pim.products.status.set with status=archived. Response: { productId, status: 'archived' }. Errors: { error: { code: 'not_found', ... } }.
  • pim.schemas.set.defaultAiRoleSet the schema's default LLM role/context (the system-prompt-style preamble used in AI ops). Pass null to clear. Response: { schemaId, defaultAiRole }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • imports.smartImports.executeFinalize a SmartImport: create the PIM schema, traits, attribute definitions, products, variants, and attribute values. Synchronous — may take seconds for large imports. The SmartImport must be in Reviewed state. Transitions to Complete (or Failed on error). Response: { smartImport: {...} } with createdSchemaId, importedProductCount, importedVariantCount populated. Errors: { error: { code: 'not_found' | 'unprocessable', ... } }.
  • pim.products.createCreate or upsert a single product by (sourceSystem, externalId). Re-running the same call returns the same productId and updates the existing record — never creates a duplicate. For ad-hoc creates with no upstream system, pass sourceSystem='mcp' (or another stable string the agent owns) so subsequent runs from the same agent stay idempotent. Response: { productId, sourceSystem, externalId, action: 'created'|'updated' }. Errors: { error: { code: 'not_found' | 'bad_input', ... } }.
  • pim.schemas.createCreate a tenant-owned PIM schema, or return the existing one if `name` already exists for this tenant. Only Master and Recipient kinds are creatable via MCP — Standard (eClass/ETIM/UNSPSC) and Connector schemas are platform-managed. Response: { schema: {...}, created: bool }. Errors: { error: { code: 'bad_input', ... } }.
  • pim.traits.attributes.addBind one or more attribute definitions to a trait by setting their `traitId`. Each attribute definition in the list has its `traitId` updated to the given trait. Idempotent — already-bound definitions are no-ops. Definitions in other schemas or other tenants are skipped with a reason. Response: { traitId, attributeDefinitionIds, bound: count, skipped: [{ id, reason }] }. Errors: { error: { code: 'not_found', ... } }.
  • imports.smartImports.getGet a SmartImport by id. By default returns the metadata + field inventory + inferred schema (when present); the raw products list is omitted unless explicitly requested since it can be large. Response: { smartImport: {...}, fieldInventory?, inferredSchema?, rawProductCount, errorMessage? }. Errors: { error: { code: 'not_found', ... } }.

Last checked May 26, 2026

Screenshot

FacetFlux screenshot

[ features ]

Product Data Management

Core capabilities for managing product data including import, validation, versioning, and localization.

Bulk Import/Export

Ability to import and export large volumes of product data via CSV, Excel, or other formats.

yes  ]
Data Validation Rules

Configurable rules to validate product data quality and completeness.

yes  ]
Version History

Track changes to product data over time with ability to rollback.

no
Inheritance/Variants

Support for product variants with inherited attributes from parent products.

yes  ]
Localization Support

Multi-language support for product content.

yes  ]
Number of Languages

How many languages are supported out of the box.

16

Supplier Portal

Capabilities for supplier onboarding, data collection, and collaboration.

Supplier Self-Service

Portal where suppliers can directly update their product information.

no
Supplier Onboarding Workflow

Structured process for onboarding new suppliers with approvals.

yes  ]
Data Quality Scoring

Automated scoring of supplier-provided data quality.

yes  ]
Supplier Performance Tracking

Analytics on supplier data quality and response times.

no
Branded Portal

White-label supplier portal with custom branding.

no

Compliance & Security

Security certifications, compliance features, and access control capabilities.

SOC 2

SOC 2 Type I or Type II certification.

None
ISO 27001

ISO 27001 information security certification.

no
GDPR Tools

Built-in tools for GDPR compliance (data export, deletion, consent).

no
Audit Trail

Complete audit log of all data changes.

no
Role-Based Access Control

Granular permissions based on user roles.

no
SSO Support

Single Sign-On integration support.

None

eCommerce Integrations

Connectivity with other systems including DAM, ERP, e-commerce platforms, and marketplaces.

DAM Integration

Integration with Digital Asset Management systems.

no
ERP Integration

Native integrations with ERP systems.

E-commerce Connectors

Pre-built connectors for e-commerce platforms.

Shopify  ]
Marketplace Syndication

Direct syndication to online marketplaces.

Amazon  ]
API Access

Type of API available for custom integrations.

REST
Webhook Support

Outbound webhooks for event-driven integrations.

no

Listing AI & Automation

Artificial intelligence and automation capabilities for content generation, categorization, and optimization.

AI Content Generation

AI-powered generation of product descriptions and content.

no
AI Image Enhancement

AI tools for image optimization, background removal, etc.

no
Automated Categorization

AI-powered automatic product categorization.

yes  ]
Smart Attribute Extraction

Automatic extraction of product attributes from descriptions or images.

yes  ]
AI/MT Translation

Built-in machine translation for product content.

no

eCommerce Publishing & Channels

Capabilities for distributing product content across multiple channels and formats.

Multi-channel Publishing

Publish product data to multiple channels from a single source.

yes  ]
Print Catalog Generation

Generate print-ready catalogs and datasheets.

no
Headless/API-first

API-first architecture for headless commerce.

yes  ]
Digital Shelf Analytics

Analytics on product performance across digital channels.

no
Scheduled Publishing

Schedule product updates to go live at specific times.

no

Reviews

0 reviews
Write a Review

No reviews yet. Be the first to review FacetFlux!