Heidi API
Authentication

Authentication

Authentication Flow

  1. To authenticate with the Heidi API and use the widget, you will need to generate a JSON Web Token (JWT) using your API key.

  2. The API key provided is unique to your EHR system.

  3. Heidi will use your API key in combination with your EHR User UID and email address to generate a unique "Heidi API User" account for the EHR User making the request.

Authenticate with the API

Method: GET

Path: /jwt

Description: Get a JWT token for authenticating with the API.

Request

GET /jwt?email=test@heidihealth.com&third_party_internal_id=123
Heidi-Api-Key: <heidi_api_key>

Response

{
  "token": "JWT_TOKEN",
  "expiration_time": "2024-08-01T00:00:00.000Z"
}

Link to a Heidi Account

Method: POST

Path: /users/linked-account

Description: Linked an API user to a Heidi account.

Request

POST /users/linked-account
Authorization: Bearer <your_token>
Content-Type: application/json
 
{
  "kinde_user_id": "kp_xxx",
}

Response

{
  "account": {
    "_id": "690d2e568252d4ba7136bcf5",
    "user_id": "kp_c2487b8e79e3413e8cd590ec43d41c9a",
    "ehr_provider": "Heidi",
    "ehr_email": "test@heidi.com",
    "ehr_user_id": "123",
    "deleted_at": null,
    "created_at": "2025-11-06T23:25:10.127632",
    "updated_at": "2025-11-06T23:25:10.127634"
  }
}

If a user is already linked to a Heidi account, the following error will be returned:

{
  "detail": {
    "msg": "Heidi account with user_id kp_xxx already linked to an OpenAPI User",
    "type": "OpenAPIHeidiAccountAlreadyLinkedError"
  }
}

Unlink a Heidi Account

Method: DELETE

Path: /users/linked-account:unlink

Description: Remove a linked Heidi account from an API user.

Request

DELETE /users/linked-account:unlink
Authorization: Bearer <your_token>

Response

{
  "is_success": true
}

Checking link status

Method: GET

Path: /users/linked-account/access

Description: Check if an API user is linked to a Heidi account.

Request

GET /users/linked-account/access
Authorization: Bearer <your_token>

Response

{
  "is_valid": true,
  "is_linked": true,
  "account": {
    "user_id": "Heidi User ID",
    "ehr_provider": "Your EHR Provider",
    "ehr_email": "The email provided with the API key",
    "ehr_user_id": "The user ID provided with the API key"
  },
  "heidi_email": "The users' email",
  "linked_account_plan": "The users' Heidi plan"
}

In the response above, if is_linked is false, the user is not linked to a Heidi account. If is_linked is true, the user is linked to a Heidi account.


Team Management

The Team Management APIs allow you to retrieve information about teams and organization members.

List Joined Teams

Method: GET

Path: /team

Description: List all teams that the authenticated user has joined.

Request

GET /team
Authorization: Bearer <your_token>

Response

{
  "joined_teams": [
    {
      "team_id": "5eb7cf5a86d9755df3a6c593",
      "team_name": "My Team",
      "user_role": "ADMIN",
      "free_trial_end_date": "2024-12-31T00:00:00.000Z",
      "joined_at": "2024-01-01T00:00:00.000Z",
      "member_count": 10
    }
  ]
}

Response Fields

FieldTypeDescription
team_idstringUnique identifier for the team
team_namestringDisplay name of the team
user_rolestringUser's role in the team (ADMIN or MEMBER)
free_trial_end_datestringISO 8601 timestamp of when free trial ends (nullable)
joined_atstringISO 8601 timestamp of when user joined (nullable)
member_countintegerNumber of members in the team (nullable)

Get Team Details

Method: GET

Path: /team/{team_id}

Description: Get detailed information about a specific team.

Request

GET /team/5eb7cf5a86d9755df3a6c593
Authorization: Bearer <your_token>

Path Parameters

ParameterTypeRequiredDescription
team_idstringYesThe unique identifier of the team

Response

