Elastic Path Product Import/Bulk Update API

```mdx-code-block import ProductImport from '/docs/partials/pxm/import/import.mdx'; ``` #### Using Imported Main Image Files You can use the main images that you have previously uploaded to Commerce and assign them to your products when importing products to Commerce. You can do this by adding a `main_image_id` header to your `.csv` file. The ID you provide in `main_image_id` is the ID of a file that has already been uploaded to Commerce using create a file. #### Importing Custom Data (Flows) You can also create/update custom extension data in a `.csv` file by creating a header that includes the flow `ID` and the field `slug` in the following format: template:*flowID*:*fieldSlug*. where: - `template` must be `template`. - `flowID` is the ID of the flow that contains the field whose data you want to create/update. - `fieldSlug` is the slug of the field whose data you want to create/update. In the following example, for a flow with ID `82c10a02-1851-4992-8ecb-d44f2782d09b` and a field with the slug `condition`: - the header is `template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition`. - the updated custom data is `as-new`. | name | slug | sku | status | template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition | | :--- | :--- | :--- | :--- | :--- | | BestEver Range | bestever-range-1a1a-30 | BE-Range-1a1a-30 | draft | as-new | #### Characteristics of CSV Import Files Product Import uses a [**Comma Separated Values (CSV)**](#characteristics-of-csv-import-files) file to import/update products, main image files, and custom extension data. - Each row in a `.csv` file represents a product you want to create/update. - Each file: - must not be larger than 50 megabytes. If a `.csv` file is larger than 50 megabytes, a `503 client read error` is displayed. - must not have more than 50,000 rows, including the header. If a CSV file exceeds 50,000 rows, an error is displayed, and the products are not imported. In other words, if you have a file with 50,000 rows that is larger than 50 megabytes, an error is displayed, and the products are not imported. - If you want to create/update more than 50,000 products or your `.csv` file is larger than 50 megabytes, you must have a separate `.csv` file and import each `.csv` file one at a time. - You can update existing products, including images, templates/flow fields, and entries. The entry in the `.csv` file must have a unique `id` and/or `external_ref` that matches the `id` and `external_ref` of the existing product you want to update. You may have both a unique `id` and `external_ref`, but you must have at least one. - You can add new products. For new products that you want to add, the entry in the `.csv` file must have an `external_ref` that does not match any existing products. The following table describes the headers that are supported. | Header | Required | Description | |:---- |:---------|:--| | id | Optional | A unique product ID that is generated when you create the product. The `id` is used to look up products in the `.csv` file and matches them to the products in your storefront that you want to update. | | external_ref | Optional | A unique attribute associated with a product. This could be an external reference from a separate company system, for example. The maximum length is 2048 characters. | | name | Required | The name of a product. | | description | Required | A description for a product. You can include quotes in your product description, if you want to emphasize a word, for example. To do this, put quotes around the product description. For example, "This product description describes my "product" and the product "version"." | | slug | Required | A label for the product that is used in the URL paths. A slug can contain any combination of letters, numbers, periods, hyphens, and underscores. NO spaces or other characters are allowed. By default, the product name is used as the slug. | | status | Required | The status of a product, either `Draft` or `Live`. | | commodity_type | Required | The commodity type, either `physical` or `digital`. | | upc_ean | Optional | The universal product code or european article number of the product. | | mpn | Optional | The manufacturer part number of a product. | | sku | Optional | The unique stock keeping unit of the product. | | tags | Optional | The product tags used to store or assign a key word against a product. A product can have up to 20 product tags. A product tag can be up to 255 characters. See [**Product Tags**](/docs/api/pxm/products/product-tags). | main_image_id | Optional | Specifies a unique ID of a main image file for a product. You can include a `main_image_id` for your products for images that are already uploaded to Commerce. See [**Using Main Image Files**](#importing-custom-data-flows). | | `template::` | Optional | You can also specify custom extension data in the CSV by specifying the flow `ID` or `slug` and the field `name`. For example, `template::` format. See [**Importing Custom Data (Flows)**](#importing-custom-data-flows). |

OpenAPI Specification

elastic-path-product-import-bulk-update-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  version: 25.1126.6886238
  x-version-timestamp: 2025-11-26 19:10:23+00:00
  title: Addresses Introduction Account Addresses Product Import/Bulk Update API
  description: 'The Addresses API allows you to organize account addresses. Addresses are a sub-resource of `account` resources, an account can have multiple addresses, such as home, work, and neighbour.


    You can use an account address with either [client_credentials access token](/docs/api/authentication/create-an-access-token) or a combination of [implicit access token](/docs/api/authentication/create-an-access-token) and [Account Management authentication](/docs/api/accounts/post-v-2-account-members-tokens) token.

    '
  contact:
    name: Elastic Path
    url: https://www.elasticpath.com
    email: support@elasticpath.com
  license:
    url: https://elasticpath.dev
    name: MIT
