---
title: "Apply a pcf_import, document_rows, pcf_lines, pcf_save or net_zero_target proposal"
method: POST
path: "/assistant/proposals/{proposalId}/apply"
tags: ["Assistant"]
---

# Apply a pcf_import, document_rows, pcf_lines, pcf_save or net_zero_target proposal

`POST /assistant/proposals/{proposalId}/apply`

net_zero_target (requires org.edit_dashboard, not org.write_data) saves the card's draft as the active net-zero target set through the SBTi engine; a draft that no longer passes (the baseline moved) is refused with 400 VALIDATION_ERROR and error.details.failures, as POST /net-zero/target-sets. For the kinds whose data lives server side; widgets and report are applied by the frontend and reported with POST /assistant/proposals/{proposalId}. Each apply is gated by the proposal's workflow step (409 WORKFLOW_STEP with the workflow summary when out of order) and a repeated apply of an applied proposal answers 200 without doing anything again. document_rows, pcf_lines and pcf_save require seenVersion, the version of the record the card the user confirmed showed (documentRows.analysisVersionId, pcfLines.importVersionId, pcfSave.footprintVersion). When it is missing or is not the record's current version nothing is applied and the answer is 409 CARD_REFRESHED with the current card. pcf_import enqueues a bom_import job and answers at once with jobId; productId in the body targets an existing, non-archived product of the organization ("Add to X" on a duplicate card). document_rows submits the ready rows through the review page's submit. pcf_lines applies the import, previews the footprint and returns parts (a pcf part and a pcf_save card, also appended to the thread). pcf_save saves the calculation in the same transaction as the workflow step. The pcf_import details below still apply. Re-checks org.write_data; the proposal must be the caller's and pending, and the upload the organization's. For a new product (or when product overrides are sent, which is how "create a new product instead" of a suggested duplicate is chosen) it creates the product with source upload, then a BOM import that reads and matches the file (synchronous, about 10-90 s) with the instructions the user gave in chat. The import is not applied: the user reviews its lines in the PCF calculator. mode (append or replace, default append) is recorded for that step. The proposal is marked applied with {productId, importId}. Afterwards the direct upload that only carried the chat attachment is deleted when it has no analysis and no submitted rows (the import keeps its own copy of the file). An extraction failure is not an error: the import exists with status error and the calculator offers to read it again.

## Path parameters

- `proposalId` string, required

## Request body

- AssistantProposalApplyRequest — seenVersion is required for document_rows, pcf_lines and pcf_save; the other fields are pcf_import only.
  - `mode` string — append (default) or replace; ignored for a new product
  - `product` object — Overrides for a new product; sending it creates a new product even when the proposal suggested an existing one.
    - `declaredQuantity` number
    - `declaredUnit` string
    - `description` string
    - `name` string
    - `productCode` string
    - `region` string
  - `productId` string — Import into this existing, non-archived product instead (the duplicate card's "Add to X").
  - `seenVersion` string — The version of the record the card showed the user: documentRows.analysisVersionId, pcfLines.importVersionId or pcfSave.footprintVersion. Missing or not current answers 409 CARD_REFRESHED and applies nothing.

## Response `200`

The product and the import in review

- AssistantProposalApplyResponse
  - `data` object, required
    - `calculationId` string — pcf_save.
    - `href` string
    - `jobId` string — pcf_import - the bom_import job started.
    - `kgCO2e` number — document_rows (submitted) or pcf_save (saved).
    - `parts` AssistantPart[] — pcf_lines - a pcf part and a pcf_save card (or a notice when incomplete).
      - `type` string, required
    - `proposalId` string, required
    - `status` string, required — applied
    - `step` string — The workflow's step after the apply.
    - `submittedRows` integer — document_rows.
    - `workflowId` string

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `409` — PROPOSAL_SETTLED, WORKFLOW_STEP, CARD_REFRESHED (the record changed on the review page or in the calculator since the card was shown: details {proposalId, part} carry the rebuilt card, nothing was applied, and the user confirms again), or PCF_PRODUCT_DUPLICATE with the clashing product (field, productId, archived)
- `503` — AI_GATEWAY_UNAVAILABLE (BOM file import is not configured)

## Changes

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

[Change history](https://skmtc.dev/greentally/apis/esgai-api/changes/assistant/proposals/:proposalId/apply/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)
