Update a nutrition menu

PATCH/api/public/nutrition-menus/{menuId}

Partially update a nutrition menu. Does not cascade: copies duplicated from this menu are left untouched, unlike the dashboard which offers to push the edit down to them.

Authentication

Requires an API key, sent as Authorization: Bearer cp_live_....

API keys carry scopes. Get the catalog of scopes and webhook events lists every scope.

Path parameters

Path parameters
NameTypeDescription
menuIdrequiredstring

Header parameters

Header parameters
NameTypeDescription
Idempotency-Keystring

Optional. Send a unique key (e.g. a UUID) to make this POST safe to retry. The same key within 24h returns the original result instead of creating a duplicate.

Request body

application/json, required

Request body fields
NameTypeDescription
namestring
descriptionstring
goalstring

Allowed values: Weight Loss Muscle Gain Weight Maintenance Other

typestring

Allowed values: Vegetarian Vegan Keto Paleo Low Carbs Gluten Free Mediterranean

totalCaloriesnumber
totalProteinnumber
totalCarbsnumber
totalFatnumber
mealsobject[]

Maximum items: 100

meals[].idstring

Meal id. Not stable: saving the menu from the dashboard rewrites every meal with a new id, so re-read this endpoint before each write instead of caching it. Ignored on create; resend it on PATCH to keep the meal and its alternatives instead of replacing it with a new one.

meals[].titlestring

Meal name, e.g. "Breakfast".

meals[].foodItemsobject[]
meals[].foodItems[].namestring

Food name, e.g. "Chicken breast".

meals[].foodItems[].quantitynumber

Amount in the given unit, e.g. 150.

meals[].foodItems[].unitstring

Unit of the quantity, e.g. "g", "ml", "unit".

meals[].foodItems[].unitWeightnumber

Grams in one unit. The app scales macros as quantity * unitWeight / 100 * the per-100g values, so send it whenever unit is not grams. Take it from the matching entry in the units array of GET /food-items. Defaults to 100.

meals[].foodItems[].productCodenumber

Food database code, from GET /food-items. Send it to link the food to its catalog entry so replacements and portion data behave like they do in the dashboard.

meals[].foodItems[].caloriesPer100gnumber
meals[].foodItems[].proteinPer100gnumber
meals[].foodItems[].carbsPer100gnumber
meals[].foodItems[].fatPer100gnumber
meals[].caloriesnumber

Total calories for the meal.

meals[].proteinnumber
meals[].carbsnumber
meals[].fatnumber
meals[].notesstring
meals[].alternativesobject[]

Alternatives the trainee may eat instead of this meal. Manage them one at a time with POST/DELETE /nutrition-menus/{menuId}/meals/{mealId}/alternatives, or send the whole array here.

Maximum items: 20

meals[].alternatives[].idstring

Alternative id. Read-only; pass it to DELETE /nutrition-menus/{menuId}/meals/{mealId}/alternatives/{alternativeId}. Not stable: saving the menu from the dashboard gives every alternative a new id, so read it fresh rather than caching it.

meals[].alternatives[].titlestring

Alternative name, e.g. "Omelette instead".

meals[].alternatives[].foodItemsobject[]
meals[].alternatives[].foodItems[].namestring

Food name, e.g. "Chicken breast".

meals[].alternatives[].foodItems[].quantitynumber

Amount in the given unit, e.g. 150.

meals[].alternatives[].foodItems[].unitstring

Unit of the quantity, e.g. "g", "ml", "unit".

meals[].alternatives[].foodItems[].unitWeightnumber

Grams in one unit. The app scales macros as quantity * unitWeight / 100 * the per-100g values, so send it whenever unit is not grams. Take it from the matching entry in the units array of GET /food-items. Defaults to 100.

meals[].alternatives[].foodItems[].productCodenumber

Food database code, from GET /food-items. Send it to link the food to its catalog entry so replacements and portion data behave like they do in the dashboard.

meals[].alternatives[].foodItems[].caloriesPer100gnumber
meals[].alternatives[].foodItems[].proteinPer100gnumber
meals[].alternatives[].foodItems[].carbsPer100gnumber
meals[].alternatives[].foodItems[].fatPer100gnumber
meals[].alternatives[].caloriesnumber

Total calories for the alternative.

meals[].alternatives[].proteinnumber
meals[].alternatives[].carbsnumber
meals[].alternatives[].fatnumber
meals[].alternatives[].notesstring
applyToAllSharedTraineesboolean

Required (true) to edit a menu shared by multiple trainees; the change then applies to all of them. Without it, a shared menu returns 409.

Request examples

cURL
curl --request PATCH \
  --url 'https://api.coach-platform.com/api/public/nutrition-menus/<menuId>' \
  --header 'Authorization: Bearer cp_live_...' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "<string>"
}'
JavaScript (fetch)
const response = await fetch('https://api.coach-platform.com/api/public/nutrition-menus/<menuId>', {
  method: 'PATCH',
  headers: {
    Authorization: 'Bearer cp_live_...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "<string>"
  }),
});

const data = await response.json();

Responses

200 OK

Successful response

