# Restore Custom Ingredient to Version



{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}

Roll back a custom ingredient to the content state it had at a prior version.

This is a **full point-in-time restore** — the entity's entire state
(nutrients, serving/gram basis, name, lifecycle status, attributes)
snaps back to exactly what was recorded in `target_version_id`. This
matches the semantics of `git checkout <tag>`: the whole entity
reverts, not just the fields that changed between the target and the
current HEAD.

Lifecycle status is part of that state, so a restore re-projects the
target version's status onto HEAD: restoring past an `archive` puts the
ingredient back in `active` or `draft`, exactly as
`unarchiveCustomIngredient` would.

It does **not** undo a delete. A `deleted` ingredient is refused with
409 `custom_ingredient_not_restorable` — `deleteCustomIngredient` is
permanent (ADR 0008 D11), and this is what makes it so. `restoreRecipe`
refuses a deleted recipe too, by a different route: a deleted recipe is
hidden from all reads, so it 404s.

Creates a new commit whose content matches `target_version_id`; the
existing history is never rewritten. The new `version_id` is
returned in the response body — pass it as `If-Match` on subsequent
mutations. Returns 404 if the custom ingredient or the target version
does not exist; 409 on a `deleted` ingredient or an `If-Match`
mismatch.

A recipe pinned to a specific custom-ingredient `version_id` is
unaffected by this call — pins are immutable by `version_id`
(ADR 0007 D2), so restoring the custom ingredient to a different
version never changes what an already-pinned recipe reads or
computes.

<APIPage document="&#x22;bettermenu&#x22;" operations="[{&#x22;path&#x22;:&#x22;/studio/custom-ingredients/{custom_ingredient_id}/restore&#x22;,&#x22;method&#x22;:&#x22;post&#x22;}]" />
