Observation (FHIR R4)
Measurements and simple assertions made about a patient, device, or other subject. Used for vital signs (heart rate, temperature, blood pressure), laboratory results, and clinical exam findings. LOINC codes are validated on write.
This reference is generated from the canonical Huli Public API OpenAPI specification and the server's FHIR R4 CapabilityStatement — do not edit it directly.
FHIR R4 Specification
Official spec: Observation — HL7 FHIR R4
Supported Interactions
- read — Read a single resource by ID (
GET /fhir/R4/{Resource}/{id}) - search-type — Search resources with query parameters (
GET /fhir/R4/{Resource}?...) - create — Create a new resource (
POST /fhir/R4/{Resource}) - update — Update an existing resource (
PUT /fhir/R4/{Resource}/{id})
Scopes
Scopes are shared across FHIR releases — the same system/Observation.* scope grants Observation access on both /fhir/R4 and /fhir/R5.
- system/Observation.rs — see scope reference
- system/Observation.cru — see scope reference
Search Parameters
| Parameter | Type | Notes |
|---|---|---|
_id | token | Exact match. For identifiers use `system |
patient | reference | Resource reference — supply the UUID of the referenced resource. |
encounter | reference | Resource reference — supply the UUID of the referenced resource. |
code | token | Exact match. For identifiers use `system |
date | date | Supports FHIR date prefixes: eq, ne, gt, ge, lt, le. Format: [prefix]YYYY-MM-DD. |
status | token | Exact match. For identifiers use `system |
category | token | Exact match. For identifiers use `system |
_count | number | Integer. For _count: default 20, max 100. |
_cursor | string | Case-insensitive partial match. |
Endpoints
Read Observation
Retrieve a single Observation resource by its ID.
/fhir/R4/Observation/{id}Required scope: system/Observation.rs
Response — 200
{
"resourceType": "Observation",
"id": "aa0e8400-e29b-41d4-a716-446655440040",
"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/550e8400-e29b-41d4-a716-446655440001"
},
"encounter": {
"reference": "Encounter/990e8400-e29b-41d4-a716-446655440030"
},
"effectiveDateTime": "2026-05-20T10:15:00Z",
"valueQuantity": {
"value": 72,
"unit": "/min",
"system": "http://unitsofmeasure.org",
"code": "/min"
}
}
Code Samples
TOKEN=$(curl -s -X POST https://api.huli.ai/auth/token \
-d "grant_type=client_credentials" \
-d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
-d "client_assertion=${CLIENT_ASSERTION}" \
-d "scope=system/Observation.rs" \
| jq -r .access_token)
curl -X GET https://api.huli.ai/fhir/R4/Observation/${RESOURCE_ID} \
-H "Authorization: Bearer ${TOKEN}"
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Observation/${id}`,
{
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
},
}
);
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
const data: unknown = await response.json();
import os
import requests
token = os.environ["HULI_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {token}"}
resp = requests.get(
f"https://api.huli.ai/fhir/R4/Observation/{resource_id}",
headers=headers,
)
resp.raise_for_status()
print(resp.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class getObservationExample {
public static void main(String[] args) throws Exception {
String token = System.getenv("HULI_ACCESS_TOKEN");
String resourceId = "RESOURCE_ID";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.huli.ai/fhir/R4/Observation/" + resourceId))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/fhir+json")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("status: " + response.statusCode());
System.out.println(response.body());
}
}
import (
"fmt"
"net/http"
"os"
)
func getObservationExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("GET", "https://api.huli.ai/fhir/R4/Observation/"+resourceID+"", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.Status)
}
Errors
| Code | Status | Description |
|---|---|---|
| HPB-00106 | 401 | Authentication failed |
| HPB-00104 | 403 | Insufficient scope |
| HPB-00102 | 404 | Resource not found |
| HPB-00105 | 429 | Rate limit exceeded |
Update Observation
Update an existing Observation resource.
/fhir/R4/Observation/{id}Required scope: system/Observation.cru
Request Body
| name | type | required | description |
|---|---|---|---|
| resourceType | string | required | |
| id | string(uuid) | optional | |
| meta | object | optional | |
| status | string | required | Observation status. |
| category | array | optional | |
| code | object | required | |
| subject | object | optional | |
| encounter | object | optional | |
| effectiveDateTime | string(date-time) | optional | Clinically relevant time for the observation. |
| valueQuantity | object | optional | Numeric observation value with unit. |
| valueCodeableConcept | object | optional | |
| valueString | string | optional |
Request Example
{
"resourceType": "Observation",
"id": "aa0e8400-e29b-41d4-a716-446655440040",
"status": "amended",
"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/550e8400-e29b-41d4-a716-446655440001"
},
"encounter": {
"reference": "Encounter/990e8400-e29b-41d4-a716-446655440030"
},
"effectiveDateTime": "2026-05-20T10:15:00Z",
"valueQuantity": {
"value": 74,
"unit": "/min",
"system": "http://unitsofmeasure.org",
"code": "/min"
}
}
Code Samples
TOKEN=$(curl -s -X POST https://api.huli.ai/auth/token \
-d "grant_type=client_credentials" \
-d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
-d "client_assertion=${CLIENT_ASSERTION}" \
-d "scope=system/Observation.cru" \
| jq -r .access_token)
curl -X PUT https://api.huli.ai/fhir/R4/Observation/${RESOURCE_ID} \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/fhir+json" \
-d @resource.json
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Observation/${id}`,
{
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/fhir+json",
},
body: JSON.stringify(payload),
}
);
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
const data: unknown = await response.json();
import os
import requests
token = os.environ["HULI_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/fhir+json"}
resp = requests.put(
f"https://api.huli.ai/fhir/R4/Observation/{resource_id}",
headers=headers,
json=payload,
)
resp.raise_for_status()
print(resp.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class updateObservationExample {
public static void main(String[] args) throws Exception {
String token = System.getenv("HULI_ACCESS_TOKEN");
String resourceId = "RESOURCE_ID";
String payload = "{}"; // your serialized FHIR resource
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.huli.ai/fhir/R4/Observation/" + resourceId))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/fhir+json")
.header("Content-Type", "application/fhir+json")
.method("PUT", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("status: " + response.statusCode());
System.out.println(response.body());
}
}
import (
"fmt"
"net/http"
"os"
)
func updateObservationExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("PUT", "https://api.huli.ai/fhir/R4/Observation/"+resourceID+"", body)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/fhir+json")
// set req.Body to your serialized resource
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.Status)
}
Errors
| Code | Status | Description |
|---|---|---|
| HPB-00101 | 400 | Validation error |
| HPB-00106 | 401 | Authentication failed |
| HPB-00104 | 403 | Insufficient scope |
| HPB-00102 | 404 | Resource not found |
| HPB-00101 | 422 | Unprocessable entity |
| HPB-00105 | 429 | Rate limit exceeded |
Search Observations
Search for Observation resources using FHIR search parameters.
/fhir/R4/ObservationRequired scope: system/Observation.rs
Query Parameters
| name | type | required | description |
|---|---|---|---|
| patient | string | optional | Patient reference (UUID). |
| encounter | string | optional | Encounter reference (UUID). |
| code | string | optional | Observation code (LOINC). Example: `8867-4` for heart rate. |
| date | string | optional | Observation effective date. Supports FHIR date prefixes: `eq`, `ne`, `gt`, `ge`, `lt`, `le`. |
| status | string | optional | Observation status: `registered`, `preliminary`, `final`, `amended`, `corrected`, `cancelled`, `entered-in-error`. |
| category | string | optional | Observation category: `vital-signs`, `laboratory`, `exam`. |
| _count | integer | optional | Number of results per page (default: 20, max: 100). |
| _cursor | string | optional | Opaque pagination cursor from the `next` link of a previous search result. |
Code Samples
TOKEN=$(curl -s -X POST https://api.huli.ai/auth/token \
-d "grant_type=client_credentials" \
-d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
-d "client_assertion=${CLIENT_ASSERTION}" \
-d "scope=system/Observation.rs" \
| jq -r .access_token)
curl -X GET https://api.huli.ai/fhir/R4/Observation \
-H "Authorization: Bearer ${TOKEN}"
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Observation`,
{
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
},
}
);
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
const data: unknown = await response.json();
import os
import requests
token = os.environ["HULI_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {token}"}
resp = requests.get(
f"https://api.huli.ai/fhir/R4/Observation",
headers=headers,
)
resp.raise_for_status()
print(resp.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class searchObservationsExample {
public static void main(String[] args) throws Exception {
String token = System.getenv("HULI_ACCESS_TOKEN");
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.huli.ai/fhir/R4/Observation"))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/fhir+json")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("status: " + response.statusCode());
System.out.println(response.body());
}
}
import (
"fmt"
"net/http"
"os"
)
func searchObservationsExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("GET", "https://api.huli.ai/fhir/R4/Observation", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.Status)
}
Errors
| Code | Status | Description |
|---|---|---|
| HPB-00106 | 401 | Authentication failed |
| HPB-00104 | 403 | Insufficient scope |
| HPB-00105 | 429 | Rate limit exceeded |
Create Observation
Create a new Observation resource. The server assigns the resource ID. LOINC codes are validated.
/fhir/R4/ObservationRequired scope: system/Observation.cru
Request Body
| name | type | required | description |
|---|---|---|---|
| resourceType | string | required | |
| id | string(uuid) | optional | |
| meta | object | optional | |
| status | string | required | Observation status. |
| category | array | optional | |
| code | object | required | |
| subject | object | optional | |
| encounter | object | optional | |
| effectiveDateTime | string(date-time) | optional | Clinically relevant time for the observation. |
| valueQuantity | object | optional | Numeric observation value with unit. |
| valueCodeableConcept | object | optional | |
| valueString | string | optional |
Request Example
{
"resourceType": "Observation",
"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": "8310-5",
"display": "Body temperature"
}
]
},
"subject": {
"reference": "Patient/550e8400-e29b-41d4-a716-446655440001"
},
"encounter": {
"reference": "Encounter/990e8400-e29b-41d4-a716-446655440030"
},
"effectiveDateTime": "2026-05-20T10:15:00Z",
"valueQuantity": {
"value": 36.6,
"unit": "Cel",
"system": "http://unitsofmeasure.org",
"code": "Cel"
}
}
Code Samples
TOKEN=$(curl -s -X POST https://api.huli.ai/auth/token \
-d "grant_type=client_credentials" \
-d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
-d "client_assertion=${CLIENT_ASSERTION}" \
-d "scope=system/Observation.cru" \
| jq -r .access_token)
curl -X POST https://api.huli.ai/fhir/R4/Observation \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/fhir+json" \
-d @observation.json
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Observation`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/fhir+json",
},
body: JSON.stringify(payload),
}
);
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
const data: unknown = await response.json();
import os
import requests
token = os.environ["HULI_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/fhir+json"}
resp = requests.post(
f"https://api.huli.ai/fhir/R4/Observation",
headers=headers,
json=payload,
)
resp.raise_for_status()
print(resp.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class createObservationExample {
public static void main(String[] args) throws Exception {
String token = System.getenv("HULI_ACCESS_TOKEN");
String payload = "{}"; // your serialized FHIR resource
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.huli.ai/fhir/R4/Observation"))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/fhir+json")
.header("Content-Type", "application/fhir+json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("status: " + response.statusCode());
System.out.println(response.body());
}
}
import (
"fmt"
"net/http"
"os"
)
func createObservationExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("POST", "https://api.huli.ai/fhir/R4/Observation", body)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/fhir+json")
// set req.Body to your serialized resource
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.Status)
}
Errors
| Code | Status | Description |
|---|---|---|
| HPB-00101 | 400 | Validation error |
| HPB-00106 | 401 | Authentication failed |
| HPB-00104 | 403 | Insufficient scope |
| HPB-00101 | 422 | Unprocessable entity |
| HPB-00105 | 429 | Rate limit exceeded |