Summary and recommendation
athenaOne exposes a REST API at `https://api.platform.athenahealth.com/v1/{practiceid}` for user and provider management.
Authentication uses OAuth 2.0 with both `client_credentials` and `authorization_code` grant types;
tokens are short-lived and must be refreshed proactively to avoid 401 errors during long-running operations.
Two scopes are required for user management work: `athena/service/Athenanet.MDP.UserManagement` for reading and writing staff records, and `athena/service/Athenanet.MDP.PracticeManagement` for provider and department lookups.
Sandbox credentials are available at developer.athenahealth.com, but production access requires completing the athenahealth Marketplace partner program-factor in that approval timeline before scoping integration work.
This API has no SCIM 2.0 endpoint and no native IdP connectors.
It also has no webhooks for user lifecycle events.
Any identity graph that needs to stay current with athenaOne must be built on scheduled polling, not event-driven triggers.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (client_credentials and authorization_code flows) |
| Base URL | Official docs |
| SCIM available | No |
Authentication
Auth method: OAuth 2.0 (client_credentials and authorization_code flows)
Setup steps
- Register as a developer or partner at developer.athenahealth.com to obtain sandbox credentials.
- Submit an application through the athenahealth Marketplace partner program for production access.
- Obtain a client_id and client_secret from the athenahealth developer portal.
- Request an access token via POST to https://api.platform.athenahealth.com/oauth2/v1/token using client_credentials or authorization_code grant.
- Include the Bearer token in the Authorization header for all subsequent API requests.
- Specify the target practiceid in the URL path for practice-scoped endpoints.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| athena/service/Athenanet.MDP.UserManagement | Grants access to read and manage user/staff records within a practice. | List users, get user details, create/update staff |
| athena/service/Athenanet.MDP.PracticeManagement | Grants access to practice-level configuration including provider and department data. | Provider and department lookups associated with users |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| userid | integer | Unique identifier for the user/staff member within the practice. | system-assigned | immutable | Used as path parameter for user-specific operations. |
| username | string | Login username for the athenaOne user. | required | optional | Must be unique within the practice. |
| firstname | string | User's first name. | required | optional | |
| lastname | string | User's last name. | required | optional | |
| string | Primary email address for the user. | optional | optional | ||
| usertype | string | Role classification of the user (e.g., STAFF, PROVIDER, ADMIN). | required | optional | Determines access level within athenaOne. |
| active | boolean | Indicates whether the user account is active. | optional (defaults to true) | optional | Set to false to deactivate without deleting. |
| providerid | integer | Associated provider ID if the user is a clinical provider. | optional | optional | Only applicable when usertype is PROVIDER. |
| departmentids | array[integer] | List of department IDs the user is associated with. | optional | optional | Controls which departments the user can access. |
| personid | integer | Internal person record ID linked to this user. | system-assigned | immutable | |
| npi | string | National Provider Identifier for provider-type users. | optional | optional | Required for billing-eligible providers. |
| supervisingproviderid | integer | ID of the supervising provider for mid-level practitioners. | optional | optional | |
| schedulingname | string | Display name used in scheduling views. | optional | optional | |
| createddatetime | string (ISO 8601) | Timestamp when the user record was created. | system-assigned | immutable |
Core endpoints
List Users / Staff
- Method: GET
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/users - Watch out for: Response is scoped to the practiceid in the path. Users from other practices are not returned.
Request example
GET /v1/195900/users?limit=10&offset=0
Authorization: Bearer {access_token}
Response example
{
"totalcount": 42,
"users": [
{"userid": 101, "username": "jdoe", "firstname": "Jane", "lastname": "Doe", "active": true}
]
}
Get User by ID
- Method: GET
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/users/{userid} - Watch out for: Returns 404 if the userid does not exist within the specified practiceid.
Request example
GET /v1/195900/users/101
Authorization: Bearer {access_token}
Response example
{
"userid": 101,
"username": "jdoe",
"firstname": "Jane",
"lastname": "Doe",
"email": "jdoe@clinic.com",
"active": true,
"usertype": "STAFF"
}
Create User / Staff
- Method: POST
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/users - Watch out for: athenahealth user creation endpoints typically use application/x-www-form-urlencoded, not JSON body. Sending JSON will result in a 400 error.
Request example
POST /v1/195900/users
Content-Type: application/x-www-form-urlencoded
username=jsmith&firstname=John&lastname=Smith&usertype=STAFF
Response example
{
"userid": 205,
"username": "jsmith"
}
Update User
- Method: PUT
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/users/{userid} - Watch out for: Full PUT semantics may apply; omitting optional fields could reset them. Verify field behavior in sandbox before production use.
Request example
PUT /v1/195900/users/101
Content-Type: application/x-www-form-urlencoded
email=newemail@clinic.com&active=true
Response example
{
"userid": 101,
"success": true
}
List Providers
- Method: GET
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/providers - Watch out for: Provider records are separate from staff user records. A provider may have both a providerid and a userid.
Request example
GET /v1/195900/providers?limit=20&offset=0
Authorization: Bearer {access_token}
Response example
{
"totalcount": 8,
"providers": [
{"providerid": 1, "firstname": "Alice", "lastname": "Brown", "npi": "1234567890"}
]
}
Get Provider by ID
- Method: GET
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/providers/{providerid} - Watch out for: NPI and scheduling configuration are managed on the provider record, not the user record.
Request example
GET /v1/195900/providers/1
Authorization: Bearer {access_token}
Response example
{
"providerid": 1,
"firstname": "Alice",
"lastname": "Brown",
"npi": "1234567890",
"active": true
}
List Departments
- Method: GET
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/departments - Watch out for: Department IDs are required when assigning users to specific locations; must be retrieved before user creation/update.
Request example
GET /v1/195900/departments
Authorization: Bearer {access_token}
Response example
{
"totalcount": 3,
"departments": [
{"departmentid": 1, "name": "Main Clinic", "active": true}
]
}
Deactivate User
- Method: PUT
- URL:
https://api.platform.athenahealth.com/v1/{practiceid}/users/{userid} - Watch out for: athenaOne does not expose a dedicated DELETE endpoint for users; deactivation via active=false is the supported offboarding method.
Request example
PUT /v1/195900/users/101
Content-Type: application/x-www-form-urlencoded
active=false
Response example
{
"userid": 101,
"success": true
}
Rate limits, pagination, and events
- Rate limits: athenahealth enforces API rate limits per client application. Specific numeric limits are not publicly documented in the developer portal; limits are communicated during the partner onboarding process.
- Rate-limit headers: Unknown
- Retry-After header: Unknown
- Rate-limit notes: Official docs do not publicly enumerate rate-limit headers or Retry-After behavior. HTTP 429 is returned when limits are exceeded. Contact athenahealth partner support for production limits.
- Pagination method: offset
- Default page size: 10
- Max page size: 100
- Pagination pointer: offset / limit
| Plan | Limit | Concurrent |
|---|---|---|
| Sandbox / Developer | Not publicly specified; reduced limits apply | 0 |
| Production Partner | Not publicly specified; negotiated per partner agreement | 0 |
- Webhooks available: No
- Webhook notes: athenahealth does not publicly document outbound webhooks for user management events. Changed data subscriptions exist for clinical data (e.g., appointments, patient records) via the athenahealth Changed Data API, but user/staff lifecycle events are not listed as supported webhook triggers.
- Alternative event strategy: Poll GET /v1/{practiceid}/users on a scheduled basis to detect user changes. For clinical event subscriptions, refer to the athenahealth Changed Data API.
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Not documented
- Endpoint: Not documented
Limitations:
- athenahealth does not publicly document a SCIM 2.0 endpoint for athenaOne.
- No native IdP connectors (Okta, Entra ID, Google Workspace, OneLogin) with SCIM provisioning are listed in official documentation.
- User provisioning must be performed via the proprietary REST API or manual admin console.
Common scenarios
Three core automation scenarios are supported by the API:
Onboard a new staff user: Fetch valid
departmentidsviaGET /v1/{practiceid}/departmentsfirst-hardcoded IDs will break on department reorganization. ThenPOST /v1/{practiceid}/userswith a form-encoded body (application/x-www-form-urlencoded). SendingContent-Type: application/jsonreturns a 400 error; this is the single most common integration failure point.Deactivate a departing employee: Look up the
useridviaGET /v1/{practiceid}/users?username={username}, thenPUT /v1/{practiceid}/users/{userid}withactive=falseas a form-encoded body. There is no DELETE endpoint. If the user is also a provider, scheduling reassignment must be handled separately in the practice admin console-the user management API does not cover it.Sync HR roster to athenaOne: Poll
GET /v1/{practiceid}/userswithoffset/limitpagination (default page size 10, max 100) on a scheduled basis (e.g., nightly). Diff against HR records to drive creates, updates, and deactivations. Refresh OAuth tokens between batches. No event stream exists for user changes, so polling is the only supported detection mechanism.
Onboard a new staff user to a practice
- Authenticate via OAuth 2.0 client_credentials to obtain a Bearer token.
- GET /v1/{practiceid}/departments to retrieve valid departmentids for the target practice.
- POST /v1/{practiceid}/users with username, firstname, lastname, usertype=STAFF, and departmentids as form-encoded body.
- Store the returned userid for future reference and updates.
Watch out for: Department IDs must be fetched first; hardcoding them will break if departments are reorganized. Use form-encoded body, not JSON.
Deactivate a departing employee
- Authenticate via OAuth 2.0 to obtain a Bearer token.
- GET /v1/{practiceid}/users?username={username} to look up the userid of the departing user.
- PUT /v1/{practiceid}/users/{userid} with active=false as form-encoded body.
- If the user is also a provider, verify provider scheduling is reassigned separately via practice admin console.
Watch out for: There is no DELETE endpoint. Setting active=false is the only API-supported deactivation method. Provider scheduling reassignment is not available via the user management API.
Sync user roster from HR system to athenaOne
- Authenticate via OAuth 2.0 client_credentials.
- GET /v1/{practiceid}/users with pagination (offset/limit) to retrieve the full current user list.
- Compare against HR system records to identify new hires, updates, and terminations.
- POST /v1/{practiceid}/users for new hires; PUT /v1/{practiceid}/users/{userid} for updates; PUT with active=false for terminations.
- Schedule this sync job to run periodically (e.g., nightly) since no webhook events are available for user changes.
Watch out for: No webhook or event stream exists for user lifecycle events; polling is required. Ensure OAuth tokens are refreshed between batches to avoid mid-sync 401 errors.
Why building this yourself is a trap
The user object and provider object are distinct and must be managed separately. A clinical provider has a providerid on the provider record (where NPI and scheduling config live) and a separate userid on the login account. Treating them as the same object will produce incomplete offboarding and broken scheduling references.
All endpoints are scoped to a single practiceid in the URL path. There is no multi-practice aggregate endpoint, which means any identity graph spanning multiple practices must issue separate authenticated requests per practice and merge results in the consuming system.
Rate limits are not publicly documented numerically; HTTP 429 is returned when limits are exceeded, and production limits are communicated only through the partner onboarding process. The API base URL has changed historically (previously preview.platform.athenahealth.com), so integrations should validate against current official docs before any version upgrade.
Full PUT semantics may apply on update endpoints-omitting optional fields could silently reset them; always validate field behavior in sandbox before promoting to production.
Automate athenaOne workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.