Weight logs
Record an end user's body weight and read back one weight per day.
Each operation acts on one end user (End-user identity). Client-token scopes: weight_logs:write to create; weight_logs:read to list.
Units and limits
Send each weight as { "value": …, "unit": … } in one of these units:
lb
10–1,000
kg
4.5–453.6
A weight is stored and returned in the unit it was sent in.
created_atis when the weight was measured (Days and timezones). Omit it to log the weight now.Every measurement is kept, but the list shows one weight per local calendar day: the one with the latest
created_at. A measurement with a latercreated_aton the same day replaces what that day shows; a backdated one earlier that day doesn't.The list covers
start_datetoend_date(both inclusive, intimezone), oldest first. Days without a weight are absent, and an empty list is a valid result.The list returns at most 100 days; when more match, you get the most recent 100, so move
end_dateback to read older days.start_datecan be at most five years before today intimezone; an earlier date fails with400 date_range_too_large.Creating a log is not idempotent. A retried create records the measurement twice, and the list then shows it once.
Weight logs have no ID and cannot be updated or deleted. To change what a day shows, log a newer measurement for that day.
API key or client token.
Records one weight measurement, in lb (10–1000) or kg (4.5–453.6). Every measurement is kept; listing shows one per local day — the latest by created_at — so logging again later the same day replaces what that day shows. Not idempotent: a retried create records the measurement twice, which listing then shows once.
Callable with a client token carrying the weight_logs:write scope.
Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.
API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.
Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.
Your stable ID for the end user whose logs this request reads or writes. Opaque to January — use the same ID your system already uses for them.
| Credential | Header | Result |
|---|---|---|
API key (sk-…) | absent | 400 end_user_id_required |
API key (sk-…) | present | the request acts on that end user |
Client token (ct-…) | absent | filled in from the token |
Client token (ct-…) | the end user the token is bound to | accepted |
Client token (ct-…) | any other end user | 403 end_user_id_mismatch |
When the weight was measured — any ISO-8601 offset; stored and returned in UTC with milliseconds. Omitted = now.
2026-09-10T07:30:00-07:00The logged weight, as stored: the unit it was sent in, and created_at in UTC.
When the weight was measured. UTC, with milliseconds.
2026-09-10T14:30:00.000Zweight is missing, malformed or out of range, or created_at is malformed.
The request carried no Authorization header, or the credential in it was rejected.
unauthorized — the header is missing or malformed, or the key is not one we recognise. A valid key belonging to the other API version is 403 forbidden instead.
A client token is rejected in one of three ways, and only the first should be handled automatically:
token_expired— the token is past its TTL. Mint a fresh one from your backend and retry the request once. This is routine and expected once per TTL window.token_invalid— no such token: it was never issued, or it has been purged, which happens shortly after it expires. This code is not an automatic token-refresh signal.token_revoked— the token was revoked, byPOST /v1.2/auth/client-token-revocationsor from the dashboard. The end user signs in again in your app, and your backend decides whether to mint another; a device that just re-mints defeats the revocation.
The credential is valid but is not allowed to make this request. forbidden is the general case — a key issued for the other API version, for example. A client token adds client_token_not_allowed, meaning the endpoint takes only an sk- API key — its description opens with API key only. (in this API: POST /v1.2/auth/client-tokens, POST /v1.2/auth/client-token-revocations, POST /v1.2/chat/completions, POST /v1.2/literature/search, POST /v1.2/extractions, GET /v1.2/extractions/{job_id}, GET /v1.2/patients/{patient_id}/snapshot, and GET /v1.2/credits).
On an endpoint that opens with API key or client token., scope_insufficient means the token was minted without the scope named at the end of that endpoint’s description, and end_user_id_mismatch means the January-End-User-ID header disagrees with the end user the token is bound to — omit it, or send exactly that id.
Two failures share this status; use code to choose the response.
rate_limited— a rolling abuse window was reached: the partner-wide v1.2 minute cap, a configured short-window limit, or a client-token limit. Back off and retry;Retry-Aftercarries the wait when Redis reports it.credit_limit_exceeded— this call costs more credits than you have left for the billing period, or they are spent. Never returned to an Enterprise account, whose usage past the allowance is billed as overage instead.
Credits reset at the end of your billing period; GET /v1.2/credits reports that instant as resets_at and remains available when either limit refuses other operations.
Any other error: the HTTP status plus { code, message }. Retry only rate_limited and the transient 5xx codes.
POST /v1.2/weight-logs HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 77
{
"weight": {
"value": 150,
"unit": "lb"
},
"created_at": "2026-09-10T07:30:00-07:00"
}{
"weight": {
"value": 150,
"unit": "lb"
},
"created_at": "2026-09-10T14:30:00.000Z"
}API key or client token.
Returns one weight per day between start_date and end_date (both inclusive local calendar dates in timezone), oldest first. Only days with a logged weight appear; when several were logged on one day, the one with the latest created_at is returned, in the unit it was logged in. At most 100 days are returned — when more match, the most recent 100. start_date may reach back at most 5 years from today in timezone. An empty list is a valid result.
Callable with a client token carrying the weight_logs:read scope.
Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.
API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.
Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.
First local calendar date in timezone, inclusive. May be at most 5 years before today in timezone.
2024-09-01Last local calendar date in timezone, inclusive. May equal start_date for a single day. When more than 100 days in the range have a weight, the most recent 100 are returned.
2024-09-08IANA timezone that defines the local calendar days this range covers. Required: without it the days would be cut in UTC, which silently shifts anything logged near midnight into the wrong day for anyone not on UTC.
America/Los_AngelesYour stable ID for the end user whose logs this request reads or writes. Opaque to January — use the same ID your system already uses for them.
| Credential | Header | Result |
|---|---|---|
API key (sk-…) | absent | 400 end_user_id_required |
API key (sk-…) | present | the request acts on that end user |
Client token (ct-…) | absent | filled in from the token |
Client token (ct-…) | the end user the token is bound to | accepted |
Client token (ct-…) | any other end user | 403 end_user_id_mismatch |
One weight per day that has one, oldest first; an empty array is a valid result.
A date is missing, malformed, or the range is inverted; start_date is more than 5 years before today in timezone (date_range_too_large); or timezone is missing or not a valid IANA name.
The request carried no Authorization header, or the credential in it was rejected.
unauthorized — the header is missing or malformed, or the key is not one we recognise. A valid key belonging to the other API version is 403 forbidden instead.
A client token is rejected in one of three ways, and only the first should be handled automatically:
token_expired— the token is past its TTL. Mint a fresh one from your backend and retry the request once. This is routine and expected once per TTL window.token_invalid— no such token: it was never issued, or it has been purged, which happens shortly after it expires. This code is not an automatic token-refresh signal.token_revoked— the token was revoked, byPOST /v1.2/auth/client-token-revocationsor from the dashboard. The end user signs in again in your app, and your backend decides whether to mint another; a device that just re-mints defeats the revocation.
The credential is valid but is not allowed to make this request. forbidden is the general case — a key issued for the other API version, for example. A client token adds client_token_not_allowed, meaning the endpoint takes only an sk- API key — its description opens with API key only. (in this API: POST /v1.2/auth/client-tokens, POST /v1.2/auth/client-token-revocations, POST /v1.2/chat/completions, POST /v1.2/literature/search, POST /v1.2/extractions, GET /v1.2/extractions/{job_id}, GET /v1.2/patients/{patient_id}/snapshot, and GET /v1.2/credits).
On an endpoint that opens with API key or client token., scope_insufficient means the token was minted without the scope named at the end of that endpoint’s description, and end_user_id_mismatch means the January-End-User-ID header disagrees with the end user the token is bound to — omit it, or send exactly that id.
Two failures share this status; use code to choose the response.
rate_limited— a rolling abuse window was reached: the partner-wide v1.2 minute cap, a configured short-window limit, or a client-token limit. Back off and retry;Retry-Aftercarries the wait when Redis reports it.credit_limit_exceeded— this call costs more credits than you have left for the billing period, or they are spent. Never returned to an Enterprise account, whose usage past the allowance is billed as overage instead.
Credits reset at the end of your billing period; GET /v1.2/credits reports that instant as resets_at and remains available when either limit refuses other operations.
Any other error: the HTTP status plus { code, message }. Retry only rate_limited and the transient 5xx codes.
GET /v1.2/weight-logs?start_date=2024-09-01&end_date=2024-09-08&timezone=America%2FLos_Angeles HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"date": "2026-09-10",
"weight": {
"value": 150,
"unit": "lb"
}
}
]
}Last updated
Was this helpful?