Skip to main content

Platform REST API

Programmatic access to all Patient Journey Intelligence platform features via RESTful HTTP endpoints with OAuth 2.0 authentication and comprehensive OpenAPI documentation.

Build Custom Integrations with Production-Ready APIs

Access data ingestion, clinical NLP, patient cohorts, registries, and AI agents through RESTful endpoints designed for scale, security, and developer experience.


Overview

The Platform REST API provides programmatic access to:

  • Data Ingestion: Upload HL7 FHIR, C-CDA, CSV, and custom data formats
  • Clinical NLP: Extract entities, relationships, and assertions from clinical text
  • Terminology Services: Search SNOMED CT, RxNorm, LOINC, ICD-10, and map codes
  • Patient Cohorts: Build, query, and export patient populations
  • Registries: Create and manage cancer, research, and custom registries
  • AI Agents: Invoke medical LLMs and orchestrate agentic workflows
  • Quality Measures: Calculate HEDIS, CMS, and custom quality metrics

Base URL: https://api.patient-journey.ai/v1

API Documentation: https://api.patient-journey.ai/docs (OpenAPI/Swagger)


Authentication

OAuth 2.0 Client Credentials Flow

Step 1: Obtain Access Token

POST https://auth.patient-journey.ai/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=api:read api:write

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api:read api:write"
}

Step 2: Use Access Token in API Requests

GET https://api.patient-journey.ai/v1/patients/12345
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

API Key Authentication (Alternative)

For simpler use cases, use API keys in the X-API-Key header:

GET https://api.patient-journey.ai/v1/patients/12345
X-API-Key: pji_live_abc123def456ghi789jkl012mno345

Note: OAuth 2.0 is recommended for production applications. API keys are suitable for development/testing.


API Endpoints

Data Ingestion

Upload FHIR Bundle

POST /v1/ingestion/fhir
Content-Type: application/fhir+json
Authorization: Bearer {token}

{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Patient",
"id": "patient-123",
"name": [{"family": "Smith", "given": ["John"]}],
"birthDate": "1975-05-15"
},
"request": {
"method": "PUT",
"url": "Patient/patient-123"
}
}
]
}

Response:

{
"job_id": "job_789xyz",
"status": "queued",
"resources_submitted": 1,
"estimated_completion": "2024-01-15T10:35:00Z"
}

Check Ingestion Job Status

GET /v1/ingestion/jobs/{job_id}
Authorization: Bearer {token}

Response:

{
"job_id": "job_789xyz",
"status": "completed",
"resources_processed": 1,
"resources_failed": 0,
"started_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:32:15Z",
"errors": []
}

Clinical NLP

Extract Clinical Entities

POST /v1/nlp/extract-entities
Content-Type: application/json
Authorization: Bearer {token}

{
"text": "Patient diagnosed with Type 2 Diabetes Mellitus. Started on Metformin 500mg BID and Lisinopril 10mg daily for hypertension.",
"entity_types": ["PROBLEM", "DRUG"],
"model": "clinical-ner-v2",
"return_offsets": true,
"confidence_threshold": 0.75
}

Response:

{
"entities": [
{
"text": "Type 2 Diabetes Mellitus",
"type": "PROBLEM",
"begin": 23,
"end": 47,
"confidence": 0.96,
"normalized_term": "Type 2 diabetes mellitus",
"snomed_code": "44054006"
},
{
"text": "Metformin",
"type": "DRUG",
"begin": 60,
"end": 69,
"confidence": 0.98,
"normalized_term": "Metformin",
"rxnorm_code": "6809"
},
{
"text": "Lisinopril",
"type": "DRUG",
"begin": 84,
"end": 94,
"confidence": 0.97,
"normalized_term": "Lisinopril",
"rxnorm_code": "29046"
},
{
"text": "hypertension",
"type": "PROBLEM",
"begin": 110,
"end": 122,
"confidence": 0.95,
"normalized_term": "Hypertensive disorder",
"snomed_code": "38341003"
}
],
"processing_time_ms": 127
}

De-Identify Text

POST /v1/nlp/de-identify
Content-Type: application/json
Authorization: Bearer {token}

