detail, or only error, will silently lose the
message on roughly half of all failures.
The five envelopes
Read whichever key is present rather than assuming one. Branch oncode or
error_name when they appear — those are stable identifiers. The prose in
detail and error is written for humans and may be reworded.
Field validation — the most common by far
Field validation — the most common by far
An object keyed by field name, each value an array of messages.
There is no Several fields fail at once, so expect more than one key:Errors that belong to the request as a whole rather than to one field
arrive under For a list field, the value is an array positionally matching what you
sent — index 0 is the first item you submitted:
detail and no code here.non_field_errors:detail — permissions, routing and content negotiation
detail — permissions, routing and content negotiation
No WeightEntry matches the given query.), so match on the status code,
never on the string.detail with code — token failures
detail with code — token failures
Token problems add a machine-readable
code, and sometimes a messages
array with the specific reason.error with code — sign-in
error with code — sign-in
The auth endpoints use Some carry only the message:
error, not detail.error with error_name — recoverable business rules
error with error_name — recoverable business rules
These name a condition your client is expected to handle, and often carry
the data needed to recover from it.
A robust client reads, in order:
detail, then error, then the first message
of the first field in the object. Treat code and error_name as the thing you
branch on, and the prose as the thing you log.Status codes
400 — fix the input
Read the field map, correct the named fields, and resubmit. Two cases deserve special handling because they are not really input errors:-
PROFILE_INCOMPLETEat checkout returnsmissing_fields.PATCH/v1/users/profile/me/with exactly those fields, then retry the checkout. -
An unknown questionnaire slug is a
400, not a404:Fetch/v1/users/questionnaires/categories/for the valid slugs rather than guessing.
401 — re-authenticate
Distinguish the two causes, because the recovery differs:- On a normal endpoint — the access token is missing, expired or malformed.
Exchange the refresh token at
/v1/users/token/refresh/and replay the request once. If the refresh also returns401({ "detail": "Token is invalid", "code": "token_not_valid" }), the session is over; the patient must sign in again. - On sign-in itself —
code: "invalid_credentials". This is deliberately non-specific: it does not reveal whether the address exists, and it is also what an unverified account gets. Never render it as “no such account”.
404 — it may exist, just not for you
Every endpoint is scoped to the authenticated account. A record belonging to someone else is indistinguishable from one that does not exist — both return404. That is intentional: a 403 would confirm the record exists.
406 — the PDF trap
The invoice and prescription PDF endpoints reject a specific binaryAccept:
Accept: application/pdf — the obvious thing to send for a PDF — fails.
Send Accept: */* instead. Many HTTP clients set a specific Accept for you,
so this usually has to be overridden explicitly.
409 — already in that state
Returned when the request conflicts with the resource’s current state, such as reactivating a subscription that was never scheduled for cancellation:429 — back off
If you receive a429, stop and wait. Honour the Retry-After header if one is
present, otherwise retry with exponential backoff and jitter. Never retry in a
tight loop.
Rate limits
Hi-Doctor does not publish numeric rate limits for this API, and this page deliberately does not invent any. What is worth knowing:- The application layer does not apply a global throttle to these endpoints, so a limit you encounter in production comes from the edge in front of the API, not from the endpoint itself. Its configuration is not public and can change without a change to this reference.
- Because of that, you cannot infer a budget from testing. A sequence that succeeds today may be throttled tomorrow.
- Write your client so that a
429on any call is handled, rather than assuming only the auth endpoints are limited.
5xx
A5xx is a fault on Hi-Doctor’s side, not a problem with your request. Retry
idempotent reads with backoff. Do not blindly retry a write: a checkout, a
questionnaire submission or a message may have been recorded before the error
was returned. Re-read the resource to find out before sending it again.
Clinical outcomes are not errors
An ineligible questionnaire result is a200-level clinical decision, not a
failure to route around. Contraindications, interactions, age, BMI and country
are enforced at submission, and resubmitting altered answers to get a different
outcome is a misuse of the service.
Related
- Authentication — tokens, refresh and sign-in failures
- API reference — conventions and the typical flow
- Sign up a new patient — registration and verification failures