---
title: "POST /uploads/{id}/factor-agent/retry"
method: POST
path: "/uploads/{id}/factor-agent/retry"
tags: ["Uploads"]
---

# POST /uploads/{id}/factor-agent/retry

`POST /uploads/{id}/factor-agent/retry`

Re-runs factor matching for the named items of an analysis that already exists. No document is read and no extraction runs, so this is the cheap action for rows that came back unmatched. Items the request does not name keep their candidates and their selection, including a factor chosen by hand from the library.

## Path parameters

- `id` integer, required

## Request body

- DirectUploadFactorRetryRequest
  - `itemIds` string[], required — The items to re-match. Every other item on the analysis is left exactly as it is, so a retry cannot discard a selection the reviewer made on a row beside the ones being retried.

## Response `200`

Matching re-ran; the named items are updated and the rest are unchanged

- DirectUploadFactorAnalysisResponse
  - `data` object, required
    - `allItems` object[], required
    - `confirmationMessage` string
    - `customPrompt` string
    - `extractionProvenance` object
      - `agentVariant` 'legacy' | 'skill_v1'
      - `attemptCount` integer
      - `diagnosticCodes` string[], required
      - `model` string
      - `policyVersion` string
      - `provider` string
      - `traceId` string
    - `items` object[], required
    - `message` string, required
    - `provenance` 'web' | 'cli', required
    - `schemaVersion` 'direct-upload-factor-review/v2', required
    - `sessionId` string
    - `sourceFileSha256` string, required
    - `status` 'processing' | 'completed' | 'needs_input' | 'error', required
    - `submitted` boolean, required
    - `submittedAt` string, date-time
    - `summary` string, required
    - `uploadId` integer, required
    - `userReviewHints` DirectUploadUserReviewHints
      - `carbonClassifications` object — Explicit reviewer overrides keyed by extracted item ID.
      - `itemTypes` object
    - `versionId` string, uuid, required
    - `warnings` string[], required

## Other responses

- `400` — The request named no items
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `409` — Nothing to re-match against: either the analysis kept no matching session, or it holds none of the named items — which happens when another tab or a re-analysis has moved on since the caller read the analysis. Refused rather than saved, because an unchanged analysis written as a new version would report a retry that matched nothing as a success.

## Changes

- **2026-09-28** `578e1527454e` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/greentally/apis/esgai-api/changes/uploads/:id/factor-agent/retry/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/578e1527454e?raw)
