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

# Resolve, correct or reject one ingredient line

`PUT /patients/{patient_id}/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 with actor_type patient, and the recipe's nutrition is recalculated.

## Path parameters

- `patient_id` integer, required
- `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` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/rxfoodapp/apis/inneranalytics-mnt-server/changes/patients/:patient_id/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)
