curl --request POST \
--url https://sandbox.rx.tera.health/v1/patient/symptoms \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"occurred_at": "2026-10-26T19:45:00Z",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner"
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
occurred_at: '2026-10-26T19:45:00Z',
symptom: 'nausea',
severity: 2,
note: 'Mild, after dinner'
})
};
fetch('https://sandbox.rx.tera.health/v1/patient/symptoms', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox.rx.tera.health/v1/patient/symptoms"
payload = {
"occurred_at": "2026-10-26T19:45:00Z",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "0190f5c9-7f80-7192-8cb4-3d4e5f607182",
"occurred_at": "2026-10-26T19:45:00Z",
"log_date": "2026-10-26",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner",
"is_red_flag": false,
"days_since_injection": 0,
"source": "brand_app",
"created_at": "2026-10-26T19:46:10Z",
"updated_at": "2026-10-26T19:46:10Z"
}Log a symptom
Severity 1 (mild) to 5 (severe). Alert rules run on every symptom: a red flag or a severe GI episode raises a
clinical flag (to the coach on the coached plan, to the brand’s prescriber on ai_only).
When the response has is_red_flag: true, show the emergency guidance (call 911, or 988 for a mental health
crisis) before anything else. Coaching is not emergency care.
Plans: AI + health and fitness coaches (ai_health_fitness), AI only (ai_only).
curl --request POST \
--url https://sandbox.rx.tera.health/v1/patient/symptoms \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"occurred_at": "2026-10-26T19:45:00Z",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner"
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
occurred_at: '2026-10-26T19:45:00Z',
symptom: 'nausea',
severity: 2,
note: 'Mild, after dinner'
})
};
fetch('https://sandbox.rx.tera.health/v1/patient/symptoms', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox.rx.tera.health/v1/patient/symptoms"
payload = {
"occurred_at": "2026-10-26T19:45:00Z",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "0190f5c9-7f80-7192-8cb4-3d4e5f607182",
"occurred_at": "2026-10-26T19:45:00Z",
"log_date": "2026-10-26",
"symptom": "nausea",
"severity": 2,
"note": "Mild, after dinner",
"is_red_flag": false,
"days_since_injection": 0,
"source": "brand_app",
"created_at": "2026-10-26T19:46:10Z",
"updated_at": "2026-10-26T19:46:10Z"
}Authorizations
A 15-minute token bound to one patient and one enrollment, issued by POST /v1/oauth/token with the
token-exchange grant. Treat it as opaque. When it expires, exchange a fresh assertion; there is no refresh token.
Headers
A unique key per logical request, for example a UUID. Retrying with the same key and the same body
within 24 hours returns the first response (with Idempotent-Replayed: true) instead of creating a duplicate.
The same key with a different body is refused with 422 idempotency_key_reused.
8 - 255Body
ISO 8601 in UTC.
"2026-10-26T14:05:00Z"
A symptom code, for example nausea, vomiting, diarrhea, constipation, reflux, fatigue, abdominal_pain.
These codes are red flags at any severity: chest_pain, difficulty_breathing, fainting,
severe_abdominal_pain, persistent_vomiting, blood_in_vomit, blood_in_stool, yellow_skin_or_eyes,
severe_dehydration, allergic_reaction, swelling_face_or_throat, vision_changes, suicidal_thoughts,
self_harm. Any symptom at severity 5 is one too. A brand's own alert rules can add codes.
^[a-z][a-z0-9_]*$"nausea"
1 <= x <= 52
The patient's own words. Read by the care team and, on a clinical flag, the prescriber.
1000"Mild, after dinner"
Your own identifier, printable ASCII without spaces.
1 - 128^[\x21-\x7E]+$"sym-20931"
Response
Logged.
ISO 8601 in UTC.
"2026-10-26T14:05:00Z"
A symptom code, for example nausea, vomiting, diarrhea, constipation, reflux, fatigue, abdominal_pain.
These codes are red flags at any severity: chest_pain, difficulty_breathing, fainting,
severe_abdominal_pain, persistent_vomiting, blood_in_vomit, blood_in_stool, yellow_skin_or_eyes,
severe_dehydration, allergic_reaction, swelling_face_or_throat, vision_changes, suicidal_thoughts,
self_harm. Any symptom at severity 5 is one too. A brand's own alert rules can add codes.
^[a-z][a-z0-9_]*$"nausea"
1 <= x <= 52
"0190f5c9-7f80-7192-8cb4-3d4e5f607182"
A calendar date in the patient's time zone.
"2026-10-26"
Set by TeraRx from the symptom and severity (see symptom). When true, show the emergency guidance (911, 988)
right away; the clinical flag to the care team or prescriber follows.
false
Set by the API from the caller. brand_api for brand servers, brand_app for patient tokens issued to a brand.
app, brand_app, brand_api, wearable, coach, ai, system "brand_app"
ISO 8601 in UTC.
"2026-10-26T14:05:00Z"
When the log was last corrected; the same as created_at until then.
"2026-10-26T14:05:00Z"
The patient's own words. Read by the care team and, on a clinical flag, the prescriber.
1000"Mild, after dinner"
Your own identifier, printable ASCII without spaces.
1 - 128^[\x21-\x7E]+$"sym-20931"
2

