---
title: "Upload a BOM file and read it into reviewable lines"
method: POST
path: "/pcf/products/{productId}/bom-imports"
---

# Upload a BOM file and read it into reviewable lines

`POST /pcf/products/{productId}/bom-imports`

Multipart upload (file, optional userPrompt of at most 500 characters) of an xlsx, csv, pdf or image file of at most 10 MiB. The AI gateway extracts the line items (name, quantity, unit, stage) and each line is matched against the PCF factor library; the call waits for both. The import is returned with status ready, or error when extraction failed (errorMessage says why; reanalyze retries). Nothing is written to the BOM until the import is applied. 503 AI_GATEWAY_UNAVAILABLE when the gateway is not configured. Requires org.write_data.

## Response `201`

The import, read and matched

- PcfBomImportResponse
  - `data` PcfBomImport, required
    - `appliedAt` string, date-time, nullable, required
    - `canReanalyze` boolean, required
    - `contentType` string, required
    - `createdAt` string, date-time, required
    - `documentProduct` PcfBomImportDocumentScope, required
      - `declaredQuantity` number, double, nullable, required
      - `declaredUnit` string, nullable, required
      - `name` string, nullable, required
    - `errorMessage` string, nullable, required
    - `extraction` PcfBomImportExtraction, required
      - `model` string, required
      - `provider` string, required
      - `traceId` string, nullable, required
    - `fileName` string, required
    - `id` string, required
    - `lines` PcfBomImportLine[], required
      - `candidates` PcfFactorCandidate[], required
        - `factor` PcfFactor, required
          - `activityCode` string, required
          - `activityUnit` string, required
          - `categoryName` string, required
          - `factorValue` number, double, required
          - `id` string, required
          - `name` string, required
          - `referenceProduct` string, nullable
          - `regionCode` string, required
          - `releaseId` string, required
          - `releaseName` string, required
          - `releaseVersion` string, required
          - `releaseYear` integer, nullable
          - `scope` integer, required
          - `sourceLocation` string, nullable
          - `sourceUuid` string, nullable
          - `split` PcfEmissionSplit — Fossil, biogenic and land-use-change parts of a GWP100 value, in the same unit as the value they split.
            - `biogenic` number, double, required
            - `fossil` number, double, required
            - `landUseChange` number, double, required
          - `unit` string, required
        - `regionMatch` 'exact' | 'regional' | 'global' | 'rest_of_world' | 'fallback' | 'unspecified', required
        - `score` number, double, required
        - `warnings` string[], required
      - `confidence` 'high' | 'medium' | 'low', required
      - `description` string, required — The item in English, as searched for in the factor library.
      - `evidence` string, required
      - `excluded` boolean, required
      - `lineId` string, required
      - `notes` string, nullable, required
      - `quantity` number, double, required
      - `quantityUnit` string, required
      - `searchKeywords` string[], required
      - `selectedFactor` PcfFactor, required
        - `activityCode` string, required
        - `activityUnit` string, required
        - `categoryName` string, required
        - `factorValue` number, double, required
        - `id` string, required
        - `name` string, required
        - `referenceProduct` string, nullable
        - `regionCode` string, required
        - `releaseId` string, required
        - `releaseName` string, required
        - `releaseVersion` string, required
        - `releaseYear` integer, nullable
        - `scope` integer, required
        - `sourceLocation` string, nullable
        - `sourceUuid` string, nullable
        - `split` PcfEmissionSplit — Fossil, biogenic and land-use-change parts of a GWP100 value, in the same unit as the value they split.
          - `biogenic` number, double, required
          - `fossil` number, double, required
          - `landUseChange` number, double, required
        - `unit` string, required
      - `selectionSource` 'auto' | 'user', nullable, required
      - `sourceName` string, required — The item as written in the file.
      - `stage` 'materials' | 'packaging' | 'transport' | 'energy' | 'waste', required
      - `status` 'matched' | 'needs_review' | 'unmatched', required
      - `warnings` string[], required
    - `productId` string, required
    - `sizeBytes` integer, required
    - `status` 'processing' | 'ready' | 'error' | 'applied', required
    - `updatedAt` string, date-time, required
    - `versionId` string, required
    - `warnings` string[], required

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `409` — Conflict
- `413` — Payload Too Large
- `415` — Unsupported Media Type

## Changes

- **2026-10-01** `b4751fd15397` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/greentally/apis/esgai-api/changes/pcf/products/:productId/bom-imports/post.md)

---

[API](https://skmtc.dev/greentally/apis/esgai-api.md) · [All operations](https://skmtc.dev/greentally/apis/esgai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/greentally/apis/esgai-api/revisions/b4751fd15397?raw)
