BETTERMENU
Studio

Restore Custom Ingredient to Version

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_restorabledeleteCustomIngredient 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.

POST
/studio/custom-ingredients/{custom_ingredient_id}/restore

Path Parameters

custom_ingredient_id*Custom Ingredient Id

Header Parameters

If-Match*string

Optimistic-concurrency token. Pass the version_id returned by the previous mutation (or by GET /recipes/{id}/versions) so the server can reject the request when another writer has advanced the recipe in the meantime. A stale token (header present but HEAD has moved) surfaces HTTP 409 with the current version_id in the response body. An absent token on a versioned recipe surfaces HTTP 412. Only consumed on API versions that declare the recipe_versioning capability — older versions ignore the header.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://api.bettermenu.live/studio/custom-ingredients/string/restore" \  -H "If-Match: string" \  -H "Content-Type: application/json" \  -d '{    "target_version_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV"  }'
{
  "data": {
    "id": "stringstringstringstringst",
    "org_id": "stringstringstringstrings",
    "status": "draft",
    "name": "string",
    "entry_method": "form",
    "notes": "string",
    "reference_amount": "string",
    "reference_unit": "string",
    "household_measure": "string",
    "reference_quantity_g": "string",
    "density_g_per_ml": "string",
    "nutrients": [
      {
        "id": "stringstringstringstringst",
        "unit": "string",
        "amount": "string",
        "market_nutrients": {
          "property1": {
            "bmid": "string",
            "nutrient_id": 0
          },
          "property2": {
            "bmid": "string",
            "nutrient_id": 0
          }
        }
      }
    ],
    "approved_markets": [
      "US"
    ],
    "brand": "string",
    "manufacturer": "string",
    "source_url": "string",
    "attributes": [
      {
        "key": "string",
        "type": "string",
        "value": null,
        "searchable": false
      }
    ],
    "artifacts": [
      {
        "key": "string",
        "kind": "string",
        "uploaded_at": "2019-08-24T14:15:22Z"
      }
    ],
    "ingredient_statement": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "updated_at": "2019-08-24T14:15:22Z"
  },
  "meta": {
    "version": "string",
    "request_id": "string",
    "timestamp": "string"
  },
  "version_id": "string"
}
{
  "type": "https://api.bettermenu.live/errors/recipe_not_found",
  "title": "Recipe Not Found",
  "status": 400,
  "detail": "Recipe rcpe_abc123 does not exist",
  "code": "recipe_not_found",
  "retryable": true,
  "instance": "/api/v1/recipes/rcpe_abc123",
  "trace_id": "req_xyz789",
  "errors": [
    {}
  ],
  "invalid_ids": [
    "f_abc123",
    "f_xyz789"
  ]
}
{
  "type": "https://api.bettermenu.live/errors/recipe_not_found",
  "title": "Recipe Not Found",
  "status": 400,
  "detail": "Recipe rcpe_abc123 does not exist",
  "code": "recipe_not_found",
  "retryable": true,
  "instance": "/api/v1/recipes/rcpe_abc123",
  "trace_id": "req_xyz789",
  "errors": [
    {}
  ],
  "invalid_ids": [
    "f_abc123",
    "f_xyz789"
  ]
}
Empty
{
  "detail": [
    {
      "loc": [
        "string"
      ],
      "msg": "string",
      "type": "string",
      "input": null,
      "ctx": {}
    }
  ]
}
BETTERMENU

FDA-compliant nutrition labels from a recipe, in minutes.

Visit bettermenu.live