Health Yourself collects questionnaire answers and blood results in your intake UX (see the Input Data Preparation Guide). Before calling Idunox, your backend maps that data into canonical Type A JSON — a structured subject block, a flat markers[] blood panel, optional sourceMetadata, and options.
Do not send legacy markers.healthQuestionnaireMarkers / markers.bloodMarkers arrays or top-level requestedAssessments. Those shapes are not accepted by the live partner API.
Optional integer and number fields on smoking and family history accept -1 as “not applicable” (TYPE_A_NOT_APPLICABLE in the platform). The server treats -1 like a missing value for branch rules (e.g. stopAge is not considered “set” when -1).
Prefer omitting a key when the intake branch does not collect that field.
Use -1 only when your serializer must send a number but the UI path is “Not applicable”.
Do not use -1 on blood markers[].value — values must be finite numbers within range.
Map intake labels to canonical enum values (lowercase snake_case). Omit keys that do not apply; do not send null for optional numbers unless your serializer requires it.
status (required when smoking is sent): never, former, current, prefer_not_to_saypastFrequency / currentFrequency (when allowed): none, light, moderate, heavy, unknown
UKB / intake label
Canonical frequency
I have never smoked
none
Just tried once or twice
light
Only occasionally
light
On most or all days
heavy
No (current-frequency auto)
none
Intake
Canonical field
Rules
Q006 Status
status
Never smoker → never; Former smoker → former; Current smoker → current
Q007 Past frequency
pastFrequency
Omit when status is never, current, or prefer_not_to_say. For former, map labels per table above.
Q008 Current frequency
currentFrequency
Only when status: "current". Must be omitted for former, never, and prefer_not_to_say (do not send "none" on former).
Q009 Current cigs/day
currentCigsPerDay
number 0..200 or -1. Only for current; must be omitted for former / never.
Q010 Past cigs/day
pastCigsPerDay
number 0..200 or -1. Omit for current / never.
Q011 Stop age
stopAge
integer 0..120 or -1. Required when status: "former" (use -1 on light/occasional former branches if needed). Omit for current / never.
Q012 Start age
startAge
integer 0..120 or -1. Heavy current or heavy former branch; otherwise omit.
Current smokers: provide currentCigsPerDay and/or currentFrequency (not unknown) so intensity is defined.Never / prefer not to say: send only status (or omit the whole smoking object for never-only paths); all other smoking keys must be omitted.
Align aliveStatus with ages. If father is deceased, send deathAge only (omit currentAge). If mother is alive, send currentAge only (omit deathAge). Swapping these causes validation errors.
Use canonical marker codes in markers[].code (not B### guide ids in the JSON body). Submit exactly 14 rows — one per code, no duplicates. Aliases resolve to the same canonical code (e.g. ALB → ALBUMIN, HBA1C → HBA1C_MMOL_MOL with mmol/mol unit).
B# (guide)
API code
Required unit
Default analytical value range*
B001
ALBUMIN
g/L
15..60
B002
ALT
U/L
3..500
B003
ALP
U/L
5..1500
B006
AST
U/L
3..1000
B007
CALCIUM
mmol/L
1..5
B008
CHOL
mmol/L
0.5..18
B010
CYSTATIN_C
mg/L
0.1..8.99
B012
GGT
U/L
5..1200
B014
HDL
mmol/L
0.05..4.65
B015
CRP
mg/L
0.08..80
B018
LDL
mmol/L
0.26..10.3
B020
PHOSPHATE
mmol/L
0.32..6.4
B028
URATE
µmol/L
89..1785
B030
HBA1C_MMOL_MOL
mmol/mol
15..515.2
*When sourceMetadata.markerRanges.{CODE} is present for a marker, validation uses your lowerBound..upperBound instead of the preset analytical range. µ / μ in units normalize to the same value as u for comparison.Accepted code aliases (non-exhaustive):ALB, CA, TCHOL / TOTAL_CHOLESTEROL, CYSTATIN, HDL_CHOLESTEROL, C_REACTIVE_PROTEIN, LDL_DIRECT, PHOS, UA, HBA1C (with mmol/mol unit only).Each array element:
{ "code": "ALT", "value": 28, "unit": "U/L" }
value must be a finite number (JSON number preferred).
Optional per-marker observedAt (ISO-8601); otherwise use sourceMetadata.sourceTimestamp for the panel.