> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omnicommerce.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview Duplicate Product Merge

> Read-only preview of merging duplicate catalog products into one master product. Uses the same contract and rules as `POST /api/v1/products/duplicates/merge` and the assistant's Fix Listing Duplicates tool.

Products are grouped by exact SKU. Each group shows its master (first in `productIds`), every product's marketplace listings per store with live status. A blocked group reports its `error`; nothing is changed.

Supports every OmniCommerce marketplace. All marketplace listings are preserved. Different listing identities in the same store block that group; the merge never delists listings.

Discover candidates with `GET /api/v1/products?status=duplicates&duplicateType=sku&detail=full`. Refresh the saved scan through `POST /api/v1/products/duplicates/scan` when needed. Each group's `masterSelections[]` contains productId, allowed and a seller-facing note, matching the UI's enabled/disabled master choices. A sole allowed choice must be master to retain stock connections. No allowed choices means the group cannot merge. Several allowed choices require deciding which product's content, price and stock to keep; no universal best master is inferred.

A preview can return HTTP 200 with ok=false and still provide usable groups/masterSelections. For stock_source_requires_master, choose an allowed master and preview again. Once every selected group succeeds, pass the reviewed groups' productIds (master first) and sku as expectedGroups to merge. Preview is read-only and does not publish to marketplaces.

### Authorization

Requires `catalog:read`.



## OpenAPI

````yaml /openapi.json post /api/v1/products/duplicates/merge-preview
openapi: 3.1.0
info:
  title: OmniCommerce API
  version: 1.0.0
  license:
    name: Proprietary
    url: https://omnicommerce.sg/terms
  description: >-
    OmniCommerce API surface for agents and developer integrations. Includes
    public endpoints (merchant discovery, product search, compare, catalog, ACO
    retrieval) and authenticated endpoints (product management via API key
    Bearer tokens).
servers:
  - url: https://omnicommerce.ai
    description: Production
  - url: http://localhost:3000
    description: Local development
security: []
tags:
  - name: agentic-checkout
    description: Merchant-fulfilled agentic checkout
    x-group: Agentic Checkout
  - name: agents
    description: agents
    x-group: Agents
  - name: analytics
    description: Sales performance across marketplaces
    x-group: Analytics
  - name: aops
    description: Agent operating procedures
    x-group: AOPs
  - name: branding
    description: branding
    x-group: Branding
  - name: campaigns
    description: Campaign briefs, offer windows, and marketplace runs
    x-group: Campaigns
  - name: catalog
    description: catalog
    x-group: Catalog
  - name: commerce
    description: commerce
    x-group: Commerce
  - name: developer-platform
    description: Authenticated developer platform APIs
    x-group: Developer Platform
  - name: documents
    description: Knowledge base document uploads
    x-group: Knowledge Base
  - name: inventory
    description: Inventory quantities, planning signals, and marketplace listing absence
    x-group: Inventory
  - name: looks
    description: AI-styled product looks
    x-group: Looks
  - name: oauth
    description: OAuth token endpoints
    x-group: OAuth
  - name: orders
    description: Workspace and agentic orders
    x-group: Orders
  - name: organizations
    description: Organization management
    x-group: Organizations
  - name: price-books
    description: Marketplace list-price markup rules
    x-group: Price Books
  - name: products
    description: Product CRUD, bulk import, enrichment, publish, and delist
    x-group: Products
  - name: promotions
    description: Central promotions and marketplace sync
    x-group: Promotions
  - name: public-agent
    description: Public agent discovery and catalog APIs
    x-group: Public Agent
  - name: returns
    description: returns
    x-group: Returns
  - name: reviews
    description: Marketplace product reviews and seller replies
    x-group: Reviews
  - name: scripts
    description: scripts
    x-group: Scripts
  - name: settlements
    description: settlements
    x-group: Settlements
  - name: ucp
    description: Universal Commerce Protocol
    x-group: UCP