servers:
- url: https://useast.api.elasticpath.com
  description: US East
- url: https://euwest.api.elasticpath.com
  description: EU West
security:
- BearerToken: []
tags:
- name: Product Import/Bulk Update
  description: "```mdx-code-block\nimport ProductImport from '/docs/partials/pxm/import/import.mdx';\n\n<ProductImport />\n```\n\n#### Using Imported Main Image Files\n\nYou can use the main images that you have previously uploaded to Commerce and assign them to your products when importing products to Commerce. You can do this by adding a `main_image_id` header to your `.csv` file. The ID you provide in `main_image_id` is the ID of a file that has already been uploaded to Commerce using create a file.\n\n#### Importing Custom Data (Flows)\n\nYou can also create/update custom extension data in a `.csv` file by creating a header that includes the flow `ID` and the field `slug` in the following format: \n\ntemplate:*flowID*:*fieldSlug*.\n\nwhere:\n\n- `template` must be `template`.\n- `flowID` is the ID of the flow that contains the field whose data you want to create/update.\n- `fieldSlug` is the slug of the field whose data you want to create/update.\n\nIn the following example, for a flow with ID `82c10a02-1851-4992-8ecb-d44f2782d09b` and a field with the slug `condition`:\n\n- the header is `template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition`.\n- the updated custom data is `as-new`.\n\n    | name | slug | sku | status | template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition |\n    | :--- | :--- | :--- | :--- | :--- |\n    | BestEver Range | bestever-range-1a1a-30 | BE-Range-1a1a-30 | draft | as-new |\n\n#### Characteristics of CSV Import Files\n\nProduct Import uses a [**Comma Separated Values (CSV)**](#characteristics-of-csv-import-files) file to import/update products, main image files, and custom extension data. \n\n- Each row in a `.csv` file represents a product you want to create/update. \n- Each file:\n    - must not be larger than 50 megabytes. If a `.csv` file is larger than 50 megabytes, a `503 client read error` is displayed.\n    - must not have more than 50,000 rows, including the header. If a CSV file exceeds 50,000 rows, an error is displayed, and the products are not imported.\n    In other words, if you have a file with 50,000 rows that is larger than 50 megabytes, an error is displayed, and the products are not imported.\n- If you want to create/update more than 50,000 products or your `.csv` file is larger than 50 megabytes, you must have a separate `.csv` file and import each `.csv` file one at a time.\n- You can update existing products, including images, templates/flow fields, and entries. The entry in the `.csv` file must have a unique `id` and/or `external_ref` that matches the `id` and `external_ref` of the existing product you want to update. You may have both a unique `id` and `external_ref`, but you must have at least one.\n- You can add new products. For new products that you want to add, the entry in the `.csv` file must have an `external_ref` that does not match any existing products.\n\nThe following table describes the headers that are supported.\n\n| Header | Required | Description  |\n|:---- |:---------|:--|\n| id                              | Optional | A unique product ID that is generated when you create the product. The `id` is used to look up products in the `.csv` file and matches them to the products in your storefront that you want to update.                                                                                                                                                                                                       |\n| external_ref                    | Optional | A unique attribute associated with a product. This could be an external reference from a separate company system, for example. The maximum length is 2048 characters.                                                                                                                                                                                                                                         |\n| name                            | Required | The name of a product.                                                                                                                                                                                                                                                                                                                                                                                        |\n| description                     | Required | A description for a product. You can include quotes in your product description, if you want to emphasize a word, for example. To do this, put quotes around the product description. For example, \"This product description describes my \"product\" and the product \"version\".\"                                                                                                                               |\n| slug                            | Required | A label for the product that is used in the URL paths. A slug can contain any combination of letters, numbers, periods, hyphens, and underscores. NO spaces or other characters are allowed. By default, the product name is used as the slug.                                                                                                                                                                |\n| status                          | Required | The status of a product, either `Draft` or `Live`.                                                                                                                                                                                                                                                                                                                                                            |\n| commodity_type                  | Required | The commodity type, either `physical` or `digital`.                                                                                                                                                                                                                                                                                                                                                           |\n| upc_ean                         | Optional | The universal product code or european article number of the product.                                                                                                                                                                                                                                                                                                                                         |\n| mpn                             | Optional | The manufacturer part number of a product.                                                                                                                                                                                                                                                                                                                                                                    |\n| sku                             | Optional | The unique stock keeping unit of the product.                                                                                                                                                                                                                                                                                                                                                                 |\n| tags                             | Optional | The product tags used to store or assign a key word against a product. A product can have up to 20 product tags. A product tag can be up to 255 characters. See [**Product Tags**](/docs/api/pxm/products/product-tags).\n| main_image_id                   | Optional | Specifies a unique ID of a main image file for a product. You can include a `main_image_id` for your products for images that are already uploaded to Commerce. See [**Using Main Image Files**](#importing-custom-data-flows).                                                                                                                                                                                        |\n| `template:<flowID>:<fieldSlug>` | Optional | You can also specify custom extension data in the CSV by specifying the flow `ID` or `slug` and the field `name`. For example, `template:<flowSlug>:<fieldName>` format. See [**Importing Custom Data (Flows)**](#importing-custom-data-flows). |\n"
