Public endpoints do not require authentication and are designed for patient-facing applications and portals.
Patient Registration
curl -X POST https://api.omniehr.com/public/patient-register \
-H "Content-Type: application/json" \
-d '{
"givenName": "John",
"familyName": "Doe",
"birthDate": "1985-06-15",
"gender": "male",
"phone": "+1-555-0123",
"email": "[email protected]",
"line1": "123 Main Street",
"city": "Springfield",
"state": "IL",
"postalCode": "62701"
}'
Register a new patient in the system. This endpoint is designed for patient portal self-registration.
Request Body
Patient’s given (first) name. Must be 1-120 characters.
Patient’s family (last) name. Must be 1-120 characters.
Patient’s date of birth in YYYY-MM-DD format (e.g., “1985-06-15”).
Patient’s gender. Must be one of: male, female, other, unknown. Defaults to unknown.
Patient’s phone number. Maximum 40 characters. Optional.
Patient’s email address. Must be a valid email format if provided. Optional.
First line of patient’s address (street address). Maximum 200 characters. Optional.
Patient’s city. Maximum 80 characters. Optional.
Patient’s state/province. Maximum 40 characters. Optional.
Patient’s postal/ZIP code. Maximum 20 characters. Optional.
Response
Success message confirming registration
Patient identifier (PID) - a unique sequential identifier assigned to the patient (e.g., “PAT-00001234”)
FHIR resource ID (MongoDB ObjectId) for the patient record
Complete FHIR Patient resourceArray of patient identifiers Patient record active status (always true for new registrations)
Array of contact informationContact system: “phone” or “email”
Patient’s birth date (YYYY-MM-DD)
Example Response
{
"message": "Registration completed",
"pid": "PAT-00001234",
"patientId": "65a1b2c3d4e5f6a7b8c9d0e4",
"patient": {
"resourceType": "Patient",
"id": "65a1b2c3d4e5f6a7b8c9d0e4",
"identifier": [
{
"system": "https://omniehr.com/patient-id",
"value": "PAT-00001234"
}
],
"active": true,
"name": [
{
"family": "Doe",
"given": ["John"]
}
],
"telecom": [
{
"system": "phone",
"value": "+1-555-0123"
},
{
"system": "email",
"value": "[email protected]"
}
],
"gender": "male",
"birthDate": "1985-06-15",
"address": [
{
"line": ["123 Main Street"],
"city": "Springfield",
"state": "IL",
"postalCode": "62701"
}
]
}
}
Minimal Registration Example
Only required fields:
curl -X POST https://api.omniehr.com/public/patient-register \
-H "Content-Type: application/json" \
-d '{
"givenName": "Jane",
"familyName": "Smith",
"birthDate": "1992-03-20"
}'
Example Response (Minimal)
{
"message": "Registration completed",
"pid": "PAT-00001235",
"patientId": "65a1b2c3d4e5f6a7b8c9d0e5",
"patient": {
"resourceType": "Patient",
"id": "65a1b2c3d4e5f6a7b8c9d0e5",
"identifier": [
{
"system": "https://omniehr.com/patient-id",
"value": "PAT-00001235"
}
],
"active": true,
"name": [
{
"family": "Smith",
"given": ["Jane"]
}
],
"telecom": [],
"gender": "unknown",
"birthDate": "1992-03-20",
"address": []
}
}
Validation Rules
All string fields are automatically trimmed of leading and trailing whitespace before validation.
Name Validation
givenName and familyName must be at least 1 character
- Maximum length: 120 characters
- Both fields are required
Birth Date Validation
- Must be in YYYY-MM-DD format (e.g., “1985-06-15”)
- Required field
- Must be a valid calendar date
Gender Validation
- Must be one of:
male, female, other, unknown
- Defaults to
unknown if not provided
- Optional field
- Phone: Maximum 40 characters, optional
- Email: Must be valid email format if provided, optional
Address Validation
- line1: Maximum 200 characters
- city: Maximum 80 characters
- state: Maximum 40 characters
- postalCode: Maximum 20 characters
- All address fields are optional
Error Responses
400 Bad Request
Returned when validation fails.
{
"error": "Validation failed",
"details": [
{
"field": "birthDate",
"message": "birthDate must be YYYY-MM-DD"
}
]
}
Common Validation Errors
{
"field": "givenName",
"message": "String must contain at least 1 character(s)"
}
{
"field": "familyName",
"message": "String must contain at least 1 character(s)"
}
{
"field": "birthDate",
"message": "birthDate must be YYYY-MM-DD"
}
{
"field": "email",
"message": "Invalid email"
}
{
"field": "gender",
"message": "Invalid enum value. Expected 'male' | 'female' | 'other' | 'unknown'"
}
500 Internal Server Error
Returned when an unexpected server error occurs.
{
"error": "Internal server error"
}
Patient Identifier (PID)
Every registered patient is automatically assigned a unique, sequential Patient Identifier (PID) in the format PAT-########.
The PID system provides:
- Sequential numbering: PIDs are assigned in order (PAT-00000001, PAT-00000002, etc.)
- Human-readable: Easy to reference in conversations and documentation
- Unique: Each patient receives exactly one PID that never changes
- FHIR compatible: Stored as a standard FHIR identifier with system URL
PID in FHIR Resource
The PID is always included in the patient’s identifier array:
{
"identifier": [
{
"system": "https://omniehr.com/patient-id",
"value": "PAT-00001234"
}
]
}
FHIR Compliance
This endpoint creates FHIR R4-compliant Patient resources. The response includes:
- Standard FHIR Patient resource structure
- Proper identifier system for PIDs
- Valid telecom and address arrays
- Compliant name structure with family and given names
- Standard gender and birthDate fields
Using the Patient Resource
The returned patient resource can be:
- Stored in patient-facing applications
- Referenced in subsequent FHIR API calls using the
patientId
- Used to link clinical resources (Observations, Conditions, etc.)
- Searched using the PID or FHIR resource ID
Example: Creating an Observation for a Registered Patient
After registration, you can create clinical resources:
curl -X POST https://api.omniehr.com/fhir/Observation \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Observation",
"status": "final",
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "29463-7",
"display": "Body Weight"
}]
},
"subject": {
"reference": "Patient/65a1b2c3d4e5f6a7b8c9d0e4"
},
"valueQuantity": {
"value": 70.5,
"unit": "kg",
"system": "http://unitsofmeasure.org",
"code": "kg"
}
}'
Integration Examples
const registerPatient = async (formData) => {
const response = await fetch('https://api.omniehr.com/public/patient-register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
givenName: formData.firstName,
familyName: formData.lastName,
birthDate: formData.dob, // YYYY-MM-DD format
gender: formData.gender,
phone: formData.phone,
email: formData.email,
line1: formData.address,
city: formData.city,
state: formData.state,
postalCode: formData.zipCode
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
const result = await response.json();
// Store PID and patient ID for future use
localStorage.setItem('patientId', result.patientId);
localStorage.setItem('pid', result.pid);
return result;
};
React Registration Component
import { useState } from 'react';
function PatientRegistration() {
const [formData, setFormData] = useState({
givenName: '',
familyName: '',
birthDate: '',
gender: 'unknown',
phone: '',
email: '',
line1: '',
city: '',
state: '',
postalCode: ''
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const response = await fetch('https://api.omniehr.com/public/patient-register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error);
}
const result = await response.json();
console.log('Registration successful:', result.pid);
// Redirect to confirmation page or next step
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
{error && <div className="error">{error}</div>}
<input
type="text"
placeholder="First Name"
value={formData.givenName}
onChange={(e) => setFormData({...formData, givenName: e.target.value})}
required
/>
<input
type="text"
placeholder="Last Name"
value={formData.familyName}
onChange={(e) => setFormData({...formData, familyName: e.target.value})}
required
/>
<input
type="date"
value={formData.birthDate}
onChange={(e) => setFormData({...formData, birthDate: e.target.value})}
required
/>
{/* Additional form fields */}
<button type="submit" disabled={loading}>
{loading ? 'Registering...' : 'Register'}
</button>
</form>
);
}