API Documentation is in beta. Report issues to developers@jump.health
Recording Consultations

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

ScopePurpose
read_consultationsList and retrieve consultations
write_consultationsCreate consultations
read_patientsAccess 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:

CodeDisplayUse Case
185316007Indirect encounterPhone/video consultations
185317003Telephone encounterPhone calls
185318008Email encounterEmail consultations
185320006Third party encounterFamily member consultation
308646001Face to face encounterIn-person visits

Consultation Medium

CodeDisplay
face-to-faceFace to Face
telephoneTelephone
videoVideo Call
emailEmail
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

CodeDisplayType
85354-9Blood pressure panelComposite
8480-6Systolic BPNumeric
8462-4Diastolic BPNumeric
8867-4Heart rateNumeric
8310-5Body temperatureNumeric
29463-7Body weightNumeric
8302-2Body heightNumeric
39156-5BMINumeric

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:

EventTrigger
consultation.createdNew consultation recorded
consultation.updatedConsultation 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