paths:
  /pcm/products/import:
    post:
      summary: Import Products
      description: "\nYou can use the Product Import API to:\n\n- Add new products, including:\n\n    - main image files. See [Importing Main Image Files](/docs/api/pxm/products/product-import-bulk-update#using-imported-main-image-files).\n    - custom data. See [Importing custom data](/docs/api/pxm/products/product-import-bulk-update#importing-custom-data-flows).\n    - Make bulk updates to existing products.\n\nYou cannot use product import to:\n\n- Delete existing products.\n- Import product bundles.\n\nThe Product Import API uses a Comma Separated Values (CSV) file to import products, main image files, custom extension data, and admin and shopper attributes. Each row in a .csv file represents a product you want to create/update. See an [example file](/assets/pim_product_import_example.csv).\n\nEach file can have 50,000 rows, including the header. If a CSV file exceeds 50,000 rows, an error is displayed, and the products are not imported. A CSV file must not be larger than 50 megabytes. If a CSV file is larger than 50 megabytes, a `503 client read` error is displayed.\n\nIf you want to create/update more than 50,000 products or your CSV file is larger than 50 megabytes, you must have a separate CSV file and import each CSV file one at a time.\n\nSee [**Characteristics of CSV Files**](/docs/api/pxm/products/product-import-bulk-update#characteristics-of-csv-import-files).\n\n## Custom Attributes in CSV\n\nYou can set custom attributes on products using CSV columns with the prefixes `shopper_attributes.` or `admin_attributes.` followed by the attribute key name. For example:\n\n- `shopper_attributes.color` sets the `color` key on `shopper_attributes`.\n- `admin_attributes.cost_of_goods` sets the `cost_of_goods` key on `admin_attributes`.\n\n**Partial updates:** When updating an existing product, only the attribute keys present as columns in the CSV are affected. Attribute keys not included as columns are left unchanged.\n\n**Removing an attribute key:** To explicitly delete an attribute key from an existing product, set the cell value to `__REMOVE_ATTRIBUTE__`. This special sentinel value instructs the importer to remove that key from the product's custom attributes. An empty cell value is treated as a literal empty string, not a deletion.\n\n**New products:** For new products being created via import, any column whose value is `__REMOVE_ATTRIBUTE__` is ignored (the key is not created).\n"
      operationId: importProducts
      tags:
      - Product Import/Bulk Update
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  description: The file you want to upload. Ensure that the file format is Comma Separated Values (CSV).
                  type: string
                  format: binary
                  example: UploadFile
            examples:
              upload_image:
                summary: Upload Image
                value:
                  file: '@path/to/file'
      responses:
        '201':
          description: Import started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/single'
              examples:
                pending:
                  summary: Successful Job
                  $ref: '#/components/examples/import'
        '400':
          $ref: '#/components/responses/bad_request'
        '422':
          $ref: '#/components/responses/unprocessable_entity'
        '500':
          $ref: '#/components/responses/internal'
      parameters:
      - name: locale
        in: query
        description: "Specifies the locale to assist in parsing flow entry date values.\n\n- If a supported locale is provided, the system attempts to interpret dates using that locale's conventions. The import job fails if a date does not match one of the supported locale's formats.\n- If this parameter is omitted, or if the value provided is not on the supported list, the system proceeds using its default parsing logic. An unsupported locale is ignored and does not cause a failure.\n\n**Supported Locales and Date Formats:**\n\n**`en-US`**\n- `1/2/2006 15:04:05`\n- `01/02/2006 15:04:05`\n- `1/2/06 15:04`\n\n**`en-GB`**\n- `2/1/2006 15:04:05`\n- `02/01/2006 15:04:05`\n- `2/1/06 15:04`\n\n**`en-CA`**\n- `2/1/2006 15:04:05`\n- `02/01/2006 15:04:05`\n- `2/1/06 15:04`     \n\nAdditional locales and date formats can be added upon request.\n"
        required: false
        schema:
          type: string
          enum:
          - en-US
          - en-GB
          - en-CA
        example: en-US
