Recording Consultations
This guide covers how to record clinical consultations, retrieve consultation history, and work with the rich clinical data model that Jump EHR supports.
Overview
Consultations in Jump EHR document patient encounters with full clinical context, including:
- Chief complaint and summary
- Problems addressed (with SNOMED CT codes)
- Medications prescribed or reviewed
- Observations (vitals, measurements)
- Procedures performed
- Referrals made
- Attached documents
Required API Scopes
| Scope | Purpose |
|---|---|
read_consultations | List and retrieve consultations |
write_consultations | Create consultations |
read_patients | Access patient records |
Creating a Consultation
Basic Consultation
const API_BASE = 'https://app.usejump.co.uk/functions/v1/api-v1';
async function createConsultation(consultationData) {
const response = await fetch(`${API_BASE}/consultations`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
patient_id: consultationData.patientId,
consultation_date: consultationData.date, // YYYY-MM-DD
consultation_time: consultationData.time, // HH:MM:SS
appointment_id: consultationData.appointmentId, // Optional
consultation_type_code: consultationData.typeCode,
consultation_type_display: consultationData.typeDisplay,
chief_complaint: consultationData.chiefComplaint,
summary: consultationData.summary
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.details || 'Failed to create consultation');
}
const { data } = await response.json();
return data;
}Example: Creating a Follow-up Consultation
const consultation = await createConsultation({
patientId: 'pat_456e7890-e89b-12d3-a456-426614174111',
date: '2025-01-20',
time: '10:30:00',
appointmentId: 'apt_789a0123-e89b-12d3-a456-426614174222',
typeCode: '185316007',
typeDisplay: 'Indirect encounter',
chiefComplaint: 'Hypertension follow-up',
summary: 'Routine BP check, well controlled on current medication'
});Consultation Types
Use SNOMED CT codes for consultation type classification:
| Code | Display | Use Case |
|---|---|---|
185316007 | Indirect encounter | Phone/video consultations |
185317003 | Telephone encounter | Phone calls |
185318008 | Email encounter | Email consultations |
185320006 | Third party encounter | Family member consultation |
308646001 | Face to face encounter | In-person visits |
Consultation Medium
| Code | Display |
|---|---|
face-to-face | Face to Face |
telephone | Telephone |
video | Video Call |
email |
await createConsultation({
patientId: 'pat_123',
date: '2025-01-20',
time: '14:00:00',
consultation_type_code: '185317003',
consultation_type_display: 'Telephone encounter',
consultation_medium_code: 'telephone',
consultation_medium_display: 'Telephone',
chief_complaint: 'Medication query',
summary: 'Patient called regarding dosage timing'
});Retrieving Consultations
List Patient Consultations
async function getPatientConsultations(patientId, options = {}) {
const params = new URLSearchParams({
patient_id: patientId,
limit: options.limit || 100,
offset: options.offset || 0
});
const response = await fetch(`${API_BASE}/consultations?${params}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const result = await response.json();
return {
consultations: result.data,
pagination: result.pagination
};
}Get Full Consultation Details
The single consultation endpoint returns comprehensive clinical data:
async function getConsultation(consultationId) {
const response = await fetch(`${API_BASE}/consultations/${consultationId}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const { data } = await response.json();
return data;
}Consultation Response Structure
const consultation = await getConsultation('con_123');
// Core details
console.log(consultation.summary); // "Follow-up for hypertension"
console.log(consultation.chief_complaint); // "Blood pressure check"
console.log(consultation.consultation_date); // "2025-01-15"
console.log(consultation.status); // "completed"
// Clinician who conducted it
console.log(consultation.clinician_profiles.name); // "Dr Sarah Smith"
// Problems addressed
consultation.consultation_problems.forEach(cp => {
console.log(cp.patient_problems.snomed_display); // "Hypertensive disorder"
console.log(cp.episode_type); // "review"
console.log(cp.consultation_notes); // "BP stable"
});
// Medications reviewed/prescribed
consultation.consultation_medications.forEach(cm => {
console.log(cm.patient_medications.display_name); // "Amlodipine 5mg tablets"
console.log(cm.patient_medications.dosage_amount); // 1
console.log(cm.patient_medications.frequency); // "once daily"
});
// Observations (vitals)
consultation.consultation_observation_links.forEach(col => {
console.log(col.observations.code_display); // "Blood pressure panel"
col.observations.observation_component.forEach(comp => {
console.log(`${comp.code_display}: ${comp.value_quantity_value} ${comp.value_quantity_unit_display}`);
// "Systolic BP: 128 mmHg"
});
});Working with Clinical Data
Problems (Diagnoses)
Problems use SNOMED CT codes for standardized classification:
// Accessing problems from a consultation
consultation.consultation_problems.forEach(problem => {
const { patient_problems } = problem;
console.log({
code: patient_problems.snomed_code, // "38341003"
display: patient_problems.snomed_display, // "Hypertensive disorder"
status: patient_problems.status, // "active"
significance: patient_problems.significance // "major"
});
// Problem-specific notes from this consultation
problem.consultation_problem_headings.forEach(heading => {
console.log(`${heading.heading_type}: ${heading.content}`);
// "history: Patient reports compliance with medication"
// "examination: BP 128/82"
});
});Observations (Vitals)
// Extract blood pressure readings
function extractBloodPressure(consultation) {
const bpLink = consultation.consultation_observation_links?.find(
link => link.observations.code === '85354-9' // Blood pressure panel
);
if (!bpLink) return null;
const components = bpLink.observations.observation_component;
const systolic = components.find(c => c.code === '8480-6');
const diastolic = components.find(c => c.code === '8462-4');
return {
systolic: systolic?.value_quantity_value,
diastolic: diastolic?.value_quantity_value,
timestamp: bpLink.observations.effective_datetime
};
}
const bp = extractBloodPressure(consultation);
// { systolic: 128, diastolic: 82, timestamp: "2025-01-15T14:15:00Z" }Common Observation Codes
| Code | Display | Type |
|---|---|---|
85354-9 | Blood pressure panel | Composite |
8480-6 | Systolic BP | Numeric |
8462-4 | Diastolic BP | Numeric |
8867-4 | Heart rate | Numeric |
8310-5 | Body temperature | Numeric |
29463-7 | Body weight | Numeric |
8302-2 | Body height | Numeric |
39156-5 | BMI | Numeric |
Medications
// Get active medications from consultation
function getActiveMedications(consultation) {
return consultation.consultation_medications
.filter(cm => cm.patient_medications.status === 'active')
.map(cm => ({
name: cm.patient_medications.display_name,
dosage: `${cm.patient_medications.dosage_amount} ${cm.patient_medications.dosage_unit}`,
frequency: cm.patient_medications.frequency,
route: cm.patient_medications.route,
instructions: cm.patient_medications.instructions
}));
}Building a Consultation Timeline
Display a patient's consultation history:
async function getPatientTimeline(patientId) {
const { consultations } = await getPatientConsultations(patientId);
return consultations.map(c => ({
id: c.id,
date: c.consultation_date,
type: c.consultation_type || 'Consultation',
summary: c.summary || 'No summary',
clinician: c.patients?.first_name
? `${c.patients.first_name} ${c.patients.last_name}`
: 'Unknown',
status: c.status
}));
}Timeline Component
function ConsultationTimeline({ patientId }) {
const [consultations, setConsultations] = useState([]);
const [selectedId, setSelectedId] = useState(null);
const [details, setDetails] = useState(null);
useEffect(() => {
getPatientTimeline(patientId).then(setConsultations);
}, [patientId]);
const handleSelect = async (id) => {
setSelectedId(id);
const fullDetails = await getConsultation(id);
setDetails(fullDetails);
};
return (
<div className="timeline">
<ul className="timeline-list">
{consultations.map(c => (
<li
key={c.id}
className={selectedId === c.id ? 'selected' : ''}
onClick={() => handleSelect(c.id)}
>
<span className="date">{formatDate(c.date)}</span>
<span className="type">{c.type}</span>
<span className="summary">{c.summary}</span>
</li>
))}
</ul>
{details && (
<ConsultationDetail consultation={details} />
)}
</div>
);
}Linking to Appointments
Consultations can be linked to appointments for a complete workflow:
// After an appointment is completed, create the consultation
async function recordConsultationForAppointment(appointment, clinicalNotes) {
const consultation = await createConsultation({
patientId: appointment.patient_id,
appointmentId: appointment.id,
date: appointment.start_time.split('T')[0],
time: appointment.start_time.split('T')[1].substring(0, 8),
typeCode: '308646001',
typeDisplay: 'Face to face encounter',
chiefComplaint: clinicalNotes.chiefComplaint,
summary: clinicalNotes.summary
});
return consultation;
}Document Attachments
Consultations can have attached documents (letters, reports, etc.):
// Access documents from a consultation
consultation.patient_documents.forEach(doc => {
console.log({
title: doc.document_title,
type: doc.document_type,
url: doc.google_docs_url,
created: doc.created_at
});
});See the Documents API for uploading documents.
Webhook Events
Subscribe to consultation events for real-time updates:
| Event | Trigger |
|---|---|
consultation.created | New consultation recorded |
consultation.updated | Consultation details changed |
app.post('/webhooks', (req, res) => {
const event = req.body;
if (event.type === 'consultation.created') {
const consultation = event.data.object;
// Trigger downstream processes
notifyClinicalTeam(consultation);
updatePatientRecord(consultation.patient_id);
}
res.status(200).send('OK');
});Best Practices
Do:
- Always include consultation_date and patient_id
- Use SNOMED CT codes for standardized clinical terminology
- Link consultations to appointments when applicable
- Include a meaningful summary for quick reference
- Retrieve full details only when needed (list endpoints return minimal data)
⚠️
Don't:
- Create consultations without patient context
- Ignore the structured clinical data (problems, medications, observations)
- Store sensitive clinical notes in plain text summaries
- Fetch full consultation details for list views (use pagination)
Next Steps
- Learn about Patient Sync for managing patient records
- Build a Booking Widget for scheduling
- Explore the full Consultations API
- Set up Webhooks for consultation notifications