The athenahealth API is two API families on one platform: the Certified APIs, athenahealth's certified FHIR R4 read and search endpoints, and the athenaOne APIs, a proprietary REST surface under /v1/{practiceid}/ where scheduling, document posting and most write workflows live. Picking the right family per workflow, then getting practice-level access, is most of the work.
This guide is for CTOs and engineering leads connecting a product (an AI scribe, a scheduling agent, a patient engagement or RCM tool) to athenaOne. Vendor details were checked against athenahealth's own sources: its live FHIR metadata and SMART configuration, the Athena Core implementation guide, its developer documentation and its GitHub samples. We build EHR integration layers across Epic, Oracle Health, athenahealth, eClinicalWorks and NextGen, and our athenahealth integration work is where these patterns come from. Still choosing which EHRs to support first? Start with our EHR integration API comparison.
Key takeaways
- Two lanes. The Certified FHIR R4 APIs are almost entirely read and search. Booking appointments, posting documents and creating patients happen in the athenaOne APIs.
- Everything is scoped to a practice. athenaOne paths carry
{practiceid}; FHIR searches use theah-practiceparameter. Departments decide much of the rest. - The sandbox is shared. A Developer Portal account gets you into the preview environment, practice
195900, atapi.preview.platform.athenahealth.com. - OAuth 2.0 both ways. 2-legged
client_credentialsfor backend services, 3-leggedauthorization_codewith PKCE for SMART apps. New token requests are capped at 50 per minute in production and 5 in preview. - Three sync options. Changed data subscriptions (poll), FHIR Subscriptions (webhooks, Alpha) and Group-level Bulk FHIR export with
_since. - Production is per customer. You get back-end access to a practice only after that client signs an Authorization and Consent agreement.
What is the athenahealth API?
The athenahealth API is the set of programmatic interfaces into athenaOne, athenahealth's cloud EHR, practice management and billing platform. It has two families: Certified APIs built on FHIR R4 and US Core for standardized clinical reads, and proprietary athenaOne APIs for practice workflows such as scheduling, registration, documents and claims.
The fastest way to understand the FHIR side is to read what the server declares. athenahealth's production CapabilityStatement is public. In September 2026 it reports FHIR 4.0.1, instantiates US Core 3.1.1 and 6.1.0 plus Bulk Data 1.0.1 and 2.0.0, and lists 32 resource types. Nearly all of them support only read and search-type; QuestionnaireResponse create and a few custom operations are the exceptions. A trimmed excerpt captured from that endpoint:
{
"resourceType": "CapabilityStatement",
"publisher": "athenahealth",
"fhirVersion": "4.0.1",
"instantiates": [
"http://hl7.org/fhir/us/core/CapabilityStatement/us-core-server|3.1.1",
"http://hl7.org/fhir/us/core/CapabilityStatement/us-core-server|6.1.0",
"http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data|1.0.1",
"http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data|2.0.0"
],
"rest": [{
"mode": "server",
"resource": [{
"type": "Appointment",
"interaction": [{ "code": "read" }, { "code": "search-type" }],
"searchParam": [
{ "name": "_id" }, { "name": "_query" },
{ "name": "base-appointment-id" }, { "name": "group-appointment-id" },
{ "name": "ah-practice" }, { "name": "_security" }
]
}]
}]
} Look at that Appointment entry. It declares no patient or date search parameter, so "this patient's upcoming visits" or "open slots next week" cannot be built on FHIR alone. That one detail pushes every scheduling product into the athenaOne APIs. Our guide on how to read a FHIR CapabilityStatement shows how to run this check for any EHR.
The athenaOne APIs are the older, broader surface. Paths look like /v1/{practiceid}/appointments/open, responses are athenaOne-shaped JSON rather than FHIR, and write calls such as posting a clinical document take form parameters instead of a JSON body. athenahealth's API documentation covers both families.
How is athenaOne organized: practices, departments and providers
athenaOne is organized around the practice. A practice is the tenant, identified by a practiceid that appears in every athenaOne API path. Inside a practice sit departments (departmentid), providers (providerid), patients (patientid) and appointments (appointmentid). Most workflow calls need both a practice and a department.
FHIR models the same structure with Organization references. athenahealth's Athena Core implementation guide defines ah-practice as Organization/a-1.Practice-[practiceId] and ah-department as Organization/a-[practiceId].Department-[deptId], with the same pattern for chart sharing groups (CSG), provider groups (PG) and brands. They appear as extensions on resources and double as search parameters.
Keep a crosswalk from day one:
| Concept | athenaOne APIs | FHIR R4 form | What to watch |
|---|---|---|---|
| Practice | practiceid in the path: /v1/{practiceid}/... | Organization/a-1.Practice-{practiceid} via ah-practice | Preview practice is 195900. Every customer has its own ID. |
| Department | departmentid parameter | Organization/a-{practiceid}.Department-{departmentid} via ah-department | Required when posting clinical documents. Changed data feeds can be subscribed per department. |
| Provider | providerid | Practitioner | Open slot searches filter by provider as well as department. |
| Patient | patientid | Patient logical id | Treat the FHIR id as opaque. Records can be merged, so keep ID history. |
| Appointment | appointmentid (you book an open slot by its ID) | Appointment, read and _id search only | Scheduling writes are athenaOne-only. |
| Bulk export group | Not applicable | Group/a-1.c-{practiceid} | The Group ID is built from the practice ID, so exports are practice-scoped. |
athenahealth FHIR API vs athenaOne API: which to use for each workflow
Use the Certified FHIR R4 APIs for standardized clinical reads across USCDI data, where your code should transfer to other EHRs. Use the athenaOne APIs when you need to write, schedule, register, match patients or touch billing. Most production integrations use both, split by workflow rather than by preference.
| Workflow | Certified FHIR R4 APIs | athenaOne APIs | Our default |
|---|---|---|---|
| Patient demographics | Patient read and search by name, family, given, birthdate, gender, identifier, _lastUpdated | Create and update patients, GET /patients/enhancedbestmatch | Read with FHIR. Create and match with athenaOne. |
| Appointments and scheduling | Appointment read, search by _id and appointment ID parameters | GET /appointments/open, PUT /appointments/{appointmentid} to book, reschedule, changed feed | athenaOne for anything beyond a known-ID read. |
| Clinical documents | DocumentReference search by patient, category, type, date, encounter; Binary read | POST /patients/{patientid}/documents/clinicaldocument | Read with FHIR. Write with athenaOne. |
| Labs and results | Observation and DiagnosticReport search by patient, category, code, date | Chart lab results, lab result documents, changed lab results feed | FHIR for reads unless you need athenaOne-specific fields. |
| Charges and billing | Coverage read and search | Claims endpoints, with claim and charge-level detail | athenaOne. FHIR does not cover billing here. |
| Bulk export and sync | Group/[id]/$export with _since | Changed data subscriptions per feed | Bulk for backfill, changed feeds or webhooks for ongoing sync. |
athenahealth also adds its own search parameters (ah-practice, ah-department, ah-chart-sharing-group, ah-provider-group, ah-brand) on top of US Core. Plain US Core code runs, but it will not scope results the way a multi-practice product needs; see why FHIR compliant does not mean interoperable. If you support several EHRs, design your internal model around workflows, not vendor endpoints, as our multi-EHR integration layer guide argues.
How do you get athenahealth API access, step by step?
Sign up on the athenahealth Developer Portal, create an app to get client credentials, and build against the shared preview practice. To reach real data, each customer practice must authorize your app. Apps that use only Certified APIs have a self-service onboarding path; apps that use athenaOne APIs go through partner onboarding with athenahealth.
- Create a Developer Portal account. athenahealth's onboarding guide says signing up grants access to the global sandbox, practice
195900. - Create an app in the Developer Console. You get a client ID and secret. The secret is shown once, so store it in your secrets manager immediately.
- Prove the credentials work. Request a preview token, then call
GET /v1/195900/ping. - Build in preview. Preview holds non-sensitive dummy data. Use it for request shapes, error handling and paging, not realistic clinical content.
- Choose your lane before you sell. Since release 23.3 the Developer Console allows self-service onboarding for apps using only Certified APIs. If you need athenaOne APIs, plan for partner onboarding and a commercial conversation with athenahealth.
- Get each customer's authorization. Partners receive only back-end access to a client's production environment, after the client signs an Authorization and Consent agreement. For Certified-only apps, practices enable the app from an athenaOne admin page.
- Switch hosts and go live. Point at
api.platform.athenahealth.comwith the customer'spracticeid, and repeat steps 6 and 7 for every practice.
| Preview | Production | |
|---|---|---|
| FHIR R4 base | https://api.preview.platform.athenahealth.com/fhir/r4 | https://api.platform.athenahealth.com/fhir/r4 |
| athenaOne base | https://api.preview.platform.athenahealth.com/v1/195900/ | https://api.platform.athenahealth.com/v1/{practiceid}/ |
| Practice | Shared global sandbox | Each customer's own ID |
| Data | Dummy data | Real PHI under the customer's authorization |
| New token requests | 5 per minute | 50 per minute |
The FHIR bases match athenahealth's FHIR base URL guide and the live endpoints. For what else changes between sandbox and production, see our SMART on FHIR sandbox to production guide.
How does athenahealth API authentication work?
athenahealth uses OAuth 2.0 on /oauth2/v1/token and /oauth2/v1/authorize. Backend services use 2-legged OAuth with the client_credentials grant. User-facing SMART on FHIR apps use 3-legged OAuth with authorization_code and PKCE. The two require different client credentials, and both return a bearer token.
The authoritative statement of what the authorization server supports is its discovery document. A trimmed copy of the live production smart-configuration, captured in September 2026:
{
"authorization_endpoint": "https://api.platform.athenahealth.com/oauth2/v1/authorize",
"token_endpoint": "https://api.platform.athenahealth.com/oauth2/v1/token",
"grant_types_supported": ["authorization_code", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": [
"client_secret_basic", "client_secret_post",
"client_secret_jwt", "private_key_jwt", "none"
],
"capabilities": [
"launch-ehr", "launch-standalone", "client-public",
"client-confidential-symmetric", "client-confidential-asymmetric",
"context-ehr-patient", "context-ehr-encounter", "context-standalone-patient",
"permission-offline", "permission-v1", "permission-v2", "sso-openid-connect"
]
} 2-legged OAuth: the backend service token request
This is the flow for sync workers, scheduling engines and document pipelines. athenahealth's authorization overview documents both secret-based authentication and JWT client assertions. The simplest form sends the client ID and secret as HTTP Basic credentials:
curl -s -X POST "https://api.preview.platform.athenahealth.com/oauth2/v1/token" \
-u "$ATHENA_CLIENT_ID:$ATHENA_CLIENT_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "scope=athena/service/Athenanet.MDP.*"
# then
curl -s "https://api.preview.platform.athenahealth.com/v1/195900/ping" \
-H "Authorization: Bearer $ACCESS_TOKEN" The athena/service/Athenanet.MDP.* scope covers athenaOne API calls. FHIR access uses SMART system/ scopes; athenahealth's FHIR Subscriptions sample, for example, requests system/Subscription.read. If your security team rejects shared secrets, the server advertises private_key_jwt, the signed-assertion method in the HL7 SMART Backend Services specification.
New token requests are capped at 50 per minute in production and 5 in preview, and exceeding the cap returns 429 for the rest of that minute. Cache tokens centrally and reuse them until shortly before expires_in. A fleet of stateless workers each fetching its own token will lock itself out, and the preview cap exposes this during your first load test.
3-legged OAuth: SMART on FHIR apps
For apps a clinician launches from athenaOne or a patient opens directly, redirect to /oauth2/v1/authorize with PKCE (S256 is the only advertised method), then exchange the code at the token endpoint. The discovery document advertises EHR and standalone launch, patient and encounter context, offline access and both SMART v1 and v2 scopes. athenahealth manages 3-legged registration separately from 2-legged apps and has changed the rules across releases, so confirm current eligibility for your app type early. For the protocol, see SMART on FHIR OAuth2 authorization for clinical apps.
Common athenahealth API workflows with example requests
Three workflows cover most product integrations: finding the right patient, booking into a real open slot, and writing a document back to the chart. The requests below use documented endpoints against the preview practice. Replace the shell variables, and check each endpoint reference for required parameters and formats.
Search for a patient
For read-only lookups, FHIR search is the portable option. Scope it to the practice with ah-practice:
curl -s -G "https://api.preview.platform.athenahealth.com/fhir/r4/Patient" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Accept: application/fhir+json" \
--data-urlencode "ah-practice=Organization/a-1.Practice-195900" \
--data-urlencode "family=$LAST_NAME" \
--data-urlencode "birthdate=$BIRTHDATE" When a person arrives from outside athenaOne (a caller, an intake form, a referral) and you must decide whether they already exist, use the Enhanced Best Match workflow. It matches on first name, last name and date of birth, with extra signals such as zip or phone:
curl -s -G "https://api.preview.platform.athenahealth.com/v1/195900/patients/enhancedbestmatch" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
--data-urlencode "firstname=$FIRST_NAME" \
--data-urlencode "lastname=$LAST_NAME" \
--data-urlencode "dob=$DOB_MM_DD_YYYY" \
--data-urlencode "zip=$ZIP" Never auto-create a patient on a weak match. Duplicate charts are costly for the practice to merge and break your sync keys. See patient matching beyond demographics for thresholds and review queues.
Find open appointment slots and book one
Scheduling is athenaOne-only. The Appointment Slot reference documents GET /appointments/open, filtered by department, provider, appointment type or reason, and date range. Each open slot has an appointmentid; booking is a PUT on that ID, documented in the Appointment reference.
# 1. Open slots for a department and provider
curl -s -G "https://api.preview.platform.athenahealth.com/v1/195900/appointments/open" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
--data-urlencode "departmentid=$DEPARTMENT_ID" \
--data-urlencode "providerid=$PROVIDER_ID" \
--data-urlencode "appointmenttypeid=$APPOINTMENT_TYPE_ID" \
--data-urlencode "startdate=$START_DATE" \
--data-urlencode "enddate=$END_DATE"
# 2. Book the chosen slot for the matched patient
curl -s -X PUT "https://api.preview.platform.athenahealth.com/v1/195900/appointments/$APPOINTMENT_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "patientid=$PATIENT_ID" \
-d "appointmenttypeid=$APPOINTMENT_TYPE_ID" \
-d "departmentid=$DEPARTMENT_ID" Three things decide whether this works at a real practice. Slots exist only where the practice has built provider schedule templates, so an empty response usually means configuration, not a bug. Appointment types and reasons are practice-specific IDs to discover per customer, never hard-code. And a slot can be taken between search and booking, so handle the failure and re-offer. Changes to booked appointments use PUT /appointments/booked/{appointmentid}. For FHIR Slot and Appointment at other vendors, see our FHIR scheduling API guide.
Post a clinical document to the chart
AI scribes and document pipelines write back through POST /patients/{patientid}/documents/clinicaldocument. Per the Clinical Document reference, departmentid is mandatory, the file goes in attachmentcontents as Base64, and documentsubclass classifies the document:
curl -s -X POST "https://api.preview.platform.athenahealth.com/v1/195900/patients/$PATIENT_ID/documents/clinicaldocument" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "departmentid=$DEPARTMENT_ID" \
--data-urlencode "documentsubclass=$DOCUMENT_SUBCLASS" \
--data-urlencode "attachmenttype=$ATTACHMENT_TYPE" \
--data-urlencode "attachmentcontents=$(base64 -i visit-note.pdf)" Posted documents land in a clinician's workflow and the legal record, so agree the subclass and department for each document type with the practice before go-live. If you already run Mirth Connect for HL7 v2 feeds, our walkthrough of Mirth Connect and athenahealth clinical and billing workflows shows how to drive these calls from an interface engine.
Scoping an athenaOne integration for scheduling or notes? We build and run these integrations for product teams. Talk to our team and we will map which of your workflows fit the Certified APIs, which need athenaOne APIs, and what each customer practice has to enable.
How do you detect changes in athenaOne and keep data in sync?
athenahealth gives you three mechanisms. Changed data subscriptions let you subscribe to a feed and poll for changed records. FHIR Subscriptions push id-only webhook notifications and are currently in Alpha. Group-level Bulk FHIR export with _since pulls incremental batches. Most products pair a bulk backfill with one of the first two.
| Changed data subscriptions | FHIR Subscriptions | Bulk FHIR Group export | |
|---|---|---|---|
| Model | Subscribe once, then poll /{feed}/changed | Push: rest-hook webhook, id-only payload | Async batch job, NDJSON files |
| Auth | 2-legged token | 2-legged apps only, HMAC-signed delivery | Token with system scopes |
| Scope | Practice, optionally per department | Topics such as Patient, Appointment, Encounter, Order, Claims | Whole practice: Group/a-1.c-{practiceid} |
| Maturity | Long-standing athenaOne API | Alpha | Part of the certified FHIR surface |
| Best for | Operational sync of appointments and patients | Near real-time triggers | Backfill, analytics, nightly deltas |
Changed data subscriptions
athenahealth's Changed Data Subscriptions guide describes the pattern: subscribe a feed, then read its changes. For appointments:
# Subscribe once (optionally to specific events with eventname)
curl -s -X POST "https://api.preview.platform.athenahealth.com/v1/195900/appointments/changed/subscription" \
-H "Authorization: Bearer $ACCESS_TOKEN"
# Poll on a schedule
curl -s -G "https://api.preview.platform.athenahealth.com/v1/195900/appointments/changed" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
--data-urlencode "departmentid=$DEPARTMENT_ID" Other feeds follow the same shape, such as /patients/changed. The changed endpoints accept parameters such as leaveunprocessed and showprocessedstartdatetime/showprocessedenddatetime, which tells you the model: reads work through a queue of unprocessed changes, and processed windows can be re-read. Check the endpoint reference before relying on either, and make the worker idempotent by upserting on appointmentid or patientid. Since release 21.7 you can subscribe feed types to individual departments, useful when a customer uses you in only part of the practice.
FHIR Subscriptions (Alpha)
athenahealth's aone-fhir-subscriptions sample describes an event platform that largely follows the FHIR Subscriptions R5 Backport guide, with only rest-hook channels and id-only payloads. Your HTTPS endpoint must answer 2xx within two seconds, verify the X-Hub-Signature HMAC and tolerate duplicates, because delivery is at least once. Failed deliveries retry for up to an hour, then sit in a dead letter queue for seven days. Every id-only notification becomes a follow-up FHIR read, so budget for that volume. For the surrounding architecture, see event-driven pipelines with FHIR Subscriptions.
Bulk FHIR export
The Group profile in the Athena Core IG states that only the Group-level export is supported, with the ID formatted as a-1.c-[practiceId]; there is no system-level or Patient-level kick-off. athenahealth has announced _since support for Bulk export, which makes nightly deltas practical. The request follows the HL7 Bulk Data export async pattern:
curl -s -i "https://api.preview.platform.athenahealth.com/fhir/r4/Group/a-1.c-195900/\$export?_type=Patient,Encounter,Observation&_since=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async"
# 202 Accepted + Content-Location header: poll it until 200 returns the output manifest The manifest lists NDJSON file URLs per resource type plus a transactionTime, which you store as the next _since. Our Bulk FHIR export guide for Epic, Oracle Health and athenahealth compares Group semantics and polling across vendors.
Going to production and listing on the athenahealth Marketplace
Production on athenahealth means one authorized practice at a time. Each customer signs an Authorization and Consent agreement that gives your app back-end access to its production environment, and you call the production host with that practice's ID. A Marketplace listing is a separate, optional step that puts your app in front of athenaOne customers.
Treat production as a repeatable runbook. For each practice, capture its practiceid, departments in scope, bookable providers and appointment types, document subclasses, and a named admin who signs and enables. The Developer Console's analytics dashboard shows call volume, errors and rate limits per app, which is the first place to look when a customer reports missing data.
The athenahealth Marketplace is athenahealth's app marketplace for athenaOne customers. athenahealth says partners are vetted for security, HIPAA compliance and integration quality before listing, with ongoing checks after. Prepare security documentation early: data flows, access controls, encryption, audit logging and incident response. We do not quote Marketplace or API fees; get current commercial terms from athenahealth before you set your own pricing.
Where teams get stuck with athenahealth integrations
The code is rarely the slow part. Teams lose time on access, configuration and assumptions the sandbox never tests.
1. Designing on FHIR, then finding the writes elsewhere
The CapabilityStatement shows read and search for almost everything. Teams that plan scheduling or note write-back on FHIR Appointment or DocumentReference writes must rebuild on athenaOne APIs and may need to change onboarding lanes. Cost: a redesign sprint plus an unplanned commercial conversation.
2. Practice-level enablement
Nothing works in production until that specific practice signs its Authorization and Consent and, for Certified-only apps, enables the app. Your go-live date sits on a practice admin's calendar. Cost: idle engineers and slipped pilots. Start the paperwork during the sales cycle.
3. Department scoping
Clinical documents need a departmentid, open slots are searched per department, and subscriptions can be department-scoped. A product that stores only practiceid posts to the wrong department or misses changes. Cost: data fixes inside a customer's chart, the most expensive kind of bug.
4. Throttling
Per-request token fetching hits the 50 and 5 per minute token caps fast, and id-only webhooks and polling add read volume. Cost: intermittent 429s that look like outages. Centralize token caching, back off with jitter, and batch reads.
5. Sandbox data gaps
Practice 195900 is a shared sandbox with dummy data. Its departments, providers, appointment types and templates are not your customer's. Cost: code that passes every preview test and returns empty slot lists in production. Build per-practice configuration discovery and test against the customer's real setup early.
6. Mapping IDs
patientid, the FHIR Patient logical id and your internal ID are three different keys, and merges add history: the changed-patients feed offers showpreviouspatientids for that reason. Cost: duplicate or orphaned records that surface months later. Keep a crosswalk keyed by practice and record previous IDs.
These problems multiply with every EHR you add, which is why we built one facade over Epic, Cerner and athenahealth in our multi-EHR FHIR facade case study.
athenahealth API integration checklist
Run through this before you promise a customer a go-live date.
- Map every workflow to Certified FHIR APIs or athenaOne APIs using the decision table.
- Confirm your onboarding lane and start any commercial track with athenahealth.
- Create the Developer Portal app and store the secret in a secrets manager.
- Build a shared token cache that respects the 50 and 5 per minute caps.
- Check the live CapabilityStatement and SMART configuration in CI and alert on changes.
- Model
practiceid,departmentid,providerid,patientidandappointmentidwith a FHIR id crosswalk. - Run Enhanced Best Match before creating any patient, with manual review for weak matches.
- Discover appointment types, reasons and departments per practice; handle empty slot lists and booking conflicts.
- Agree document subclass and department mapping with each practice.
- Choose a sync design: bulk backfill with
_sinceplus changed data polling or FHIR Subscriptions, all idempotent. - Prepare a per-practice runbook and security documentation for any Marketplace listing.
- Monitor call volume, errors and rate limits per practice from the first production call.
The Certified APIs exist because of the ONC (g)(10) standardized API criterion, which requires US Core, SMART App Launch and Bulk Data. We hold our own open-source FHIR server to that bar: it passes the Inferno SMART App Launch suite 47 of 47. On athenahealth, though, the certified surface is the easy half. The athenaOne APIs, practice configuration and per-customer access decide whether an integration ships.
Planning an athenaOne integration? Our healthcare interoperability solutions team builds the FHIR and athenaOne API layer, sync workers and per-practice onboarding, and our custom healthcare software development team builds the product around it. Talk to our team to pressure-test your athenahealth scope before you commit to a timeline.



