Record a weigh-in
POST/api/public/trainees/{traineeId}/body-metrics
Record a weigh-in for a trainee: weight, body fat, and/or body measurements. This is the only way to write weight through the API, because weight is kept as a dated history rather than a single field: the previous value is moved into the history and the new one becomes current. PATCH /trainees/{traineeId} therefore does NOT accept weight.
Every field is optional, but send at least one. Send only what was actually measured; omitted fields are left untouched, and each measurement field keeps its own dated history. Measurements are in cm, weight in kg, bodyFat in percent.
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
| Name | Type | Description |
|---|---|---|
traineeIdrequired | string |
Header parameters
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | 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
| Name | Type | Description |
|---|---|---|
weight | number | Body weight in kg. Becomes the current weight; the previous one is pushed onto the weight history. |
bodyFat | number | Body fat percentage. Kept as a dated history, exactly like weight. |
date | string | ISO date this measurement was taken. Defaults to now. Use it to backfill an earlier weigh-in. |
chest | number | chest in cm. |
waist | number | waist in cm. |
rightArm | number | rightArm in cm. |
leftArm | number | leftArm in cm. |
rightThigh | number | rightThigh in cm. |
leftThigh | number | leftThigh in cm. |
rightCalf | number | rightCalf in cm. |
leftCalf | number | leftCalf in cm. |
neck | number | neck in cm. |
butt | number | butt in cm. |
navel | number | navel in cm. |
lowerAbdomen | number | lowerAbdomen in cm. |
upperAbdomen | number | upperAbdomen in cm. |
upperHip | number | upperHip in cm. |
lowerHip | number | lowerHip in cm. |
Request examples
curl --request POST \
--url 'https://api.coach-platform.com/api/public/trainees/<traineeId>/body-metrics' \
--header 'Authorization: Bearer cp_live_...' \
--header 'Content-Type: application/json' \
--data '{
"weight": 123
}'const response = await fetch('https://api.coach-platform.com/api/public/trainees/<traineeId>/body-metrics', {
method: 'POST',
headers: {
Authorization: 'Bearer cp_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"weight": 123
}),
});
const data = await response.json();Responses
201 Created
{
"data": {
"traineeId": "<string>",
"date": "<date-time>",
"weight": 123,
"bodyFat": 123,
"measurements": {}
},
"warnings": [
{
"field": "<string>",
"message": "<string>"
}
]
}Response fields (9)
| Name | Type | Description |
|---|---|---|
data | object | |
data.traineeId | string | |
data.date | string<date-time> | |
data.weight | number | null | |
data.bodyFat | number | null | |
data.measurements | object | The measurement fields recorded by this request, in cm. |
warnings | object[] | Non-fatal problems with follow-up writes. The resource was created, but each listed field was not applied. |
warnings[].field | string | |
warnings[].message | string |
Error responses
400Bad Request401Unauthorized403Forbidden404Not Found409Conflict429Too Many Requests500Internal Server Error
These statuses share the same response body.
{
"error": {
"code": "<string>",
"message": "<string>",
"fix": "<string>",
"details": {},
"retryAfterMs": 123
}
}Error fields (6)
| Name | Type | Description |
|---|---|---|
error | object | |
error.code | string | |
error.message | string | |
error.fix | string | null | |
error.details | object | null | |
error.retryAfterMs | number | null |
More Trainees endpoints
This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.