Skip to main content

Workflow Guide

Full referral lifecycle

1. GP creates a draft referral

The referring clinician (GP, A&E consultant, etc.) creates a draft. A draft can be edited before sending — no consent check runs at this stage.

POST /api/referrals
Authorization: Bearer <clinician-jwt>

{
"patientId": "Patient/ePatient-8675309",
"requesterId": "Practitioner/dr-smith",
"performerId": "Organization/royal-london-cardiology",
"receivingFacilityClientId": "royal-london-cardiology-smart",
"referralCode": "103696004",
"referralDisplay": "Patient referral to cardiologist",
"priority": "ROUTINE",
"reasonCodes": ["I20.9"],
"clinicalNote": "Chest pain and elevated troponin. ECG shows ST changes.",
"sharedResourceTypes": ["Observation", "Condition", "DiagnosticReport"],
"occurrenceDate": "2025-07-15",
"sendingOrganisationId": "Organization/anytown-gp-practice",
"receivingOrganisationId": "Organization/royal-london-cardiology"
}

Response: 201 Created

{ "id": 1, "status": "DRAFT", "consentVerified": false, ... }

The FHIR ServiceRequest is synced to HAPI asynchronously.


Before sending, the patient must have consented to share the sharedResourceTypes with the receivingFacilityClientId. If not, the send call returns 422.

The clinician can direct the patient to the consent portal:

http://localhost:8082/consent/portal

Or the patient can consent via the standard SMART OAuth2 flow when the receiving facility's application launches.


3. GP sends the referral

POST /api/referrals/1/send
Authorization: Bearer <clinician-jwt>

Internally this runs:

  1. Consent gate: calls POST /api/consent/evaluate for each resource type in sharedResourceTypes
  2. If gate passes → status = ACTIVE, authoredOn = now(), consentVerified = true
  3. Creates initial ReferralTask with status = REQUESTED at the receiving facility
  4. Syncs ServiceRequest and Task to HAPI FHIR (async)
  5. Writes audit event including consent check result

Success response: 200

{ "id": 1, "status": "ACTIVE", "consentVerified": true, ... }

Consent gate failure: 422

{
"code": "CONSENT_GATE_FAILED",
"message": "Cannot send referral — patient has not consented to share Condition with royal-london-cardiology-smart. Ask the patient to grant consent via the patient portal."
}

4. Receiving facility works the referral

The receiving facility sees the referral in their inbox:

GET /api/referrals/inbox?performerId=Organization/royal-london-cardiology
Authorization: Bearer <receiving-clinician-jwt>

They progress the task through the workflow:

Acknowledge receipt:

PATCH /api/referrals/1/tasks/1
{ "status": "RECEIVED" }

Accept into their system:

PATCH /api/referrals/1/tasks/1
{ "status": "ACCEPTED", "note": "Appointment booked for 15 July" }

Mark in progress (appointment occurring):

PATCH /api/referrals/1/tasks/1
{ "status": "INPROGRESS" }

Complete:

PATCH /api/referrals/1/tasks/1
{ "status": "COMPLETED", "note": "Cardiology assessment completed. Findings documented." }

When the task reaches COMPLETED, the parent ReferralRecord automatically transitions to COMPLETED and the ServiceRequest is updated in HAPI.

Reject (no capacity, clinical decline):

PATCH /api/referrals/1/tasks/1
{
"status": "REJECTED",
"rejectionReason": "No capacity until Q4. Please refer to City Hospital."
}

5. Referring clinician monitors status

GET /api/referrals/1
Authorization: Bearer <clinician-jwt>
GET /api/referrals/1/tasks
Authorization: Bearer <clinician-jwt>

The referring clinician can see the current task status and any notes added by the receiving facility.


Putting a referral on hold

Either party can put an active referral on hold:

POST /api/referrals/1/hold?reason=Patient+admitted+to+ICU
Authorization: Bearer <clinician-jwt>

Resume when appropriate:

POST /api/referrals/1/resume
Authorization: Bearer <clinician-jwt>

Revoking a referral

POST /api/referrals/1/revoke?reason=Patient+declined+referral
Authorization: Bearer <clinician-jwt>

All open tasks are automatically cancelled. The ServiceRequest status is set to revoked in HAPI. The referral record and all tasks are preserved for audit purposes.


Priority levels

PriorityUse caseExpected response
ROUTINEStandard outpatient referralWithin 18 weeks (NHS) / 30 days
URGENTSuspected cancer, urgent assessmentWithin 2 weeks
ASAPNeeds attention soon but not immediately life-threateningWithin 24–72 hours
STATImmediate life-threatening — usually A&E escalationImmediate

Priority is mapped to ServiceRequest.priority in FHIR.


The consent gate checks that the patient has consented to share each resource type in sharedResourceTypes with the receiving facility's SMART client_id. This is enforced at the send() transition.

If a patient later revokes consent after a referral has been sent:

  • The referral status remains ACTIVE — revoking consent does not automatically revoke the referral
  • The receiving facility may lose FHIR API access to the patient's data if they access it via the standard SMART flow
  • The referring clinician should decide whether to revoke the referral as well

This separation is intentional: consent governs data access; the referral governs the clinical workflow. These are distinct concerns.


Next: API Reference →