Water logs
Record an end user's water intake and read it back as daily totals.
Each operation acts on one end user (End-user identity). Client-token scopes: water_logs:write to create or delete; water_logs:read to list.
Units and limits
Send each amount as { "value": …, "unit": … } in one of these units:
fl_oz
1–811.5
ml
30–24,000
cup (US cup, 8 fl oz)
0.1–101.4
The minimums don't convert exactly into one another (1 fl oz is about 29.6 ml, below the 30 ml minimum), so send the unit the user entered.
An end user's total is capped at 24 L (about 811 fl oz) per UTC calendar day of
created_at, whatever offset you send. A log that would pass the cap fails with400 daily_water_limit_exceeded.created_atis when the water was consumed (Days and timezones). Omit it to log the water now.A created log comes back in the unit it was sent in. Save its
idto delete it later.The list returns one total per local calendar day between
start_dateandend_date(both inclusive, intimezone), oldest first, in theunityou ask for (required), rounded to one decimal place. Days with nothing logged 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. Before you retry a create that timed out, list the day to check whether it was recorded, because a retry records the water twice and counts it twice toward the cap.
Deleting is idempotent: an unknown or already-deleted log also returns
204. A deleted amount no longer counts toward its day's cap.
API key or client token.
Records one amount of water, in fl_oz, ml or cup (1–811.5 fl_oz, 30–24000 ml, 0.1–101.4 cup). An end user's total is capped at 24 L (about 811 fl oz) per day: a log that would take the day of its created_at past it is refused with daily_water_limit_exceeded. Save the returned id to delete the log. Not idempotent: verify with the list endpoint before retrying a timed-out create, since a retry records the water twice and counts twice toward the cap.
Callable with a client token carrying the water_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 water was consumed — any ISO-8601 offset; stored and returned in UTC with milliseconds. Omitted = now. Its day is the one the daily cap counts it against.
2026-09-10T07:30:00-07:00The logged entry: its id, the amount in the unit it was sent in, and created_at in UTC.
Save this id to delete the log.
78129823-8ba2-4183-b13b-71f0e963c606When the water was consumed. UTC, with milliseconds.
2026-09-10T14:30:00.000Zamount is missing, malformed or out of range, or created_at is malformed (invalid_request); or the log would take the end user's total for its day past the daily cap (daily_water_limit_exceeded).
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/water-logs HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 78
{
"amount": {
"value": 8,
"unit": "fl_oz"
},
"created_at": "2026-09-10T07:30:00-07:00"
}{
"id": "78129823-8ba2-4183-b13b-71f0e963c606",
"amount": {
"value": 8,
"unit": "fl_oz"
},
"created_at": "2026-09-10T14:30:00.000Z"
}API key or client token.
Returns one total per local calendar day between start_date and end_date (both inclusive, in timezone), oldest first, in the unit you ask for, rounded to one decimal place. Days with nothing logged are absent. 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 water_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.
2026-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 water logged, the most recent 100 are returned.
2026-09-10IANA 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_AngelesThe unit every daily total is returned in.
fl_ozPossible values: 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 |
One total per local day with water logged, 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); timezone is missing or not a valid IANA name; or unit is missing or not fl_oz/ml/cup.
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/water-logs?start_date=2026-09-01&end_date=2026-09-10&timezone=America%2FLos_Angeles&unit=fl_oz HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"date": "2026-09-10",
"total": {
"value": 64,
"unit": "fl_oz"
}
}
]
}API key or client token.
Idempotent: deleting an unknown or already-deleted log answers the same 204, so it is safe to retry. The amount no longer counts toward its day's cap.
Callable with a client token carrying the water_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.
The log id returned when the log was created.
78129823-8ba2-4183-b13b-71f0e963c606Pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$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 |
The log was deleted; empty body. Idempotent — deleting an already-deleted or unknown log also answers 204.
No content
log_id is not a UUID.
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.
DELETE /v1.2/water-logs/{log_id} HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Last updated
Was this helpful?