Example body (application/json)
{
  "data": {
    "id": "<string>",
    "coach": "<string>",
    "escorts": [
      "<string>"
    ],
    "title": "<string>",
    "description": "<string>",
    "goal": "<string>",
    "type": "<string>",
    "totalCalories": 123,
    "totalProtein": 123,
    "totalCarbs": 123,
    "totalFat": 123,
    "meals": [
      {
        "id": "<string>",
        "title": "<string>",
        "foodItems": [
          {
            "name": "<string>",
            "quantity": 123,
            "unit": "<string>",
            "unitWeight": 123,
            "productCode": 123,
            "caloriesPer100g": 123,
            "proteinPer100g": 123,
            "carbsPer100g": 123,
            "fatPer100g": 123
          }
        ],
        "calories": 123,
        "protein": 123,
        "carbs": 123,
        "fat": 123,
        "notes": "<string>",
        "alternatives": [
          {
            "id": "<string>",
            "title": "<string>",
            "foodItems": [
              {
                "name": "<string>",
                "quantity": 123,
                "unit": "<string>",
                "unitWeight": 123,
                "productCode": 123,
                "caloriesPer100g": 123,
                "proteinPer100g": 123,
                "carbsPer100g": 123,
                "fatPer100g": 123
              }
            ],
            "calories": 123,
            "protein": 123,
            "carbs": 123,
            "fat": 123,
            "notes": "<string>"
          }
        ]
      }
    ],
    "createdAt": "<date-time>"
  }
}
Response fields (49)
Response fields
NameTypeDescription
dataobject
data.idstring
data.coachstring
data.escortsstring[]
data.titlestring
data.descriptionstring
data.goalstring
data.typestring
data.totalCaloriesnumber
data.totalProteinnumber
data.totalCarbsnumber
data.totalFatnumber
data.mealsobject[]
data.meals[].idstring

Meal id. Not stable: saving the menu from the dashboard rewrites every meal with a new id, so re-read this endpoint before each write instead of caching it. Ignored on create; resend it on PATCH to keep the meal and its alternatives instead of replacing it with a new one.

data.meals[].titlestring

Meal name, e.g. "Breakfast".

data.meals[].foodItemsobject[]
data.meals[].foodItems[].namestring

Food name, e.g. "Chicken breast".

data.meals[].foodItems[].quantitynumber

Amount in the given unit, e.g. 150.

data.meals[].foodItems[].unitstring

Unit of the quantity, e.g. "g", "ml", "unit".

data.meals[].foodItems[].unitWeightnumber

Grams in one unit. The app scales macros as quantity * unitWeight / 100 * the per-100g values, so send it whenever unit is not grams. Take it from the matching entry in the units array of GET /food-items. Defaults to 100.

data.meals[].foodItems[].productCodenumber

Food database code, from GET /food-items. Send it to link the food to its catalog entry so replacements and portion data behave like they do in the dashboard.

data.meals[].foodItems[].caloriesPer100gnumber
data.meals[].foodItems[].proteinPer100gnumber
data.meals[].foodItems[].carbsPer100gnumber
data.meals[].foodItems[].fatPer100gnumber
data.meals[].caloriesnumber

Total calories for the meal.

data.meals[].proteinnumber
data.meals[].carbsnumber
data.meals[].fatnumber
data.meals[].notesstring
data.meals[].alternativesobject[]

Alternatives the trainee may eat instead of this meal. Manage them one at a time with POST/DELETE /nutrition-menus/{menuId}/meals/{mealId}/alternatives, or send the whole array here.

Maximum items: 20

data.meals[].alternatives[].idstring

Alternative id. Read-only; pass it to DELETE /nutrition-menus/{menuId}/meals/{mealId}/alternatives/{alternativeId}. Not stable: saving the menu from the dashboard gives every alternative a new id, so read it fresh rather than caching it.

data.meals[].alternatives[].titlestring

Alternative name, e.g. "Omelette instead".

data.meals[].alternatives[].foodItemsobject[]
data.meals[].alternatives[].foodItems[].namestring

Food name, e.g. "Chicken breast".

data.meals[].alternatives[].foodItems[].quantitynumber

Amount in the given unit, e.g. 150.

data.meals[].alternatives[].foodItems[].unitstring

Unit of the quantity, e.g. "g", "ml", "unit".

data.meals[].alternatives[].foodItems[].unitWeightnumber

Grams in one unit. The app scales macros as quantity * unitWeight / 100 * the per-100g values, so send it whenever unit is not grams. Take it from the matching entry in the units array of GET /food-items. Defaults to 100.

data.meals[].alternatives[].foodItems[].productCodenumber

Food database code, from GET /food-items. Send it to link the food to its catalog entry so replacements and portion data behave like they do in the dashboard.

data.meals[].alternatives[].foodItems[].caloriesPer100gnumber
data.meals[].alternatives[].foodItems[].proteinPer100gnumber
data.meals[].alternatives[].foodItems[].carbsPer100gnumber
data.meals[].alternatives[].foodItems[].fatPer100gnumber
data.meals[].alternatives[].caloriesnumber

Total calories for the alternative.

data.meals[].alternatives[].proteinnumber
data.meals[].alternatives[].carbsnumber
data.meals[].alternatives[].fatnumber
data.meals[].alternatives[].notesstring
data.createdAtstring<date-time>

Error responses

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 429 Too Many Requests
  • 500 Internal Server Error

These statuses share the same response body.

Example body (application/json)
{
  "error": {
    "code": "<string>",
    "message": "<string>",
    "fix": "<string>",
    "details": {},
    "retryAfterMs": 123
  }
}
Error fields (6)
Error fields
NameTypeDescription
errorobject
error.codestring
error.messagestring
error.fixstring | null
error.detailsobject | null
error.retryAfterMsnumber | null

This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.