components:
  responses:
    bad_request:
      description: Bad request. The request failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error'
          examples:
            bad-request:
              value:
                errors:
                - title: Bad Request
                  detail: Could not parse the supplied filter
                  status: '400'
    unprocessable_entity:
      description: Bad request. The request failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error'
          examples:
            failed-validation:
              value:
                errors:
                - title: Failed Validation
                  status: '422'
                  detail: <XYZ> can not be empty
    internal:
      description: Internal server error. There was a system failure in the platform.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error'
          examples:
            internal-server-error:
              value:
                errors:
                - status: '500'
                  title: Internal Server Error
                  detail: There was an internal server error, you can report with your request id.
                  request_id: 635da56d-75a1-43cd-b696-7ab119756b3a
  schemas:
    single:
      type: object
      required:
      - data
      properties:
        data:
          $ref: '#/components/schemas/job'
    error:
      required:
      - errors
      properties:
        errors:
          type: array
          items:
            required:
            - status
            - title
            properties:
              status:
                type: string
                description: The HTTP response code of the error.
                example: '500'
              title:
                type: string
                description: A brief summary of the error.
                example: Internal server error
              detail:
                type: string
                description: Optional additional detail about the error.
                example: An internal error has occurred.
              request_id:
                type: string
                description: Internal request ID.
                example: 00000000-0000-0000-0000-000000000000
              meta:
                type: object
                description: Additional supporting meta data for the error.
                example:
                  missing_ids:
                  - e7d50bd5-1833-43c0-9848-f9d325b08be8
    job:
      type: object
      required:
      - id
      - type
      - attributes
      - meta
      properties:
        id:
          description: A unique identifier generated when a job is created.
          type: string
        type:
          description: This represents the type of resource object being returned. Always `pim-job`.
          type: string
          enum:
          - pim-job
        attributes:
          type: object
          required:
          - started_at
          - completed_at
          - created_at
          - updated_at
          - type
          - status
          properties:
            started_at:
              description: The date and time a job is started.
              type: string
              example: '2020-09-22T09:00:00.000Z'
              format: date-time
              nullable: true
            completed_at:
              type: string
              example: '2020-09-22T09:00:00.000Z'
              format: date-time
              nullable: true
              description: The date and time a job is completed.
            created_at:
              type: string
              description: The date and time a job is created.
              example: '2020-09-22T09:00:00.000Z'
              format: date-time
            updated_at:
              type: string
              description: The date and time a job is updated.
              example: '2020-09-22T09:00:00.000Z'
              format: date-time
            type:
              type: string
              description: 'The status of a job.


                * `pending` - Commerce has received the request but is currently busy processing other requests.

                * `started` - Commerce has started processing the job.

                * `success` - The job has successfully completed.

                * `failed` - The job has failed.

                '
              enum:
              - child-products
              - product-import
              - product-export
              - hierarchy-duplicate
              - pricebook-import
              - pricebook-delete
              - hierarchy-delete
              - indexing-job
            status:
              type: string
              enum:
              - pending
              - cancelled
              - cancelling
              - started
              - success
              - failed
        meta:
          type: object
          required:
          - x_request_id
          properties:
            x_request_id:
              type: string
              description: Applies to all job types. A unique request ID is generated when a job is created.
            copied_from:
              type: string
              description: Applies to `hierarchy-duplicate` job types. The ID of the original hierarchy that you duplicated.
            hierarchy_id:
              type: string
              description: Applies to `hierarchy-duplicate` job types. The duplicated hierarchy ID.
            file_locations:
              type: array
              nullable: true
              description: If the job type is `product_export`, a link to the file is created when running a job.
              items:
                type: string
            filter:
              type: string
              nullable: true
              description: The entities included in the job. For example, if the job type is `product-export`, the PXM products included in the export.
  examples:
    import:
      value:
        data:
          type: pim-job
          id: 7e1b9ba1-c844-4556-9b16-4ae3f0988b0f
          attributes:
            completed_at: null
            created_at: '2024-01-05T15:27:23.161Z'
            started_at: null
            status: pending
            type: product-import
            updated_at: '2024-01-05T15:27:23.161Z'
          meta:
            x_request_id: fad8c5c0-9546-4e0c-b68e-8a2d809891e5
  securitySchemes:
    BearerToken:
      type: http
      scheme: bearer