---
title: "Resolve, correct or reject one ingredient line"
method: PUT
path: "/chefs/recipes/{recipe_id}/review/{ingredient_id}"
tags: ["recipes"]
---

# Resolve, correct or reject one ingredient line

`PUT /chefs/recipes/{recipe_id}/review/{ingredient_id}`

Attach a food to the line, replace an incorrect match, or reject the line as not an ingredient. Every outcome is written to the correction ledger, including agreement with what the algorithm already proposed, and the recipe's nutrition and classification are recalculated.

## Path parameters

- `recipe_id` integer, required
- `ingredient_id` integer, required

## Request body

- ResolveRecipeReviewLineRequest — Attach a food (`rxfood_id`), or set `rejected` to drop the line as not an ingredient. Quantity fields keep their existing values when omitted.
  - `group_id` integer, nullable — Move the line into this existing ingredient group on the recipe. Omit to leave its group unchanged.
  - `group_name` string, nullable — Move the line into a group with this name, creating it on the recipe if needed. An empty string ungroups the line. Takes precedence over group_id.
  - `rejected` boolean — The line is not an ingredient; it is removed and the decision recorded.
  - `rxfood_id` string, nullable — CNF food to attach. Required unless rejected.
  - `serving_unit_amount` number, nullable
  - `serving_unit_label` string, nullable
  - `servings` number, nullable

## Response `200`

successful operation

- RecipeReviewLineResponse — One ingredient line awaiting or having had a decision. `resolved` is false when nothing is attached yet, which is what blocks publishing. The provenance fields are populated only for lines that came from a scan.
  - `child_recipe_id` integer, nullable
  - `description` string, nullable
  - `extracted_name` string, nullable — What the parser read the ingredient as.
  - `food_name` string, nullable
  - `group_id` integer, nullable — Ingredient group this line belongs to, or null when ungrouped.
  - `group_name` string, nullable — Display name of the line's ingredient group, for showing headings without a second lookup.
  - `ingredient_id` integer, nullable — Null for a rejected line, which no longer has an ingredient but stays visible so the curator can see what was discarded.
  - `mapping_confidence` number, nullable
  - `mapping_status` 'unmatched' | 'auto' | 'confirmed' | 'rejected', nullable — A rejected line is returned with resolved=true and no ingredient_id: it needs no further decision but is shown so the discard is visible.
  - `original_text` string, nullable — What the source said, for a scanned or imported line.
  - `resolved` boolean
  - `rxfood_id` string, nullable
  - `serving_unit_label` string, nullable
  - `servings` number, nullable
  - `sort_order` integer
  - `suggestions` object[], nullable — Catalogue candidates for an unresolved line, best first. Not exhaustive -- clients should also offer a catalogue search.
    - `confidence` number
    - `name` string
    - `name_display` string, nullable — CNF display name when populated. Null when the catalogue row has none.
    - `rxfood_id` string

## Changes

- **2026-09-24** `a61b77b30e63` — 1 info
  - added the optional property `suggestions/items/name_display` to the response with the `200` status
- **2026-09-19** `2991fb51502d` — 4 info
  - added the new optional request property `group_id`
  - added the new optional request property `group_name`
  - added the optional property `group_id` to the response with the `200` status
  - added the optional property `group_name` to the response with the `200` status
- **2026-09-15** `8d4f658e79b1` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/rxfoodapp/apis/inneranalytics-mnt-server/changes/chefs/recipes/:recipe_id/review/:ingredient_id/put.md)

---

[API](https://skmtc.dev/rxfoodapp/apis/inneranalytics-mnt-server.md) · [All operations](https://skmtc.dev/rxfoodapp/apis/inneranalytics-mnt-server/llms.txt) · [OpenAPI document](https://skmtc.dev/rxfoodapp/apis/inneranalytics-mnt-server/revisions/750cc0d96a93?raw)
