
Athena
athenahealth
Athena
Complete OAuth 2.0 and FHIR R4 integration adapter for athenahealth EHR systems. Supports patient-facing, system-to-system (Basic Auth or JWT), and embedded EHR launch workflows with full FHIR resource CRUD operations.
Overview
ConnectHealth's athenahealth integration gives your application secure access to patient data and clinical workflows through athenahealth's OAuth 2.0 and FHIR R4 APIs. ConnectHealth acts as the middleware layer — handling authentication, token lifecycle, and FHIR communication — so your team can focus on building features rather than managing EHR-specific OAuth flows.
You (your organization) must create and own EHR applications. ConnectHealth is middleware — it does NOT create apps, manage athenahealth accounts, or submit applications on your behalf, so you must have an approved athenahealth app with credentials before configuring any workflow in ConnectHealth.
On This Page
Supported Authentication Flows
Click a card to jump to its configuration section.
Standalone OAuth
Standard OAuth 2.0 authorization code flow where users authorize access to their data via the athenahealth patient portal. Best for patient portals, health tracking apps, and third-party apps needing patient consent.
Backend to Backend (B2B)
Client credentials flow for server-to-server authentication without any user interaction. Supports both Basic Auth and JWT assertion methods. Best for automated data sync, reporting, and background processing.
Embed Launch
SMART on FHIR launch flow for applications embedded within athenahealth's interface. The app is launched from within the EHR and receives patient context automatically. Best for clinical decision support and in-context clinical tools.
Key Features
- FHIR resource CRUD operations
- Bulk data export
- Dual backend auth methods (Basic Auth or JWT assertion)
- Scope normalization (auto-adds openid and fhirUser)
- Token refresh
- Audit logging for all operations
Before You Begin
Before you can use athenahealth with ConnectHealth, you must set up an application with athenahealth. This section outlines the prerequisites and gives you a step-by-step guide to get started.
Prerequisites Checklist
- athenahealth developer account — Create an account at athenahealth Developer Portal under your organization's email domain
- Approved sandbox application — Created in the Developer Portal with Client ID and Client Secret
- Redirect URI configured — Registered in your athenahealth app (provided by ConnectHealth)
- For production — A separate production app submission approved by athenahealth
- For JWT B2B — An RSA key pair (RS256 or RS384) with the public key registered in athenahealth
Create Your athenahealth Application
Follow these steps to create your athenahealth application. Your organization owns and manages this app — athenahealth's developer portal is where you'll manage credentials and configuration.
Create an athenahealth Developer Account
If you don't already have one, create a developer account in the athenahealth Developer Portal.
- Sign up using your organization's email domain (e.g., someone@your-company.com)
- Your organization will own this account and all apps created under it
- Keep your login credentials secure
Create a New Application in the Developer Portal
In the Developer Portal, create a new application for sandbox testing:
- Click Create a New App
- Choose your launch type:
- For Standalone (patient-facing): Select 3-Legged OAuth for PHR Apps or 3-Legged OAuth
- For Backend (B2B): Select Backend or System Application
- For Embed Launch (in-EHR): Select SMART on FHIR EHR Launch
- Click Continue to App Details
- Select Preview environment (sandbox)
- Enter an app name (e.g., "ConnectHealth Integration - Sandbox")
- You will add the Redirect URL in the next step
- Click Create Application
Retrieve Your Credentials and Configure Redirect URI
After creating your app, copy your credentials and configure where athenahealth should redirect after authorization:
- In your app's Credentials tab, copy your Client ID and Client Secret
- In your app's App Details tab, set the Post-login Redirect URL (for Standalone) or Launch URL (for Embed Launch) to your ConnectHealth callback URL:
https://your-connecthealth-domain/api/workflow/auth/{integrationId}/callback
You will get the exact {integrationId} from ConnectHealth after creating your connection - For B2B / Backend: If using JWT, copy the JWKS URI from ConnectHealth and paste it into your app's JWKS URI field
- Click Save
Submit for Sandbox Approval (if required)
Some sandbox apps are auto-approved, but some may require manual review by athenahealth:
- Check your app status in the Developer Portal
- If manual review is required, submit your app and wait for athenahealth's approval (typically a few hours to 1-2 days)
- You will receive an email when your sandbox app is approved
- Only after approval can you use the Client ID and Client Secret in ConnectHealth
Configure in ConnectHealth
Now you're ready to configure your athenahealth connection in ConnectHealth:
- In ConnectHealth, navigate to Connections and create a new connection
- Select Athena as the EHR type
- Select your workflow type:
- Standalone for patient-facing applications
- Backend for server-to-server automation
- Embed Launch for in-EHR applications
- Paste your Client ID and Client Secret from athenahealth
- Fill in other required fields (FHIR Base URL, Scopes, etc. — see Configuration Reference section below)
- Copy the generated Redirect URL from ConnectHealth and paste it into your athenahealth app (if you haven't already)
- Save your connection
Test with Sandbox Data
Test your integration using sandbox credentials (see Sandbox Environment Setup below for test data and URLs).
- For Standalone: Initiate OAuth and log in with sandbox test credentials
- For Backend: Request a system token and test FHIR calls
- Verify that data flows correctly between athenahealth and ConnectHealth
Production App (When Ready)
Production apps are NOT auto-approved. You must:
- Create a separate app in the Developer Portal targeting the Production environment
- Submit it for manual review by athenahealth
- Wait for athenahealth's approval — they review apps before they can access real patient data
Do not attempt to go live until you receive approval. Using sandbox credentials or unapproved apps against production will fail.
When you're ready to go to production:
- Create a new application in the Developer Portal with Production environment selected
- Configure it with the same settings as your sandbox app (Redirect URL, scopes, etc.)
- Submit for athenahealth's production approval (this may take several days)
- Once approved, create a new production connection in ConnectHealth using your production credentials
- See the athenahealth API Onboarding Guide for detailed production submission steps
Sandbox Environment Setup
athenahealth's Preview environment is the sandbox for all integration testing. You will need your own approved sandbox application (created in Steps 1–4 above) to obtain a Client ID and Client Secret. athenahealth also provides shared test patient data for quick functional testing — these are listed below.
Shared Test Data (athenahealth Preview Environment)
Use the following shared test patient data for validating your integration. Note: You still need your own approved sandbox application's Client ID and Client Secret — these are test patient records only, not a shared application credential.
athenahealth Preview Endpoints
| Purpose | URL |
|---|---|
| FHIR Base (R4) | https://api.preview.platform.athenahealth.com/fhir/r4 |
| OAuth Authorization | https://api.preview.platform.athenahealth.com/oauth2/v1/authorize |
| OAuth Token | https://api.preview.platform.athenahealth.com/oauth2/v1/token |
Test Patient Data (Practice ID 195900)
- Practice ID:
195900(or80000for PHR-specific testing) - Patient IDs:
60178,60179,60180,60181,60182,60183,60184 - FHIR R4 Logical IDs:
a-195900.E-60178througha-195900.E-60184(format:a-195900.E-<patientId>) - PHR Test Login:
phrtest_preview@mailinator.com/Password1
Sandbox vs Production Comparison
Understand the key differences between sandbox and production environments:
| Aspect | Sandbox (Preview) | Production |
|---|---|---|
| FHIR Base Host | api.preview.platform.athenahealth.com |
api.platform.athenahealth.com |
| App Approval | Quick / may be auto-approved | Manual review required — apps do NOT work until approved |
| Data | Test patients only | Real patient data (HIPAA-covered) |
| Credentials | From your sandbox app | Separate Client ID + Secret from production app |
| Approval Timeline | Minutes to hours | Days to weeks |
| SLA / Support | No guarantees | Production SLA with athenahealth support |
Important: athenahealth's API Onboarding Guide explicitly states that production apps undergo a review process before activation. Plan your production timeline accordingly — do not assume immediate production access.
Which FHIR Base URL Should You Use?
athenahealth exposes two forms of FHIR base URL. Both are valid — choose based on your integration scope:
| Type | Format | When to Use |
|---|---|---|
| Global | https://api.platform.athenahealth.com/fhir/r4 |
When your token spans multiple practices |
| Site-Specific ✅ Preferred | https://api.platform.athenahealth.com/{practiceId}/brand/{brandId}/csg/{csgId}/fhir/r4 |
When your integration targets a single practice (faster, more deterministic) |
Site-specific URLs are scoped to a single practice/brand/context (CSG), avoiding cross-tenant resolution on every FHIR request — making them faster and more deterministic. Sandbox example: https://api.preview.platform.athenahealth.com/195900/brand/1/csg/1/fhir/r4
Configuration Reference
Complete Steps 1–4 above (create and get your athenahealth app approved) before filling in these fields. You will need your Client ID, Client Secret, and an approved athenahealth application to proceed.
ConnectHealth supports multiple workflow types for this integration. Choose the one that matches your use case.
Standalone OAuth
Standard OAuth 2.0 authorization code flow where users authorize access to their data via the athenahealth patient portal. Best for patient portals, health tracking apps, and third-party apps needing patient consent.
| Field | Autofill | Required | Description |
|---|---|---|---|
Client ID |
No | Yes | Your unique application identifier from the athenahealth developer portal. |
Client Secret |
No | Yes | Client secret for confidential clients. Keep this secure and never expose in client-side code. |
Authorization URL |
Yes | Yes | athenahealth's OAuth authorization endpoint URL. |
Token URL |
Yes | Yes | athenahealth's OAuth token endpoint URL. |
Scopes |
No | Yes | Space-separated list of OAuth scopes. The submodule auto-normalizes scopes to include openid and fhirUser. |
Redirect URL |
Yes | Yes | Your application's callback URL where athenahealth redirects after authorization. |
FHIR Base URL |
No | Yes | The base URL of the athenahealth FHIR server you are connecting to. |
Setup Steps
- Register your application in the athenahealth developer portal and note the Client ID and Client Secret.
- Register your redirect URI (callback URL) in the developer portal.
- Determine the scopes your application needs (openid and fhirUser are auto-added if missing).
- Obtain the FHIR base URL and OAuth endpoints from your athenahealth environment.
- Configure the Standalone workflow in ConnectHealth with all the fields above.
- Test the authorization flow by initiating a login — the user should be redirected to athenahealth to authorize.
Backend to Backend (B2B)
Client credentials flow for server-to-server authentication without any user interaction. Supports both Basic Auth (client_secret) and JWT assertion methods. Best for automated data sync, reporting, and background processing.
| Field | Autofill | Required | Description |
|---|---|---|---|
Client ID |
No | Yes | Your unique application identifier from the athenahealth developer portal. |
Client Secret |
No | Yes | Client secret used for Basic Auth authentication. Can alternatively use JWT assertion via Private Key. |
Token URL |
Yes | Yes | athenahealth's OAuth token endpoint URL. |
FHIR Base URL |
No | Yes | The base URL of the athenahealth FHIR server. |
Scopes |
No | Yes | Space-separated list of system-level OAuth scopes (e.g., system/*.read). |
Setup Steps
- Register your application in the athenahealth developer portal as a Backend/System application.
- Note your Client ID and Client Secret for Basic Auth authentication.
- Alternatively, generate an RSA key pair for JWT assertion. Copy the JWKS URL from ConnectHealth and register it in the athenahealth developer portal.
- After app registration is complete in athenahealth, configure the Backend workflow in ConnectHealth with your credentials, endpoints, and required scopes.
- Test by requesting a backend token — no user interaction should be required.
SMART on FHIR - Embed Launch
SMART on FHIR launch flow for applications embedded within athenahealth's EHR interface. The app is launched from within the EHR and receives patient context automatically. Best for clinical decision support and in-context clinical tools.
| Field | Autofill | Required | Description |
|---|---|---|---|
Client ID |
No | Yes | Your unique application identifier from the athenahealth developer portal. |
Client Secret |
No | No | Client secret for confidential clients. |
Setup Steps
- Register your application in the athenahealth developer portal as a SMART on FHIR EHR Launch application.
- Configure the launch URL where athenahealth will send the iss and launch parameters.
- Configure the Embed Launch workflow in ConnectHealth with the Client ID and Client Secret.
- Your app needs to handle the tokenId returned by ConnectHealth and call the token exchange endpoint to retrieve the access token.
- Test by launching your app from within the athenahealth EHR environment.
How to Handle SMART Launch
Once your Embed Launch app is configured, here's the end-to-end flow — from athenahealth initiating the launch, to your app receiving a usable FHIR access token. Each step is tied to the exact ConnectHealth endpoint involved.
athenahealth Initiates the Launch
When a clinician opens your app from within athenahealth, athenahealth calls your registered Launch URL:
GET https://<your-ch-domain>/api/workflow/auth/{integrationId}/launch?iss=...&launch=...
iss— athenahealth's FHIR base URL (e.g.,https://api.platform.athenahealth.com/fhir/r4)launch— an opaque token carrying patient + encounter context
No action needed from you — this is the URL you registered in the athenahealth Developer Portal.
ConnectHealth Completes OAuth and Returns a tokenId
ConnectHealth exchanges the launch token with athenahealth server-side, stores the resulting access token securely on the backend, and redirects back to your embedded app with a short-lived tokenId (a UUID) appended to the URL. The tokenId is one-time use — it's consumed on read and cannot be replayed.
Call Token Exchange to Retrieve the Access Token
Your app must call the Token Exchange endpoint with the tokenId. This endpoint requires the x-api-key header — without it, you will get a 401:
GET https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/exchange/{tokenId}
Headers:
x-api-key: <your-connecthealth-api-key>
Accept: application/json
Response contains access_token, patient, scope, expires_in, and — if offline_access was requested — a refresh_token.
Jump to Get Your ConnectHealth API Key to create one from the Settings tab before calling Token Exchange.
Call FHIR Using the Access Token
Use the access_token as a Bearer token against the FHIR base URL. Prefer the site-specific URL for better performance (see "Which FHIR Base URL Should You Use?" in the Sandbox section):
- Sandbox:
https://api.preview.platform.athenahealth.com/195900/brand/1/csg/1/fhir/r4 - Production:
https://api.platform.athenahealth.com/{practiceId}/brand/{brandId}/csg/{csgId}/fhir/r4
GET {fhirBaseUrl}/Patient/{patient}
Headers:
Authorization: Bearer {access_token}
Accept: application/fhir+json
Refresh Before Expiry
Access tokens expire (typically in minutes). Before the token expires, call the Token Refresh endpoint to obtain a new one without re-prompting the user. Like Token Exchange, this requires x-api-key:
POST https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/refresh
Headers:
x-api-key: <your-connecthealth-api-key>
Content-Type: application/json
Body:
{
"refresh_token": "<your-refresh-token>"
}
Refresh only works if offline_access was included in your requested scopes.
General Scopes
Scopes define the level of access your application requests. Choose the appropriate scopes based on your workflow type and data needs.
User Scopes
User-level scopes grant access based on the permissions of the logged-in clinician or user.
| Scope | Description |
|---|---|
user/*.read |
Read all resource types the user has access to |
user/Patient.read |
Read patient demographics the user can access |
user/Encounter.read |
Read encounter records the user can access |
System Scopes
System-level scopes grant access for backend/server applications without a specific user context. Used with the Backend to Backend (B2B) workflow.
| Scope | Description |
|---|---|
system/*.read |
Read all resource types at the system level |
system/Patient.read |
Read all patient demographics |
Launch Scopes
Launch scopes are used with SMART on FHIR to receive context from the EHR launch.
| Scope | Description |
|---|---|
launch |
Required for EHR launch — receives the launch context from athenahealth |
launch/patient |
Request patient context in a standalone launch |
Identity Scopes
OpenID Connect scopes for obtaining user identity information. The submodule auto-adds openid and fhirUser if not present.
| Scope | Description |
|---|---|
openid |
Required for OpenID Connect — returns an ID token (auto-added) |
fhirUser |
Returns the FHIR resource URL of the authenticated user (auto-added) |
offline_access |
Request a refresh token for long-lived access |
Use Cases
Choose the workflow type that best matches your application's needs.
Patient-Facing Applications
Scenario: A third-party app needs to access patient health data with the patient's explicit consent.
Recommended Workflow: Standalone OAuth
Best For: Patient portals, health tracking apps, care management tools
Recommended Scopes: patient/*.read openid fhirUser launch/patient offline_access
System-to-System Integration
Scenario: A server needs to access athenahealth data without user interaction for automated processing.
Recommended Workflow: Backend to Backend (B2B)
Best For: Nightly data sync, population health analytics, automated reporting
Recommended Scopes: system/*.read
EHR-Embedded Applications
Scenario: An application launched from within athenahealth's clinical workflow that receives patient context automatically.
Recommended Workflow: Embed Launch (SMART on FHIR)
Best For: Clinical decision support, order entry helpers, documentation assistants
Recommended Scopes: launch openid fhirUser patient/*.read
Workflow Automation
Scenario: Low-code Node-RED workflows interacting with athenahealth for automated data pipelines within ConnectHealth.
Recommended Workflow: Backend to Backend (B2B)
Best For: Automated notifications, data transformation pipelines, integration workflows
Recommended Scopes: system/*.read
Get Your ConnectHealth API Key
Several ConnectHealth endpoints — Token Exchange, Backend Token, and Token Refresh — require a ConnectHealth API key passed as the x-api-key header. Without this header, these endpoints return 401 Unauthorized. Follow these steps to create your API key.
Log in to the ConnectHealth Dashboard
Open your ConnectHealth instance (the URL where your deployment is hosted) and sign in with your account credentials.
Navigate to Settings → API Keys
From the left navigation, click Settings, then open the API Keys tab. If you have never generated a key before, the list will be empty.
Create a New API Key
Click Create API Key, enter a descriptive name (e.g., athena-prod-client or embed-launch-dev), and submit. Use one key per environment or per client application so you can rotate individual keys without affecting others.
Copy Your API Key
ConnectHealth automatically saves your API key securely. You can view and copy the key value from Settings → API Keys at any time. Click your key name to reveal and copy it whenever you need it.
Use the Key in the x-api-key Header
Pass the key on every request to a protected endpoint using the header name x-api-key (lowercase, hyphenated). Example:
curl -X GET "https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/exchange/{tokenId}" \
-H "x-api-key: YOUR_API_KEY" \
-H "Accept: application/json"
Endpoints requiring this header are listed in the API Endpoints section below.
API Endpoints
These are the ConnectHealth endpoints your application will interact with. All paths are prefixed with /api/workflow/auth/{integrationId}, where {integrationId} is the connection ID you created in ConnectHealth.
Token Exchange, Backend Token, and Token Refresh all require the x-api-key header. Create a key from Settings → API Keys before calling these endpoints.
Authentication Endpoints
| Method | Endpoint | Description | API Key |
|---|---|---|---|
GET |
/api/workflow/auth/{integrationId}/start |
Initiate OAuth flow for standalone launch. Typically hit from a browser; returns a redirect to athenahealth. | No |
GET |
/api/workflow/auth/{integrationId}/callback |
OAuth redirect URI. Called by athenahealth after user authorization — not by your client. Exchanges the code for tokens and stores them, returning a one-time tokenId. |
No |
GET |
/api/workflow/auth/{integrationId}/launch |
SMART on FHIR EHR Launch URL. Called by athenahealth with iss and launch query params — not by your client. |
No |
GET |
/api/workflow/auth/{integrationId}/token/exchange/{tokenId} |
Exchange a one-time tokenId for the actual access token and patient context. The tokenId is consumed on read. |
Yes |
GET |
/api/workflow/auth/{integrationId}/token |
Request a Backend (B2B) system token using the configured client credentials. No user interaction. | Yes |
POST |
/api/workflow/auth/{integrationId}/token/refresh |
Refresh an expiring access token. Requires a previously issued refresh token (requested via offline_access scope). |
Yes |
GET |
/api/workflow/auth/{integrationId}/token/status/{tokenId} |
Check whether a tokenId is still valid and ready to exchange. Does not consume the token. |
No |
GET |
/api/workflow/auth/{integrationId}/introspect |
Optional diagnostic endpoint that inspects the currently stored token for the integration. | No |
GET |
/api/workflow/auth/{integrationId}/health |
Optional liveness check for the integration's auth pipeline. | No |
Examples
Copy-paste examples for the client-callable endpoints. Replace <your-ch-domain>, {integrationId}, {tokenId}, and YOUR_API_KEY with your actual values.
Token Exchange
Exchange a one-time tokenId for an access token + patient context after Standalone or Embed Launch flows.
curl
curl -X GET "https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/exchange/{tokenId}" \
-H "x-api-key: YOUR_API_KEY" \
-H "Accept: application/json"
JavaScript (fetch)
const res = await fetch(
`https://<your-ch-domain>/api/workflow/auth/${integrationId}/token/exchange/${tokenId}`,
{
headers: {
"x-api-key": process.env.CH_API_KEY,
"Accept": "application/json",
},
}
);
const { access_token, patient, scope, expires_in } = await res.json();
Backend Token (B2B)
Request a system-level access token for server-to-server flows.
curl
curl -X GET "https://<your-ch-domain>/api/workflow/auth/{integrationId}/token" \
-H "x-api-key: YOUR_API_KEY" \
-H "Accept: application/json"
JavaScript (fetch)
const res = await fetch(
`https://<your-ch-domain>/api/workflow/auth/${integrationId}/token`,
{
headers: {
"x-api-key": process.env.CH_API_KEY,
"Accept": "application/json",
},
}
);
const { access_token, expires_in, scope } = await res.json();
Token Refresh
Refresh an access token before expiry. Only works if the original token was issued with offline_access.
curl
curl -X POST "https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/refresh" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'
JavaScript (fetch)
const res = await fetch(
`https://<your-ch-domain>/api/workflow/auth/${integrationId}/token/refresh`,
{
method: "POST",
headers: {
"x-api-key": process.env.CH_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ refresh_token: "YOUR_REFRESH_TOKEN" }),
}
);
const { access_token, refresh_token, expires_in } = await res.json();
Response
{
"body": {
"access_token": "eyJhbGc...",
"refresh_token": "dGhpcyBp...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "patient/*.read",
"patient": "patient-id-if-applicable"
},
"message": "Token refreshed successfully",
"timestamp": 1718000000000
}
Token Status
Check if a one-time tokenId is still valid and ready to exchange. Non-consuming.
curl
curl -X GET "https://<your-ch-domain>/api/workflow/auth/{integrationId}/token/status/{tokenId}" \
-H "Accept: application/json"
JavaScript (fetch)
const res = await fetch(
`https://<your-ch-domain>/api/workflow/auth/${integrationId}/token/status/${tokenId}`,
{ headers: { "Accept": "application/json" } }
);
const { valid, expiresAt } = await res.json();
OAuth Start (browser-initiated)
Begin the Standalone OAuth flow. Typically opened in a browser so the user can authorize with athenahealth.
curl (inspect redirect only)
curl -I "https://<your-ch-domain>/api/workflow/auth/{integrationId}/start"
Example Launch URL (registered in athenahealth Developer Portal):
https://demo.ehrconnect.healthconnect.systems/api/workflow/auth/[your-integration-id]/launch
Replace the domain and integration ID with your actual values.
External Resources
- athenahealth Developer Portal (Login)
- athenahealth API Onboarding Guide — Comprehensive guide for app creation, sandbox, and production submission
- athenahealth FHIR R4 Documentation
- athenahealth Developer Home
- SMART App Launch Guide
- FHIR R4 Specification