Skip to main content

Quick Start

Prerequisites

  • The AJ FHIR Platform running (HAPI FHIR on :8080, Auth Server on :9000)
  • The Consent Manager running (:8082)
  • A SYSTEM-scoped token from the Auth Server for the consent gate

1. Get a SYSTEM-scoped token

The Referral Module calls the Consent Manager's /api/consent/evaluate endpoint using a system token. Generate one:

curl -X POST http://localhost:9000/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=referral-service&client_secret=secret&scope=SYSTEM"

Use the returned access_token as CONSENT_SERVICE_TOKEN.

2. Configure environment

# Required
export FHIR_BASE_URL=http://localhost:8080/fhir
export FHIR_SERVICE_TOKEN=<service-account-token>
export CONSENT_MANAGER_URL=http://localhost:8082
export CONSENT_SERVICE_TOKEN=<system-scoped-token>

# JWT validation
export JWT_EXPECTED_ISSUER=http://localhost:9000
export JWT_EXPECTED_AUDIENCE=http://localhost:8080/fhir

# Database
export DB_URL=jdbc:postgresql://localhost:5432/ajfhir_referral
export DB_USER=ajfhir
export DB_PASS=your-password
Consent service token required

If CONSENT_SERVICE_TOKEN is blank in a non-test profile, the application throws IllegalStateException at startup. Without this token the consent gate cannot function and no referral can be sent.

3. Start with Docker Compose

referral:
image: ajfhir/referral:1.0.0
ports:
- "8083:8083"
environment:
DB_URL: jdbc:postgresql://postgres:5432/ajfhir_referral
DB_USER: ajfhir
DB_PASS: ${DB_PASS}
FHIR_BASE_URL: http://hapi-fhir:8080/fhir
FHIR_SERVICE_TOKEN: ${FHIR_SERVICE_TOKEN}
CONSENT_MANAGER_URL: http://consent-manager:8082
CONSENT_SERVICE_TOKEN: ${CONSENT_SERVICE_TOKEN}
JWT_EXPECTED_ISSUER: ${JWT_EXPECTED_ISSUER}
JWT_EXPECTED_AUDIENCE: ${JWT_EXPECTED_AUDIENCE}
depends_on:
- postgres
- hapi-fhir
- consent-manager
docker compose up -d referral

4. Verify

curl http://localhost:8083/actuator/health
# {"status":"UP"}

5. Send your first referral

Step 1: Create a draft referral

curl -X POST http://localhost:8083/api/referrals \
-H "Authorization: Bearer <clinician-token>" \
-H "Content-Type: application/json" \
-d '{
"patientId": "Patient/ePatient-8675309",
"requesterId": "Practitioner/dr-smith",
"performerId": "Organization/royal-london-cardiology",
"receivingFacilityClientId": "akhester-smart-client",
"referralCode": "103696004",
"referralDisplay": "Cardiology referral",
"priority": "ROUTINE",
"reasonCodes": ["I20.9"],
"clinicalNote": "Chest pain and elevated troponin.",
"sharedResourceTypes": ["Observation", "Condition", "DiagnosticReport"],
"sendingOrganisationId": "Organization/anytown-gp",
"receivingOrganisationId": "Organization/royal-london-cardiology"
}'

Note the id from the response.

Step 2: Send it (consent gate runs here)

curl -X POST http://localhost:8083/api/referrals/1/send \
-H "Authorization: Bearer <clinician-token>"

If the patient has active consent for the receiving facility, the response is 200 with status: ACTIVE.

If consent is missing, the response is 422:

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

Step 3: Receiving facility accepts

curl -X PATCH http://localhost:8083/api/referrals/1/tasks/1 \
-H "Authorization: Bearer <receiving-clinician-token>" \
-H "Content-Type: application/json" \
-d '{ "status": "ACCEPTED" }'

Next: Architecture →