Corsano Vital Signs Webhook Specification (HL7)
The webhook sends vital signs in one of two HL7 formats: HL7 FHIR R5 or HL7 v2.5.1. Select the format with the payload format setting (hl7-fhir or hl7-v2). Each section below shows both formats in tabs, so you can compare them. When you select a tab, all the tabs on the page change to that format. We welcome you to test out our webhook and share your feedback.

1. Overview
The webhook delivers physiological measurements collected or derived by the Corsano wearable.
| HL7 FHIR R5 | HL7 v2.5.1 | |
|---|---|---|
| Payload | FHIR Bundle in JSON | ORU^R01 message in pipe-delimited (ER7) encoding |
| Content-Type | application/fhir+json | x-application/hl7-v2+er7; charset=utf-8 |
| One measurement | One Observation | One OBX segment |
| Blood pressure | One Observation with systolic and diastolic components | Two OBX segments: systolic and diastolic |
| Measurement time | effectiveDateTime | OBR-7 and OBX-14 |
| Recommended response | HTTP 204 No Content | HTTP 200 with an HL7 ACK |
Supported measurements:
| Measurement | LOINC | Unit | FHIR identifier suffix | HL7 v2 OBX-4 |
|---|---|---|---|---|
| Heart rate | 8867-4 | /min | _hr | hr |
| SpO2 | 2708-6 | % | _spo2 | spo2 |
| Respiratory rate | 9279-1 | /min | _rr | rr |
| Body temperature | 8310-5 | Cel or [degF] | _temp | temp |
| Blood pressure panel (FHIR only) | 85354-9 | mm[Hg] | _bp | — |
| Systolic blood pressure | 8480-6 | mm[Hg] | _bp (component) | bp |
| Diastolic blood pressure | 8462-4 | mm[Hg] | _bp (component) | bp |
Measurements are normally generated approximately once per minute.
2. Webhook
Production endpoints use HTTPS.
- HL7 FHIR R5
- HL7 v2.5.1
POST
Content-Type: application/fhir+json
The request body contains a FHIR R5 Bundle.
{
"resourceType": "Bundle",
"type": "collection",
"timestamp": "2026-08-18T16:40:00+02:00",
"entry": []
}
Each measurement is represented as an Observation.
Heart rate, SpO2, respiratory rate and temperature use separate Observations.
Blood pressure uses one Observation containing systolic and diastolic components.
POST
Content-Type: x-application/hl7-v2+er7; charset=utf-8
The request body contains one HL7 v2 ORU^R01 message.
Segments are separated by a carriage return (\r, 0x0D).
The message uses these segments:
MSH Message header
PID Patient identification
{
OBR One observation group per measurement time
{ OBX } One or more observations
}
Heart rate, SpO2, respiratory rate and temperature use one OBX segment each.
Blood pressure uses two OBX segments: one for systolic and one for diastolic.
Message header (MSH) example:
MSH|^~\&|CORSANO|CORSANO_ONPREM|EMR|HOSPITAL|20260818164005+0200||ORU^R01^ORU_R01|6f1c2a9e-8d4b-4e7a-9c1f-2b3d4e5f6a7b|P|2.5.1|||NE|NE||UNICODE UTF-8
| Field | Name | Value |
|---|---|---|
| MSH-3 | Sending application | CORSANO |
| MSH-4 | Sending facility | CORSANO_ONPREM |
| MSH-5 | Receiving application | Agreed as part of the integration |
| MSH-6 | Receiving facility | Agreed as part of the integration |
| MSH-7 | Message date/time | Time the message was created |
| MSH-9 | Message type | ORU^R01^ORU_R01 |
| MSH-10 | Message control ID | Unique for each message |
| MSH-11 | Processing ID | P (production) or T (test) |
| MSH-12 | Version | 2.5.1 |
| MSH-18 | Character set | UNICODE UTF-8 |
Observation request (OBR): each OBR segment groups all measurements with the same measurement time.
OBR|1||RABNC_1787064000000^CORSANO|85353-1^Vital signs panel^LN|||20260818164000+0200||||||||||||||||||F
| Field | Name | Value |
|---|---|---|
| OBR-1 | Set ID | 1, 2, 3, ... |
| OBR-3 | Filler order number | <patient>_<epoch milliseconds>^CORSANO |
| OBR-4 | Universal service identifier | 85353-1^Vital signs panel^LN |
| OBR-7 | Observation date/time | Measurement time |
| OBR-25 | Result status | F (final) |
3. Common Observation Fields
- HL7 FHIR R5
- HL7 v2.5.1
Each Observation contains:
resourceType
identifier
status
category
code
subject
effectiveDateTime
Scalar measurements also contain:
valueQuantity
Example category:
{
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
]
}
]
}
Completed measurements use:
{
"status": "final"
}
Each OBX segment contains:
| Field | Name | Value |
|---|---|---|
| OBX-1 | Set ID | 1, 2, 3, ... within the OBR group |
| OBX-2 | Value type | NM (numeric) |
| OBX-3 | Observation identifier | <LOINC>^<display>^LN |
| OBX-4 | Observation sub-ID | hr, spo2, rr, temp, bp |
| OBX-5 | Observation value | Numeric value |
| OBX-6 | Units | <UCUM>^<display>^UCUM |
| OBX-11 | Result status | F (final) |
| OBX-14 | Observation date/time | Measurement time |
Completed measurements use:
OBX-11 F
4. Patient
The patient identifier and mapping to the receiving EMR are agreed as part of the integration.
- HL7 FHIR R5
- HL7 v2.5.1
The patient is referenced through subject.
{
"subject": {
"reference": "Patient/RABNC"
}
}
The patient is identified through PID-3.
PID|1||RABNC^^^CORSANO^PI
| Component | Value |
|---|---|
| ID | RABNC |
| Assigning authority | CORSANO |
| Identifier type | PI (patient internal identifier) |
5. Observation Identifier
Each observation has a unique and stable identifier. The identifier is the same in both formats, for example RABNC_1787064000000_hr.
The identifier remains unchanged if the same measurement is delivered again.
- HL7 FHIR R5
- HL7 v2.5.1
{
"identifier": [
{
"system": "https://corsano.com/fhir/observation",
"value": "RABNC_1787064000000_hr"
}
]
}
Recommended suffixes:
_hr
_spo2
_rr
_temp
_bp
The identifier is the combination of:
OBR-3 RABNC_1787064000000
OBX-4 hr
Result:
RABNC_1787064000000_hr
OBX-4 values:
hr
spo2
rr
temp
bp
Systolic and diastolic blood pressure share OBX-4 bp.
MSH-10 changes for each delivery. Do not use MSH-10 to find duplicate measurements.
6. Heart Rate
LOINC: 8867-4
- HL7 FHIR R5
- HL7 v2.5.1
{
"resourceType": "Observation",
"identifier": [
{
"system": "https://corsano.com/fhir/observation",
"value": "RABNC_1787064000000_hr"
}
],
"status": "final",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8867-4",
"display": "Heart rate"
}
]
},
"subject": {
"reference": "Patient/RABNC"
},
"effectiveDateTime": "2026-08-18T16:40:00+02:00",
"valueQuantity": {
"value": 72,
"unit": "beats/minute",
"system": "http://unitsofmeasure.org",
"code": "/min"
}
}
OBX|1|NM|8867-4^Heart rate^LN|hr|72|/min^beats/minute^UCUM|||||F|||20260818164000+0200
7. SpO2
LOINC: 2708-6
- HL7 FHIR R5
- HL7 v2.5.1
Example value:
{
"valueQuantity": {
"value": 98,
"unit": "%",
"system": "http://unitsofmeasure.org",
"code": "%"
}
}
OBX|2|NM|2708-6^Oxygen saturation^LN|spo2|98|%^%^UCUM|||||F|||20260818164000+0200
8. Respiratory Rate
LOINC: 9279-1
- HL7 FHIR R5
- HL7 v2.5.1
Example value:
{
"valueQuantity": {
"value": 21.75,
"unit": "breaths/minute",
"system": "http://unitsofmeasure.org",
"code": "/min"
}
}
OBX|3|NM|9279-1^Respiratory rate^LN|rr|21.75|/min^breaths/minute^UCUM|||||F|||20260818164000+0200
9. Body Temperature
LOINC: 8310-5
- HL7 FHIR R5
- HL7 v2.5.1
Celsius uses UCUM Cel.
{
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8310-5",
"display": "Body temperature"
}
],
"text": "Core body temperature"
},
"valueQuantity": {
"value": 37.1,
"unit": "°C",
"system": "http://unitsofmeasure.org",
"code": "Cel"
}
}
Fahrenheit uses UCUM [degF].
{
"valueQuantity": {
"value": 98.8,
"unit": "°F",
"system": "http://unitsofmeasure.org",
"code": "[degF]"
}
}
Celsius uses UCUM Cel.
OBX|4|NM|8310-5^Body temperature^LN|temp|37.1|Cel^°C^UCUM|||||F|||20260818164000+0200
Fahrenheit uses UCUM [degF].
OBX|4|NM|8310-5^Body temperature^LN|temp|98.8|[degF]^°F^UCUM|||||F|||20260818164000+0200
10. Blood Pressure
Systolic blood pressure: 8480-6
Diastolic blood pressure: 8462-4
Both values use UCUM mm[Hg].
- HL7 FHIR R5
- HL7 v2.5.1
Blood pressure uses one Observation with LOINC 85354-9 (blood pressure panel). Systolic and diastolic are components.
{
"resourceType": "Observation",
"identifier": [
{
"system": "https://corsano.com/fhir/observation",
"value": "RABNC_1787064000000_bp"
}
],
"status": "final",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "85354-9",
"display": "Blood pressure panel with all children optional"
}
],
"text": "Blood pressure"
},
"subject": {
"reference": "Patient/RABNC"
},
"effectiveDateTime": "2026-08-18T16:40:00+02:00",
"component": [
{
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8480-6",
"display": "Systolic blood pressure"
}
]
},
"valueQuantity": {
"value": 118,
"unit": "mmHg",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
},
{
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8462-4",
"display": "Diastolic blood pressure"
}
]
},
"valueQuantity": {
"value": 76,
"unit": "mmHg",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
}
]
}
Blood pressure uses two OBX segments with OBX-4 bp: one for systolic and one for diastolic.
OBX|5|NM|8480-6^Systolic blood pressure^LN|bp|118|mm[Hg]^mmHg^UCUM|||||F|||20260818164000+0200
OBX|6|NM|8462-4^Diastolic blood pressure^LN|bp|76|mm[Hg]^mmHg^UCUM|||||F|||20260818164000+0200
A blood pressure measurement always contains both segments.
11. Complete Example
- HL7 FHIR R5
- HL7 v2.5.1
The Bundle contains one entry for each Observation. The Observations are the same as in sections 6–10.
MSH|^~\&|CORSANO|CORSANO_ONPREM|EMR|HOSPITAL|20260818164005+0200||ORU^R01^ORU_R01|6f1c2a9e-8d4b-4e7a-9c1f-2b3d4e5f6a7b|P|2.5.1|||NE|NE||UNICODE UTF-8
PID|1||RABNC^^^CORSANO^PI
OBR|1||RABNC_1787064000000^CORSANO|85353-1^Vital signs panel^LN|||20260818164000+0200||||||||||||||||||F
OBX|1|NM|8867-4^Heart rate^LN|hr|72|/min^beats/minute^UCUM|||||F|||20260818164000+0200
OBX|2|NM|2708-6^Oxygen saturation^LN|spo2|98|%^%^UCUM|||||F|||20260818164000+0200
OBX|3|NM|9279-1^Respiratory rate^LN|rr|21.75|/min^breaths/minute^UCUM|||||F|||20260818164000+0200
OBX|4|NM|8310-5^Body temperature^LN|temp|37.1|Cel^°C^UCUM|||||F|||20260818164000+0200
OBX|5|NM|8480-6^Systolic blood pressure^LN|bp|118|mm[Hg]^mmHg^UCUM|||||F|||20260818164000+0200
OBX|6|NM|8462-4^Diastolic blood pressure^LN|bp|76|mm[Hg]^mmHg^UCUM|||||F|||20260818164000+0200
12. Measurement Time
Each measurement contains the time represented by the measurement. Timestamps include the timezone.
When several minutes are included in one webhook, each measurement keeps its own timestamp.
- HL7 FHIR R5
- HL7 v2.5.1
{
"effectiveDateTime": "2026-08-18T16:40:00+02:00"
}
Each OBR and OBX contains the measurement time.
20260818164000+0200
The format is YYYYMMDDHHMMSS+ZZZZ.
Each minute has its own OBR group.
OBR|1||RABNC_1787064000000^CORSANO|...|||20260818164000+0200|...
OBX|1|NM|8867-4^Heart rate^LN|hr|72|...
OBR|2||RABNC_1787064060000^CORSANO|...|||20260818164100+0200|...
OBX|1|NM|8867-4^Heart rate^LN|hr|74|...
13. Units
| Measurement | Display | UCUM |
|---|---|---|
| Heart rate | beats/minute | /min |
| SpO2 | % | % |
| Respiratory rate | breaths/minute | /min |
| Temperature | °C | Cel |
| Temperature | °F | [degF] |
| Blood pressure | mmHg | mm[Hg] |
- HL7 FHIR R5
- HL7 v2.5.1
The machine readable unit system is:
http://unitsofmeasure.org
The coding system in OBX-6 is:
UCUM
14. Webhook Response
Successful processing returns HTTP 2xx.
- HL7 FHIR R5
- HL7 v2.5.1
Recommended:
HTTP/1.1 204 No Content
Supported error responses:
400 Invalid request
401 Authentication failed
403 Not authorized
422 Invalid FHIR or measurement data
429 Rate limit
500 Server error
Recommended: HTTP 200 with an HL7 ACK message in the body.
HTTP/1.1 200 OK
Content-Type: x-application/hl7-v2+er7; charset=utf-8
MSH|^~\&|EMR|HOSPITAL|CORSANO|CORSANO_ONPREM|20260818164006+0200||ACK^R01^ACK|ACK-0001|P|2.5.1
MSA|AA|6f1c2a9e-8d4b-4e7a-9c1f-2b3d4e5f6a7b
MSA-2 contains the MSH-10 value of the received message.
MSA-1 values:
| Code | Meaning |
|---|---|
AA | Accepted |
AE | Error. The message is sent again. |
AR | Rejected. The message is not sent again. |
HTTP 204 No Content without a body is also accepted as success.
Supported error responses:
400 Invalid request
401 Authentication failed
403 Not authorized
422 Invalid HL7 message or measurement data
429 Rate limit
500 Server error
15. Validation
- HL7 FHIR R5
- HL7 v2.5.1
Payloads are validated against FHIR R5.
The integration also verifies:
- LOINC codes
- UCUM units
- patient references
- observation timestamps
- blood pressure component structure
- compatibility with the receiving EMR
Messages are validated against HL7 v2.5.1.
The integration also verifies:
- message structure (
ORU^R01) - LOINC codes
- UCUM units
- patient identifiers
- observation timestamps
- blood pressure systolic and diastolic pair
- compatibility with the receiving EMR