Patient (FHIR R4)
Demographic and administrative information about an individual receiving healthcare services. Maps to HuliPractice patient records including name, birth date, gender, contact information, and identifiers such as CURP.
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: Patient — 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}) - $everything — operation
Scopes
Scopes are shared across FHIR releases — the same system/Patient.* scope grants Patient access on both /fhir/R4 and /fhir/R5.
- system/Patient.rs — see scope reference
- system/Patient.cru — see scope reference
Search Parameters
| Parameter | Type | Notes |
|---|---|---|
_id | token | Exact match. For identifiers use `system |
identifier | token | Exact match. For identifiers use `system |
name | string | Case-insensitive partial match. |
gender | token | Exact match. For identifiers use `system |
birthdate | date | Supports FHIR date prefixes: eq, ne, gt, ge, lt, le. Format: [prefix]YYYY-MM-DD. |
active | token | Exact match. For identifiers use `system |
_count | number | Integer. For _count: default 20, max 100. |
_cursor | string | Case-insensitive partial match. |
Endpoints
Read Patient
Retrieve a single Patient resource by its ID.
/fhir/R4/Patient/{id}Required scope: system/Patient.rs
Response — 200
{
"resourceType": "Patient",
"id": "550e8400-e29b-41d4-a716-446655440001",
"meta": {
"lastUpdated": "2026-01-15T10:30:00Z"
},
"active": true,
"name": [
{
"use": "official",
"family": "Garcia",
"given": [
"Maria"
]
}
],
"gender": "female",
"birthDate": "1990-03-15",
"telecom": [
{
"system": "phone",
"value": "+52-555-0100",
"use": "mobile"
},
{
"system": "email",
"value": "maria.garcia@example.com"
}
],
"address": [
{
"use": "home",
"line": [
"Av. Reforma 222"
],
"city": "Ciudad de Mexico",
"state": "CDMX",
"postalCode": "06600",
"country": "MX"
}
],
"identifier": [
{
"system": "https://huli.ai/identifiers/curp",
"value": "GARM900315MDFRRL09"
}
]
}
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/Patient.rs" \
| jq -r .access_token)
curl -X GET https://api.huli.ai/fhir/R4/Patient/${RESOURCE_ID} \
-H "Authorization: Bearer ${TOKEN}"
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Patient/${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/Patient/{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 getPatientExample {
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/Patient/" + 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 getPatientExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("GET", "https://api.huli.ai/fhir/R4/Patient/"+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 Patient
Update an existing Patient resource. The request body must include resourceType: "Patient". Deceased patients cannot be updated (returns 422).
/fhir/R4/Patient/{id}Required scope: system/Patient.cru
Request Body
| name | type | required | description |
|---|---|---|---|
| resourceType | string | required | |
| id | string(uuid) | optional | Server-assigned resource ID. Do not include on create. |
| meta | object | optional | |
| active | boolean | optional | Whether this patient record is active. |
| name | array | optional | |
| gender | string | optional | Administrative gender. |
| birthDate | string(date) | optional | Date of birth (YYYY-MM-DD). |
| deceasedBoolean | boolean | optional | Whether the patient is deceased. |
| telecom | array | optional | |
| address | array | optional | |
| maritalStatus | object | optional | |
| contact | array | optional | Emergency contacts or next of kin. |
| identifier | array | optional | |
| extension | array | optional | FHIR extensions, rooted at the IG canonical base (`https://fhir.huli.ai/r4` on R4 operations, `https://fhir.huli.ai/r5` on R5 operations). Huli supports: - `second-lastname` (second/maternal surname) - `huli-blood-type` - `huli-private-insurance` |
Request Example
{
"resourceType": "Patient",
"id": "550e8400-e29b-41d4-a716-446655440001",
"active": true,
"name": [
{
"use": "official",
"family": "Garcia Lopez",
"given": [
"Maria"
]
}
],
"gender": "female",
"birthDate": "1990-03-15",
"telecom": [
{
"system": "phone",
"value": "+52-555-0101",
"use": "mobile"
}
]
}
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/Patient.cru" \
| jq -r .access_token)
curl -X PUT https://api.huli.ai/fhir/R4/Patient/${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/Patient/${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/Patient/{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 updatePatientExample {
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/Patient/" + 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 updatePatientExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("PUT", "https://api.huli.ai/fhir/R4/Patient/"+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 |
Patient $everything
Aggregate a patient's clinical record across Patient, Encounter, Observation, Composition, DocumentReference, MedicationRequest, and ServiceRequest into a single searchset Bundle. Each additional resource type is included only when the access token's SMART scopes grant read on it; withheld types are listed in an information OperationOutcome and signalled via a scope-filtered meta.tag. Optional start/end bound the date range; _count caps each per-type page; _type restricts the included resource types. Baseline scope: system/Patient.r.
/fhir/R4/Patient/{id}/$everythingRequired scope: system/Patient.r
Query Parameters
| name | type | required | description |
|---|---|---|---|
| start | string | optional | Inclusive lower date bound (YYYY-MM-DD). |
| end | string | optional | Inclusive upper date bound (YYYY-MM-DD). |
| _type | string | optional | Comma-separated list of resource types to include. |
| _count | integer | optional | Number of results per page (default: 20, max: 100). |
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/Patient.r" \
| jq -r .access_token)
curl -X GET https://api.huli.ai/fhir/R4/Patient/${RESOURCE_ID}/$everything \
-H "Authorization: Bearer ${TOKEN}"
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Patient/${id}/$everything`,
{
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/Patient/{resource_id}/$everything",
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 patientEverythingExample {
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/Patient/" + resourceId + "/$everything"))
.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 patientEverythingExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("GET", "https://api.huli.ai/fhir/R4/Patient/"+resourceID+"/$everything", 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 |
Search Patients
Search for Patient resources using FHIR search parameters. Results are returned as a FHIR Bundle with cursor-based pagination.
/fhir/R4/PatientRequired scope: system/Patient.rs
Query Parameters
| name | type | required | description |
|---|---|---|---|
| name | string | optional | Patient name (case-insensitive partial match). |
| gender | string | optional | Administrative gender. Values: `male`, `female`, `other`, `unknown`. |
| birthdate | string | optional | Date of birth. Supports FHIR date prefixes: `eq`, `ne`, `gt`, `ge`, `lt`, `le`. Format: `[prefix]YYYY-MM-DD`. |
| identifier | string | optional | Patient identifier in `system|value` format. |
| active | string | optional | Whether the patient record is active. |
| _id | string | optional | Patient resource ID (UUID). |
| _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. |
Response — 200
{
"resourceType": "Bundle",
"type": "searchset",
"total": 2,
"link": [
{
"relation": "self",
"url": "https://api.huli.ai/fhir/R4/Patient?name=Garcia&_count=20"
},
{
"relation": "next",
"url": "https://api.huli.ai/fhir/R4/Patient?name=Garcia&_count=20&_cursor=eyJ0IjoiMjAyNi0wMS0xNVQxMDozMDowMFoiLCJpIjoiNTUwZTg0MDAtZTI5Yi00MWQ0LWE3MTYtNDQ2NjU1NDQwMDAxIn0"
}
],
"entry": [
{
"fullUrl": "Patient/550e8400-e29b-41d4-a716-446655440001",
"resource": {
"resourceType": "Patient",
"id": "550e8400-e29b-41d4-a716-446655440001",
"active": true,
"name": [
{
"use": "official",
"family": "Garcia",
"given": [
"Maria"
]
}
],
"gender": "female",
"birthDate": "1990-03-15"
},
"search": {
"mode": "match"
}
}
]
}
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/Patient.rs" \
| jq -r .access_token)
curl -X GET https://api.huli.ai/fhir/R4/Patient \
-H "Authorization: Bearer ${TOKEN}"
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Patient`,
{
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/Patient",
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 searchPatientsExample {
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/Patient"))
.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 searchPatientsExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("GET", "https://api.huli.ai/fhir/R4/Patient", 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 Patient
Create a new Patient resource. The server assigns the resource ID; do not include id in the request body.
/fhir/R4/PatientRequired scope: system/Patient.cru
Request Body
| name | type | required | description |
|---|---|---|---|
| resourceType | string | required | |
| id | string(uuid) | optional | Server-assigned resource ID. Do not include on create. |
| meta | object | optional | |
| active | boolean | optional | Whether this patient record is active. |
| name | array | optional | |
| gender | string | optional | Administrative gender. |
| birthDate | string(date) | optional | Date of birth (YYYY-MM-DD). |
| deceasedBoolean | boolean | optional | Whether the patient is deceased. |
| telecom | array | optional | |
| address | array | optional | |
| maritalStatus | object | optional | |
| contact | array | optional | Emergency contacts or next of kin. |
| identifier | array | optional | |
| extension | array | optional | FHIR extensions, rooted at the IG canonical base (`https://fhir.huli.ai/r4` on R4 operations, `https://fhir.huli.ai/r5` on R5 operations). Huli supports: - `second-lastname` (second/maternal surname) - `huli-blood-type` - `huli-private-insurance` |
Request Example
{
"resourceType": "Patient",
"active": true,
"name": [
{
"use": "official",
"family": "Hernandez",
"given": [
"Carlos"
]
}
],
"gender": "male",
"birthDate": "1985-07-20",
"telecom": [
{
"system": "phone",
"value": "+52-555-0200",
"use": "mobile"
},
{
"system": "email",
"value": "carlos.hernandez@example.com"
}
],
"address": [
{
"use": "home",
"line": [
"Calle Madero 50"
],
"city": "Guadalajara",
"state": "Jalisco",
"postalCode": "44100",
"country": "MX"
}
]
}
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/Patient.cru" \
| jq -r .access_token)
curl -X POST https://api.huli.ai/fhir/R4/Patient \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/fhir+json" \
-d @patient.json
const token = process.env.HULI_ACCESS_TOKEN ?? "";
const response = await fetch(
`https://api.huli.ai/fhir/R4/Patient`,
{
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/Patient",
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 createPatientExample {
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/Patient"))
.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 createPatientExample() {
token := os.Getenv("HULI_ACCESS_TOKEN")
req, _ := http.NewRequest("POST", "https://api.huli.ai/fhir/R4/Patient", 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 |