{
 "openapi": "3.1.0",
 "info": {
  "title": "Rikskampen X Theme 5 API - profile",
  "version": "0.1.0",
  "description": "Theme 5 API contract proposal (API01, decision D11): the client profile and the derived calorie profile. The safety floor reported in the calorie profile is provisional policy (D4). Real-client gate: a qualified nutrition professional must review this provisional policy before any real client relies on it, and no production backend may apply it to real clients before that review."
 },
 "tags": [
  {
   "name": "profile"
  }
 ],
 "paths": {
  "/api/theme5/clients/{clientId}/profile": {
   "get": {
    "operationId": "getClientProfile",
    "tags": [
     "profile"
    ],
    "summary": "Get the client's recorded profile",
    "description": "The recorded profile (canonical 3.1, including waist). A value that was never recorded is null, never 0 or a default (P03, D2); recorded values are positive numbers.",
    "security": [
     {
      "coachAuth": []
     }
    ],
    "parameters": [
     {
      "$ref": "common.openapi.json#/components/parameters/ClientId"
     }
    ],
    "responses": {
     "200": {
      "description": "Success.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "additionalProperties": false,
         "required": [
          "clientId",
          "name",
          "age",
          "gender",
          "heightCm",
          "weightKg",
          "goalWeightKg",
          "waistCm",
          "revision"
         ],
         "properties": {
          "clientId": {
           "type": "string"
          },
          "name": {
           "type": "string"
          },
          "age": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "gender": {
           "type": [
            "string",
            "null"
           ],
           "minLength": 1
          },
          "heightCm": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "weightKg": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "goalWeightKg": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "waistCm": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "revision": {
           "$ref": "common.openapi.json#/components/schemas/Revision"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "common.openapi.json#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "common.openapi.json#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "common.openapi.json#/components/responses/Forbidden"
     },
     "404": {
      "$ref": "common.openapi.json#/components/responses/NotFound"
     }
    },
    "x-theme5-rules": [
     "R-UNKNOWN-IS-NULL",
     "R-COACH-ASSIGNED"
    ]
   },
   "patch": {
    "operationId": "updateClientProfile",
    "tags": [
     "profile"
    ],
    "summary": "Update recorded profile values",
    "description": "Change recorded profile values; sending null clears a value back to unknown. The server recomputes the calorie profile; no derived value is written.",
    "security": [
     {
      "coachAuth": []
     }
    ],
    "parameters": [
     {
      "$ref": "common.openapi.json#/components/parameters/ClientId"
     },
     {
      "$ref": "common.openapi.json#/components/parameters/IdempotencyKey"
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
         "expectedRevision"
        ],
        "properties": {
         "expectedRevision": {
          "$ref": "common.openapi.json#/components/schemas/Revision"
         },
         "age": {
          "type": [
           "number",
           "null"
          ],
          "exclusiveMinimum": 0
         },
         "gender": {
          "type": [
           "string",
           "null"
          ],
          "minLength": 1
         },
         "heightCm": {
          "type": [
           "number",
           "null"
          ],
          "exclusiveMinimum": 0
         },
         "weightKg": {
          "type": [
           "number",
           "null"
          ],
          "exclusiveMinimum": 0
         },
         "goalWeightKg": {
          "type": [
           "number",
           "null"
          ],
          "exclusiveMinimum": 0
         },
         "waistCm": {
          "type": [
           "number",
           "null"
          ],
          "exclusiveMinimum": 0
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Success.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "additionalProperties": false,
         "required": [
          "clientId",
          "name",
          "age",
          "gender",
          "heightCm",
          "weightKg",
          "goalWeightKg",
          "waistCm",
          "revision",
          "audit"
         ],
         "properties": {
          "clientId": {
           "type": "string"
          },
          "name": {
           "type": "string"
          },
          "age": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "gender": {
           "type": [
            "string",
            "null"
           ],
           "minLength": 1
          },
          "heightCm": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "weightKg": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "goalWeightKg": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "waistCm": {
           "type": [
            "number",
            "null"
           ],
           "exclusiveMinimum": 0
          },
          "revision": {
           "$ref": "common.openapi.json#/components/schemas/Revision"
          },
          "audit": {
           "$ref": "common.openapi.json#/components/schemas/AuditStamp"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "common.openapi.json#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "common.openapi.json#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "common.openapi.json#/components/responses/Forbidden"
     },
     "404": {
      "$ref": "common.openapi.json#/components/responses/NotFound"
     },
     "409": {
      "$ref": "common.openapi.json#/components/responses/Conflict"
     },
     "422": {
      "$ref": "common.openapi.json#/components/responses/Unprocessable"
     }
    },
    "x-theme5-rules": [
     "R-UNKNOWN-IS-NULL",
     "R-DERIVED-READ-ONLY",
     "R-STALE-REVISION",
     "R-IDEMPOTENT-WRITE",
     "R-AUDITED-WRITE",
     "R-COACH-ASSIGNED",
     "R-SCHEMA-400"
    ]
   }
  },
  "/api/theme5/clients/{clientId}/calorie-profile": {
   "get": {
    "operationId": "getCalorieProfile",
    "tags": [
     "profile"
    ],
    "summary": "Get the derived calorie profile",
    "description": "Read-only derived values (D2, D3): Mifflin-St Jeor BMR from finite positive inputs; the activity factor from the recorded steps, with activityBasis \"steps\", or, when steps are not recorded, BMR alone with activityBasis \"bmr-only\" and activityFactor null; the goal ratio; and a recommendation clamped between the configured floor and the 1,500 kcal cap (the floor never exceeds the cap). Exercise is never added to food calories. Unavailable inputs give null values and false flags. The floor value is provisional policy (D4) and only reported here; this is read-only.",
    "security": [
     {
      "coachAuth": []
     }
    ],
    "parameters": [
     {
      "$ref": "common.openapi.json#/components/parameters/ClientId"
     }
    ],
    "responses": {
     "200": {
      "description": "Success.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "additionalProperties": false,
         "required": [
          "bmrAvailable",
          "recommendationAvailable",
          "bmr",
          "activityFactor",
          "activityBasis",
          "maintenance",
          "recommended",
          "floor",
          "cap"
         ],
         "properties": {
          "bmrAvailable": {
           "type": "boolean"
          },
          "recommendationAvailable": {
           "type": "boolean"
          },
          "bmr": {
           "type": [
            "number",
            "null"
           ]
          },
          "maintenance": {
           "type": [
            "number",
            "null"
           ]
          },
          "activityFactor": {
           "type": [
            "number",
            "null"
           ],
           "enum": [
            1.2,
            1.375,
            1.55,
            1.725,
            1.9,
            null
           ]
          },
          "recommended": {
           "type": [
            "integer",
            "null"
           ],
           "multipleOf": 50,
           "maximum": 1500
          },
          "floor": {
           "type": "integer",
           "exclusiveMinimum": 0,
           "maximum": 1500
          },
          "cap": {
           "const": 1500
          },
          "activityBasis": {
           "type": [
            "string",
            "null"
           ],
           "enum": [
            "steps",
            "bmr-only",
            null
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "common.openapi.json#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "common.openapi.json#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "common.openapi.json#/components/responses/Forbidden"
     },
     "404": {
      "$ref": "common.openapi.json#/components/responses/NotFound"
     }
    },
    "x-theme5-rules": [
     "R-DERIVED-READ-ONLY",
     "R-UNKNOWN-IS-NULL",
     "R-COACH-ASSIGNED"
    ]
   }
  }
 },
 "components": {
  "securitySchemes": {
   "coachAuth": {
    "$ref": "common.openapi.json#/components/securitySchemes/coachAuth"
   }
  }
 }
}