{
"text": "Patient John Smith, DOB 05/15/1975, MRN 12345, was seen on 2024-01-15 at Memorial Hospital.",
"strategy": "mask",
"phi_types": ["PATIENT_NAME", "DATE", "ID", "HOSPITAL"]
}

Response:

{
"de_identified_text": "Patient [NAME], DOB [DATE], MRN [ID], was seen on [DATE] at [HOSPITAL].",
"phi_detected": [
{"type": "PATIENT_NAME", "text": "John Smith", "begin": 8, "end": 18, "replacement": "[NAME]"},
{"type": "DATE", "text": "05/15/1975", "begin": 24, "end": 34, "replacement": "[DATE]"},
{"type": "ID", "text": "12345", "begin": 40, "end": 45, "replacement": "[ID]"},
{"type": "DATE", "text": "2024-01-15", "begin": 60, "end": 70, "replacement": "[DATE]"},
{"type": "HOSPITAL", "text": "Memorial Hospital", "begin": 74, "end": 91, "replacement": "[HOSPITAL]"}
]
}

Terminology Services

Search Medical Terminology

GET /v1/terminology/search?query=diabetes&terminology=SNOMED_CT&limit=5
Authorization: Bearer {token}

Response:

{
"results": [
{
"code": "44054006",
"display": "Type 2 diabetes mellitus",
"system": "http://snomed.info/sct",
"score": 0.98
},
{
"code": "46635009",
"display": "Type 1 diabetes mellitus",
"system": "http://snomed.info/sct",
"score": 0.95
},
{
"code": "73211009",
"display": "Diabetes mellitus",
"system": "http://snomed.info/sct",
"score": 0.92
}
],
"total": 247
}

Map Codes Between Terminologies

POST /v1/terminology/map
Content-Type: application/json
Authorization: Bearer {token}

{
"source_code": "44054006",
"source_system": "SNOMED_CT",
"target_system": "ICD10CM"
}

Response:

{
"mappings": [
{
"target_code": "E11.9",
"target_display": "Type 2 diabetes mellitus without complications",
"target_system": "http://hl7.org/fhir/sid/icd-10-cm",
"equivalence": "equivalent",
"confidence": 0.95
}
]
}

Patient Cohorts

Create Cohort

POST /v1/cohorts
Content-Type: application/json
Authorization: Bearer {token}

{
"name": "Uncontrolled T2DM on Metformin",
"description": "Patients with T2DM, HbA1c >8%, currently on metformin",
"inclusion_criteria": [
{
"type": "condition",
"concept_id": "44054006",
"concept_name": "Type 2 diabetes mellitus",
"date_range": {"start": "2020-01-01", "end": "2024-12-31"}
},
{
"type": "drug_exposure",
"concept_id": "6809",
"concept_name": "Metformin",
"status": "active"
},
{
"type": "measurement",
"concept_id": "4184637",
"concept_name": "Hemoglobin A1c",
"operator": ">",
"value": 8.0,
"unit": "%",
"date_range": {"start": "2024-10-01", "end": "2024-12-31"}
}
],
"exclusion_criteria": [
{
"type": "condition",
"concept_id": "46635009",
"concept_name": "Type 1 diabetes mellitus"
}
]
}

Response:

{
"cohort_id": "cohort_456abc",
"name": "Uncontrolled T2DM on Metformin",
"status": "building",
"estimated_completion": "2024-01-15T10:40:00Z",
"created_at": "2024-01-15T10:35:00Z"
}

Get Cohort Status & Patient Count

GET /v1/cohorts/{cohort_id}
Authorization: Bearer {token}

Response:

{
"cohort_id": "cohort_456abc",
"name": "Uncontrolled T2DM on Metformin",
"status": "completed",
"patient_count": 247,
"created_at": "2024-01-15T10:35:00Z",
"completed_at": "2024-01-15T10:38:22Z",
"inclusion_criteria": [...],
"exclusion_criteria": [...]
}

Export Cohort Data

POST /v1/cohorts/{cohort_id}/export
Content-Type: application/json
Authorization: Bearer {token}

{
"format": "csv",
"include_data": ["demographics", "conditions", "medications", "measurements"],
"de_identify": true,
"compression": "gzip"
}

Response:

