eClinicalWorks Integration
Vantrexia provides a certified FHIR R4 integration with eClinicalWorks (eCW) EMR for bidirectional patient data exchange, automated observation syncing, and remote patient monitoring workflows. This guide covers authentication, configuration, API endpoints, and troubleshooting.
Overview
The eClinicalWorks integration enables Vantrexia to read patient demographics from eCW and write RPM observation data back to patient charts in real time. This eliminates manual data entry for clinical staff and ensures that all remote monitoring readings are part of the patient's longitudinal health record.
Key capabilities:
- Patient Import — Search and import patient demographics from eCW into Vantrexia's patient registry
- Observation Push — Automatically sync RPM readings (blood pressure, SpO2, weight, glucose) to eCW as FHIR Observation resources
- Authentication — Dual authentication support: JWT Backend Services for automated sync and OAuth2 Standalone for interactive access
- Audit Trail — Every data exchange is logged with timestamps, resource IDs, and delivery confirmation for HIPAA compliance
Authentication Methods
Vantrexia supports two authentication methods for connecting to eClinicalWorks' FHIR API. The appropriate method depends on whether the access is machine-initiated (automated sync) or user-initiated (interactive workflows).
JWT Backend Services (Primary)
The JWT Backend Services flow uses the OAuth 2.0 client_credentials grant type with a signed JWT client assertion. This is the primary authentication method for all automated, machine-to-machine data exchange between Vantrexia and eCW.
| Parameter | Value |
|---|---|
| Grant Type | client_credentials |
| Client Assertion Type | urn:ietf:params:oauth:client-assertion-type:jwt-bearer |
| Signing Algorithm | RS384 (RSA with SHA-384) |
| Key Registration | JWKS endpoint (/.well-known/jwks.json) |
| Token Lifetime | 5 minutes (300 seconds) |
| Access Token Expiry | 60 minutes (3600 seconds) |
The JWT assertion includes the following claims:
{
"iss": "your-ecw-client-id",
"sub": "your-ecw-client-id",
"aud": "https://oauthserver.eclinicalworks.com/oauth/oauth2/token",
"exp": 1738900500,
"iat": 1738900200,
"jti": "unique-request-id-uuid4"
}
OAuth2 Standalone (Interactive)
The OAuth2 Standalone flow uses the authorization_code grant with PKCE (Proof Key for Code Exchange) for user-interactive scenarios where a provider needs to authorize Vantrexia to access their eCW account. This flow is used during initial setup and for operations that require user consent.
| Parameter | Value |
|---|---|
| Grant Type | authorization_code |
| PKCE Challenge Method | S256 |
| Redirect URI | https://api.vantrexia.com/api/v1/ecw/auth/callback/ |
| Response Type | code |
| Access Token Expiry | 60 minutes (3600 seconds) |
| Refresh Token | Supported (7-day lifetime) |
Configuration
The following endpoints and configuration parameters are required to establish a connection with eClinicalWorks:
| Configuration | Staging | Production |
|---|---|---|
| Token Endpoint | https://staging-oauthserver.eclinicalworks.com/oauth/oauth2/token |
https://oauthserver.eclinicalworks.com/oauth/oauth2/token |
| FHIR Base URL | https://sandbox-fhir4.eclinicalworks.com/fhir/r4/{practice_code} |
https://fhir4.eclinicalworks.com/fhir/r4/{practice_code} |
| Authorization URL | https://staging-oauthserver.eclinicalworks.com/oauth/oauth2/authorize |
https://oauthserver.eclinicalworks.com/oauth/oauth2/authorize |
| JWKS Endpoint | https://api.vantrexia.com/.well-known/jwks.json |
|
Required Scopes
The following FHIR scopes must be granted to Vantrexia's client application in the eCW developer portal:
system/Patient.read # Read patient demographics
system/Observation.write # Write RPM observation data
system/*.write # Write clinical resources (Observations, DiagnosticReports)
user/Patient.read # Read patients in user context (OAuth2 standalone)
user/Observation.write # Write observations in user context (OAuth2 standalone)
Setup Steps
Follow these steps to configure the eClinicalWorks integration from scratch. Estimated setup time: 30–45 minutes.
Generate RSA Key Pair
Generate an RSA key pair for JWT signing. The private key stays on the Vantrexia server; the public key is registered with eCW via the JWKS endpoint.
# Generate 2048-bit RSA private key
openssl genrsa -out ecw_private_key.pem 2048
# Extract public key
openssl rsa -in ecw_private_key.pem -pubout -out ecw_public_key.pem
# Generate a key ID (kid) for JWKS
export KEY_ID=$(openssl rand -hex 16)
echo "Key ID: $KEY_ID"
# Verify the key pair
openssl rsa -in ecw_private_key.pem -check -noout
Register in eCW Developer Portal
Log in to the eClinicalWorks Developer Portal and create a new application registration:
- Navigate to Applications → Register New Application
- Set the application type to Backend Service
- Enter the redirect URI:
https://api.vantrexia.com/api/v1/ecw/auth/callback/ - Select the required FHIR scopes listed above
- Submit the registration and note the assigned Client ID
Whitelist JWKS Endpoint
In the eCW developer portal, register your JWKS endpoint URL so eCW can verify your JWT signatures:
https://api.vantrexia.com/.well-known/jwks.json
Vantrexia automatically serves the JWKS document containing your public key. Verify it is accessible:
curl -s https://api.vantrexia.com/.well-known/jwks.json | python -m json.tool
The response should contain a keys array with your RSA public key in JWK format, including the kid matching your generated Key ID.
Configure Environment Variables
Add the following variables to your .env file (local development) or AWS Secrets Manager (production):
# eClinicalWorks Integration
ECW_CLIENT_ID=your-assigned-client-id
ECW_CLIENT_SECRET=your-client-secret
ECW_ENVIRONMENT=staging
ECW_PRACTICE_CODE=your-practice-code
ECW_APP_TYPE=backend_service
# For production, change ECW_ENVIRONMENT:
# ECW_ENVIRONMENT=production
Test Connection
Verify the integration is working by testing JWT authentication and FHIR connectivity via the Vantrexia API:
# Test JWT token acquisition
curl -X POST https://api.vantrexia.com/api/v1/ecw/test/jwt/ \
-H "Authorization: Bearer YOUR_VANTREXIA_TOKEN" \
-H "Content-Type: application/json"
# Expected response:
# {
# "status": "success",
# "token_type": "bearer",
# "expires_in": 3600,
# "scope": "system/Patient.read system/Observation.write"
# }
# Test FHIR connection
curl -X POST https://api.vantrexia.com/api/v1/ecw/test/connection/ \
-H "Authorization: Bearer YOUR_VANTREXIA_TOKEN" \
-H "Content-Type: application/json"
# Expected response:
# {
# "status": "success",
# "fhir_server": "eClinicalWorks FHIR R4",
# "capabilities": ["Patient", "Observation", "DiagnosticReport"]
# }
API Endpoints
Vantrexia exposes the following endpoints for managing the eClinicalWorks integration. All endpoints require authentication with a valid Vantrexia access token.
Initiates the OAuth2 standalone authorization flow. Returns an authorization URL that the user should be redirected to for granting eCW access. A PKCE code challenge is generated and stored server-side.
Response
{
"authorization_url": "https://staging-oauthserver.ecwcloud.com/oauth/oauth2/authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&code_challenge=...&code_challenge_method=S256&state=...",
"state": "random-state-token"
}
Handles the OAuth2 callback after the user authorizes Vantrexia in eCW. Exchanges the authorization code for access and refresh tokens using the PKCE code verifier. Tokens are encrypted and stored in the database.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
code | string | Authorization code from eCW |
state | string | State parameter for CSRF validation |
Returns the current eClinicalWorks authentication status for the requesting user's organization. Indicates whether JWT and/or OAuth2 credentials are configured and valid.
Response
{
"jwt_configured": true,
"jwt_last_success": "2026-02-09T10:30:00Z",
"oauth2_configured": true,
"oauth2_token_expires": "2026-02-09T11:30:00Z",
"fhir_base_url": "https://sandbox-api.eclinicalworks.com/fhir/r4",
"scopes": ["system/Patient.read", "system/Observation.write"]
}
Tests JWT authentication by generating a client assertion, requesting an access token from eCW's OAuth server, and validating the response. Returns the token metadata on success or a detailed error message on failure.
Response (Success)
{
"status": "success",
"token_type": "bearer",
"expires_in": 3600,
"scope": "system/Patient.read system/Observation.write system/*.write"
}
Performs a full end-to-end connection test: acquires a JWT token, queries the eCW FHIR metadata endpoint (/metadata), and verifies that the required resource types are available.
Response (Success)
{
"status": "success",
"fhir_server": "eClinicalWorks FHIR R4",
"fhir_version": "4.0.1",
"capabilities": ["Patient", "Observation", "DiagnosticReport", "Encounter"],
"response_time_ms": 342
}
Searches for patients in eClinicalWorks by name, date of birth, or MRN. Results are returned as FHIR Patient resources and formatted for display in the Vantrexia import UI.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | Patient name (partial match supported) |
birthdate | string | No | Date of birth (YYYY-MM-DD format) |
identifier | string | No | MRN or other patient identifier |
_count | integer | No | Max results to return (default: 20) |
Response
{
"count": 2,
"patients": [
{
"ecw_id": "Patient/12345",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-03-15",
"gender": "female",
"mrn": "MRN-001234",
"phone": "555-0101",
"already_imported": false
},
{
"ecw_id": "Patient/67890",
"first_name": "John",
"last_name": "Smith",
"date_of_birth": "1972-11-28",
"gender": "male",
"mrn": "MRN-005678",
"phone": "555-0202",
"already_imported": true
}
]
}
Imports one or more selected patients from eClinicalWorks into Vantrexia's patient registry. Creates local patient records with linked eCW identifiers for future observation syncing.
Request Body
{
"patient_ids": ["Patient/12345", "Patient/67890"],
"assign_to_provider": "dr-smith-uuid",
"program": "RPM"
}
Response
{
"imported": 2,
"skipped": 0,
"patients": [
{
"vantrexia_id": "a1b2c3d4-uuid",
"ecw_id": "Patient/12345",
"name": "Jane Doe",
"status": "imported"
},
{
"vantrexia_id": "e5f6g7h8-uuid",
"ecw_id": "Patient/67890",
"name": "John Smith",
"status": "imported"
}
]
}
Data Flow
When an RPM observation is recorded in Vantrexia (either from MioConnect device data or manual entry), the following pipeline pushes it to eClinicalWorks:
Observation Created
A new Observation record is stored in Vantrexia's database with vital sign data (e.g., systolic: 138, diastolic: 88, pulse: 72).
FHIR R4 Transform
The observation is transformed into a FHIR R4 Observation resource with LOINC codes, proper units (UCUM), and a reference to the patient's eCW FHIR ID.
{
"resourceType": "Observation",
"status": "final",
"category": [{
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}]
}],
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "85354-9",
"display": "Blood pressure panel"
}]
},
"subject": {
"reference": "Patient/12345"
},
"effectiveDateTime": "2026-02-09T10:30:00Z",
"component": [
{
"code": {"coding": [{"system": "http://loinc.org", "code": "8480-6", "display": "Systolic BP"}]},
"valueQuantity": {"value": 138, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]"}
},
{
"code": {"coding": [{"system": "http://loinc.org", "code": "8462-4", "display": "Diastolic BP"}]},
"valueQuantity": {"value": 88, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]"}
}
]
}
JWT Token Acquired
A JWT client assertion is generated with a 5-minute expiry, signed with the RS384 private key, and exchanged for an access token at eCW's token endpoint. Tokens are cached until 5 minutes before expiry.
POST to eCW FHIR Endpoint
The FHIR Observation resource is POSTed to {ECW_FHIR_BASE_URL}/Observation with the access token in the Authorization header. Retries are attempted up to 3 times with exponential backoff on transient failures (5xx, timeout).
Delivery Confirmation
On successful creation (HTTP 201), the response includes the eCW-assigned resource ID. This ID is stored in Vantrexia's database alongside the observation for audit trailing and deduplication. Failed deliveries are queued for retry via Celery.
Troubleshooting
Common issues encountered during eClinicalWorks integration setup and operation:
| Issue | Symptoms | Resolution |
|---|---|---|
| JWT Token Expired | HTTP 401 response with invalid_grant error when requesting access token |
Ensure the JWT assertion exp claim is set to no more than 5 minutes from iat. Check that the server clock is synchronized via NTP. Vantrexia auto-caches tokens; clear the cache with python manage.py clear_ecw_token_cache. |
| JWKS Not Accessible | eCW returns invalid_client error; unable to verify JWT signature |
Verify https://api.vantrexia.com/.well-known/jwks.json is publicly accessible (no auth required). Check that the kid in the JWT header matches the key ID in the JWKS document. Ensure Nginx is not blocking the endpoint with rate limiting. |
| FHIR Validation Errors | HTTP 422 response with OperationOutcome containing validation errors |
Common causes: missing required LOINC codes, incorrect UCUM unit codes, invalid patient reference. Check the OperationOutcome issue array for specific field-level errors. Run python manage.py validate_fhir_resources to validate locally before syncing. |
| Scope Mismatch | HTTP 403 when accessing FHIR resources despite valid token | Verify that the requested scopes in the JWT assertion match the scopes granted in the eCW developer portal. The system/Observation.write scope is required for pushing observations. Check with GET /api/v1/ecw/auth/status/ for currently active scopes. |
| Patient Not Found | FHIR POST returns HTTP 404 for the patient reference in the Observation | Ensure the patient exists in eCW and the Patient/ID reference is correct. Re-import the patient from eCW to refresh the linked ID. Patient IDs may change if the patient record is merged in eCW. |
| Rate Limiting | HTTP 429 Too Many Requests from eCW FHIR API | eCW applies rate limits per client. Vantrexia's Celery workers use a token bucket rate limiter (default: 10 requests/second). If you hit rate limits, reduce the ECW_RATE_LIMIT setting in your environment variables. Batch observation pushes during off-peak hours. |
| SSL/TLS Handshake Failure | Connection errors when contacting eCW endpoints | Ensure the server has an up-to-date CA certificate bundle. eCW requires TLS 1.2+. Check with openssl s_client -connect staging-oauthserver.ecwcloud.com:443 -tls1_2. Update the certifi Python package if needed. |
ECW_LOG_LEVEL=DEBUG in your environment. This logs all JWT assertions (with secrets redacted), HTTP requests/responses, and FHIR resource payloads. Logs are written to /app/logs/ecw_integration.log and automatically rotated at 10 MB.
GET /api/v1/ecw/auth/status/ and the relevant log entries from ecw_integration.log.
Was this page helpful?