{
  "team": {
    "id": "5eb7cf5a86d9755df3a6c593",
    "name": "My Team",
    "country": "AU",
    "is_subscribed": true,
    "created_at": "2024-01-01T00:00:00.000Z",
    "updated_at": "2024-06-01T00:00:00.000Z",
    "is_stripe_managed": true,
    "charge_future_members": true,
    "allow_to_add_team_members": true,
    "admin_session_review_toggle": false,
    "subscribed_plan": "PRO",
    "tier": "PRO",
    "plan_cycle": "MONTHLY",
    "plan_start_date": "2024-01-01T00:00:00.000Z",
    "plan_end_date": "2025-01-01T00:00:00.000Z",
    "require_patient_consent": false,
    "org_id": "5eb7cf5a86d9755df3a6c594",
    "org_name": "My Organization"
  }
}

Response Fields

FieldTypeDescription
idstringUnique identifier for the team
namestringTeam display name
countrystringCountry code for the team
is_subscribedbooleanWhether the team has an active subscription
created_atstringISO 8601 timestamp of team creation
updated_atstringISO 8601 timestamp of last update
is_stripe_managedbooleanWhether billing is managed through Stripe
charge_future_membersbooleanWhether new members are automatically charged
allow_to_add_team_membersbooleanWhether adding new members is allowed
admin_session_review_togglebooleanWhether admin session review is enabled
subscribed_planstringCurrent subscription plan tier
tierstringCurrent tier level
plan_cyclestringBilling cycle (MONTHLY or YEARLY)
plan_start_datestringISO 8601 timestamp of plan start
plan_end_datestringISO 8601 timestamp of plan end
require_patient_consentbooleanWhether patient consent is required
org_idstringOrganization ID (if part of an organization)
org_namestringOrganization name (if part of an organization)

List Organization Members

Method: GET

Path: /organization/{organization_id}/members

Description: List members of an organization with pagination and filtering options.

Request

GET /organization/5eb7cf5a86d9755df3a6c593/members?page=1&page_size=10
Authorization: Bearer <your_token>

Path Parameters

ParameterTypeRequiredDescription
organization_idstringYesThe unique identifier of the organization

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number (minimum: 1)
page_sizeintegerNo10Number of results per page (1-200)
order_bystringNonameField to sort by: name, email, specialty, role, or team
is_descendingbooleanNofalseSort in descending order
searchstringNo-Search term to filter members
role_idsarrayNo-Filter by role IDs
team_idsarrayNo-Filter by team IDs
specialty_idsarrayNo-Filter by specialty IDs
show_pending_invitations_onlybooleanNofalseShow only pending invitations

Response

{
  "members": [
    {
      "id": "5eb7cf5a86d9755df3a6c593",
      "team_id": "5eb7cf5a86d9755df3a6c594",
      "team_name": "My Team",
      "user_role": "MEMBER",
      "kinde_user_id": "kp_xxx",
      "name": "John Doe",
      "email": "john.doe@example.com",
      "specialty": "General Practice",
      "specialty_id": "5eb7cf5a86d9755df3a6c596",
      "country": "AU",
      "invitation_accepted": true,
      "is_team_owner": false,
      "invitation_expire_at": null
    }
  ],
  "total": 50,
  "page": 1,
  "page_size": 10
}

Response Fields

FieldTypeDescription
membersarrayList of organization members
totalintegerTotal number of members
pageintegerCurrent page number
page_sizeintegerNumber of members per page

Member Object Fields

FieldTypeDescription
idstringUnique identifier for the team relation/invitation
team_idstringTeam ID the member belongs to
team_namestringName of the team
user_rolestringUser's role (ADMIN or MEMBER)
kinde_user_idstringUser's Kinde ID
namestringMember's display name
emailstringMember's email address
specialtystringMember's medical specialty
specialty_idstringSpecialty ID (nullable)
countrystringMember's country code (nullable)
invitation_acceptedbooleanWhether the invitation has been accepted
is_team_ownerbooleanWhether the member is the team owner
invitation_expire_atstringISO 8601 timestamp of invitation expiry (nullable)