{
"export_id": "export_789xyz",
"status": "processing",
"estimated_completion": "2024-01-15T10:45:00Z"
}

Download Export:

GET /v1/cohorts/{cohort_id}/exports/{export_id}/download
Authorization: Bearer {token}

Returns a downloadable file (CSV, Parquet, or JSON) with cohort data.


Quality Measures

Calculate Quality Measure

POST /v1/quality-measures/calculate
Content-Type: application/json
Authorization: Bearer {token}

{
"measure_id": "CDC-HbA1c-Control",
"cohort_id": "cohort_456abc",
"measurement_period": {
"start": "2023-01-01",
"end": "2023-12-31"
},
"stratify_by": ["age_group", "sex"]
}

Response:

{
"measure_id": "CDC-HbA1c-Control",
"measure_name": "Comprehensive Diabetes Care: HbA1c Control (<8%)",
"numerator": 189,
"denominator": 247,
"performance_rate": 76.5,
"benchmark": 70.0,
"meets_benchmark": true,
"stratifications": [
{"group": "Age 18-44", "numerator": 42, "denominator": 58, "rate": 72.4},
{"group": "Age 45-64", "numerator": 91, "denominator": 112, "rate": 81.3},
{"group": "Age 65+", "numerator": 56, "denominator": 77, "rate": 72.7},
{"group": "Male", "numerator": 98, "denominator": 130, "rate": 75.4},
{"group": "Female", "numerator": 91, "denominator": 117, "rate": 77.8}
],
"calculated_at": "2024-01-15T10:40:00Z"
}

Medical LLM & VLM

Generate Text with Medical LLM

POST /v1/models/clinical-gpt-7b/generate
Content-Type: application/json
Authorization: Bearer {token}

{
"prompt": "A 65-year-old male with chest pain radiating to left arm. ECG shows ST elevation in leads II, III, aVF. What is the diagnosis?",
"max_tokens": 200,
"temperature": 0.3,
"top_p": 0.9
}

Response:

{
"model": "clinical-gpt-7b",
"generated_text": "Diagnosis: Acute Inferior Wall ST-Elevation Myocardial Infarction (STEMI)\n\nThe ECG findings of ST-segment elevation in the inferior leads (II, III, aVF) are consistent with acute STEMI involving the right coronary artery territory. Immediate management includes:\n1. Activate cardiac catheterization lab for emergent PCI\n2. Dual antiplatelet therapy (aspirin + P2Y12 inhibitor)\n3. Anticoagulation (heparin or bivalirudin)\n4. Consider right-sided ECG leads to assess for RV involvement\n\nDoor-to-balloon time should be <90 minutes.",
"finish_reason": "stop",
"confidence": 0.92,
"usage": {
"prompt_tokens": 34,
"completion_tokens": 128,
"total_tokens": 162
}
}

Analyze Medical Image with VLM

POST /v1/models/radiology-vlm-8b/analyze-image
Content-Type: application/json
Authorization: Bearer {token}

{
"image": "base64_encoded_image_data...",
"image_type": "chest_xray",
"prompt": "Identify all findings and provide a structured radiology report.",
"max_tokens": 400,
"temperature": 0.2
}

Response:

{
"model": "radiology-vlm-8b",
"findings": [
{
"finding": "Right lower lobe opacity",
"location": {"x": 420, "y": 380, "width": 85, "height": 95},
"confidence": 0.89,
"severity": "moderate",
"snomed_code": "233604007"
}
],
"report": "FINDINGS:\n1. Right lower lobe opacity measuring approximately 8.5 x 9.5 cm, concerning for pneumonia\n2. Mild blunting of right costophrenic angle suggesting small pleural effusion\n3. Cardiac silhouette within normal limits\n\nIMPRESSION:\nRight lower lobe pneumonia with small right pleural effusion.",
"usage": {
"prompt_tokens": 1250,
"completion_tokens": 95,
"total_tokens": 1345
}
}

Pagination

For endpoints returning large result sets, use pagination parameters:

GET /v1/patients?limit=50&offset=100
Authorization: Bearer {token}

Response includes pagination metadata:

{
"data": [...],
"pagination": {
"total": 2500,
"limit": 50,
"offset": 100,
"has_more": true,
"next": "/v1/patients?limit=50&offset=150"
}
}