paths:
  /api/v1/products/duplicates/merge-preview:
    post:
      tags:
        - products
      summary: Preview Duplicate Product Merge
      description: >-
        Read-only preview of merging duplicate catalog products into one master
        product. Uses the same contract and rules as `POST
        /api/v1/products/duplicates/merge` and the assistant's Fix Listing
        Duplicates tool.


        Products are grouped by exact SKU. Each group shows its master (first in
        `productIds`), every product's marketplace listings per store with live
        status. A blocked group reports its `error`; nothing is changed.


        Supports every OmniCommerce marketplace. All marketplace listings are
        preserved. Different listing identities in the same store block that
        group; the merge never delists listings.


        Discover candidates with `GET
        /api/v1/products?status=duplicates&duplicateType=sku&detail=full`.
        Refresh the saved scan through `POST /api/v1/products/duplicates/scan`
        when needed. Each group's `masterSelections[]` contains productId,
        allowed and a seller-facing note, matching the UI's enabled/disabled
        master choices. A sole allowed choice must be master to retain stock
        connections. No allowed choices means the group cannot merge. Several
        allowed choices require deciding which product's content, price and
        stock to keep; no universal best master is inferred.


        A preview can return HTTP 200 with ok=false and still provide usable
        groups/masterSelections. For stock_source_requires_master, choose an
        allowed master and preview again. Once every selected group succeeds,
        pass the reviewed groups' productIds (master first) and sku as
        expectedGroups to merge. Preview is read-only and does not publish to
        marketplaces.


        ### Authorization


        Requires `catalog:read`.
      operationId: post_v1_products_duplicates_merge_preview
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - productIds
              properties:
                dryRun:
                  type: boolean
                  description: >-
                    True runs the same merge transaction and rolls it back,
                    including database reference/constraint validation. No
                    product changes are saved, no mutation events or duplicate
                    refreshes run, and marketplace listings stay unchanged.
                    Requires catalog:write. Omitted/false performs the reviewed
                    merge. This differs from CLI --dry-run, which only prints a
                    request.
                organizationId:
                  type: string
                  description: >-
                    Required only for session-authenticated calls. API
                    credentials use their own organization.
                productIds:
                  type: array
                  minItems: 2
                  maxItems: 20
                  items:
                    type: string
                    minLength: 1
                    maxLength: 255
                  description: >-
                    Ordered standalone catalog product IDs. Products are grouped
                    by exact SKU; each group merges into one master.
                masterProductIds:
                  type: array
                  minItems: 1
                  maxItems: 10
                  items:
                    type: string
                    minLength: 1
                    maxLength: 255
                  description: >-
                    Optional master per SKU group, chosen from productIds; at
                    most one per group. Defaults to the first requested product
                    of each group. The master keeps its content, images, price
                    and stock.
                expectedGroups:
                  type: array
                  minItems: 1
                  maxItems: 10
                  description: >-
                    Optional groups from a preview to pin: membership, master
                    (first product) and SKU. Groups that changed or are omitted
                    are not merged.
                  items:
                    type: object
                    additionalProperties: false
                    required:
                      - productIds
                      - sku
                    properties:
                      productIds:
                        type: array
                        minItems: 2
                        maxItems: 20
                        items:
                          type: string
                          minLength: 1
                          maxLength: 255
                      sku:
                        type: string
                        minLength: 1
                        maxLength: 255
                explanation:
                  type: string
                  maxLength: 2000
            example:
              productIds:
                - 4d3c2b1a-0000-4000-8000-000000000001
                - 4d3c2b1a-0000-4000-8000-000000000002
              masterProductIds:
                - 4d3c2b1a-0000-4000-8000-000000000002
      responses:
        '200':
          description: >-
            Read-only preview, including product details, per-store listings and
            structured master eligibility. ok=false is a domain-level block;
            inspect data.groups even then.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  apiVersion:
                    type: string
                  operationId:
                    type: string
                  status:
                    type: string
                    enum:
                      - accepted
                      - completed
                      - failed
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      productIds:
                        type: array
                        items:
                          type: string
                      survivingProductId:
                        anyOf:
                          - type: string
                          - type: 'null'
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            productId:
                              type: string
                            name:
                              type: string
                            sku:
                              anyOf:
                                - type: string
                                - type: 'null'
                            imageUrl:
                              anyOf:
                                - type: string
                                - type: 'null'
                            price:
                              anyOf:
                                - type: string
                                - type: 'null'
                            currency:
                              anyOf:
                                - type: string
                                - type: 'null'
                            inventoryQuantity:
                              anyOf:
                                - type: number
                                - type: 'null'
                            marketplaces:
                              type: array
                              items:
                                type: object
                                properties:
                                  platform:
                                    type: string
                                    enum:
                                      - shopee
                                      - lazada
                                      - tiktok
                                      - shopify
                                      - whatsapp
                                      - zalora
                                      - amazon
                                      - ebay
                                  storeId:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  itemId:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  live:
                                    type: boolean
                                required:
                                  - platform
                                  - storeId
                                  - itemId
                                  - live
                                additionalProperties: false
                          required:
                            - productId
                            - name
                            - sku
                            - imageUrl
                            - price
                            - currency
                            - inventoryQuantity
                            - marketplaces
                          additionalProperties: false
                      error:
                        type: string
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            success:
                              type: boolean
                            productIds:
                              type: array
                              items:
                                type: string
                            survivingProductId:
                              anyOf:
                                - type: string
                                - type: 'null'
                            products:
                              type: array
                              items:
                                type: object
                                properties:
                                  productId:
                                    type: string
                                  name:
                                    type: string
                                  sku:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  imageUrl:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  price:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  currency:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                  inventoryQuantity:
                                    anyOf:
                                      - type: number
                                      - type: 'null'
                                  marketplaces:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        platform:
                                          type: string
                                          enum:
                                            - shopee
                                            - lazada
                                            - tiktok
                                            - shopify
                                            - whatsapp
                                            - zalora
                                            - amazon
                                            - ebay
                                        storeId:
                                          anyOf:
                                            - type: string
                                            - type: 'null'
                                        itemId:
                                          anyOf:
                                            - type: string
                                            - type: 'null'
                                        live:
                                          type: boolean
                                      required:
                                        - platform
                                        - storeId
                                        - itemId
                                        - live
                                      additionalProperties: false
                                required:
                                  - productId
                                  - name
                                  - sku
                                  - imageUrl
                                  - price
                                  - currency
                                  - inventoryQuantity
                                  - marketplaces
                                additionalProperties: false
                            error:
                              type: string
                            sku:
                              anyOf:
                                - type: string
                                - type: 'null'
                            masterSelections:
                              type: array
                              items:
                                type: object
                                properties:
                                  productId:
                                    type: string
                                  allowed:
                                    type: boolean
                                  note:
                                    anyOf:
                                      - type: string
                                      - type: 'null'
                                required:
                                  - productId
                                  - allowed
                                  - note
                                additionalProperties: false
                            errorCode:
                              type: string
                              const: stock_source_requires_master
                          required:
                            - success
                            - productIds
                            - survivingProductId
                            - products
                            - sku
                          additionalProperties: false
                    required:
                      - success
                      - productIds
                      - survivingProductId
                      - products
                      - groups
                    additionalProperties: false
                  error:
                    type: string
                  warnings:
                    type: array
                    items:
                      type: string
                  recommendations:
                    type: array
                    items:
                      type: string
                  links:
                    type: object
                    propertyNames:
                      type: string
                    additionalProperties:
                      type: string
                required:
                  - ok
                  - apiVersion
                  - operationId
                  - status
                  - data
                  - warnings
                  - recommendations
                  - links
                additionalProperties: false
        '400':
          description: Invalid payload.
        '401':
          description: Unauthorized
        '403':
          description: Credential lacks catalog:read.
        '500':
          description: Internal Server Error
      security:
        - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Bearer API key for server-to-server access. Session auth is also
        supported in first-party UI flows.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.