Rate Limiting

Rate Limits by Tier:

  • Standard: 1,000 requests/hour, 10,000/day
  • Professional: 10,000 requests/hour, 100,000/day
  • Enterprise: Custom limits per SLA

Rate Limit Headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1705324800

429 Rate Limit Exceeded Response:

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 300 seconds.",
"retry_after": 300
}
}

Error Handling

All errors follow a consistent format:

{
"error": {
"code": "INVALID_REQUEST",
"message": "Missing required parameter 'patient_id'",
"details": {
"parameter": "patient_id",
"expected_type": "string"
},
"request_id": "req_abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
}

Common HTTP Status Codes:

  • 200 OK - Successful request
  • 201 Created - Resource created successfully
  • 400 Bad Request - Invalid parameters
  • 401 Unauthorized - Missing or invalid authentication
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource doesn't exist
  • 429 Too Many Requests - Rate limit exceeded
  • 500 Internal Server Error - Server-side error
  • 503 Service Unavailable - Temporary service disruption

Webhooks

Subscribe to events for async operations like cohort building, data ingestion, and exports.

Configure Webhook Endpoint:

POST /v1/webhooks
Content-Type: application/json
Authorization: Bearer {token}

{
"url": "https://your-app.com/webhooks/patient-journey",
"events": ["cohort.completed", "ingestion.completed", "export.ready"],
"secret": "your_webhook_secret_for_signature_verification"
}

Webhook Payload Example:

{
"event": "cohort.completed",
"data": {
"cohort_id": "cohort_456abc",
"patient_count": 247,
"completed_at": "2024-01-15T10:38:22Z"
},
"timestamp": "2024-01-15T10:38:22Z",
"signature": "sha256=abc123..."
}

Verify Webhook Signature:

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
expected_signature = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected_signature}", signature)

SDKs & Client Libraries

Python SDK

pip install patient-journey-sdk
from patient_journey import Client

# Initialize client
client = Client(api_key="pji_live_abc123...")

# Extract clinical entities
result = client.nlp.extract_entities(
text="Patient diagnosed with Type 2 Diabetes",
entity_types=["PROBLEM", "DRUG"]
)

print(result.entities)

JavaScript/TypeScript SDK

npm install @patient-journey/sdk
import { PatientJourneyClient } from '@patient-journey/sdk';

const client = new PatientJourneyClient({
apiKey: 'pji_live_abc123...'
});

// Create cohort
const cohort = await client.cohorts.create({
name: 'T2DM Patients',
inclusion_criteria: [
{ type: 'condition', concept_id: '44054006' }
]
});

console.log(cohort.patient_count);

OpenAPI Specification

Full OpenAPI 3.0 specification available at:

URL: https://api.patient-journey.ai/openapi.json

Interactive Docs: https://api.patient-journey.ai/docs

Generate client libraries in any language:

# Generate Python client
openapi-generator generate -i https://api.patient-journey.ai/openapi.json -g python -o ./client

# Generate Java client
openapi-generator generate -i https://api.patient-journey.ai/openapi.json -g java -o ./client

# Generate Go client
openapi-generator generate -i https://api.patient-journey.ai/openapi.json -g go -o ./client

Best Practices

💡 API Integration Tips

  • Cache access tokens: OAuth tokens are valid for 1 hour – reuse them to avoid unnecessary auth requests
  • Implement retry logic: Use exponential backoff for 5xx errors and rate limit (429) responses
  • Use webhooks for async ops: Don't poll for job status – subscribe to webhooks for completion events
  • Batch requests when possible: Send multiple entities in a single NLP extraction call instead of per-entity
  • Validate inputs locally: Check required parameters before making API calls to reduce 400 errors
  • Monitor rate limits: Track X-RateLimit-Remaining header to avoid hitting limits
  • Use pagination: Don't fetch all results at once – use limit and offset for large datasets
  • Secure API keys: Never commit API keys to version control – use environment variables

Support & Resources

📖

API Documentation

Interactive Swagger Docs

💬

Developer Community

Forums & Discussions

🐛

Report Issues

GitHub Issues


Next Steps