Skip to content

Providers and seats

Thea bills practices per provider seat, and only the practice admin can add or remove seats. The API never creates or activates a seat on its own. Staff and admins aren’t billed.

GET /practices/{practice_id}/providers returns everyone on the practice’s Thea roster:

{
"data": [
{
"id": "2210",
"practice_id": "152",
"first_name": "Sam",
"last_name": "Rivera",
"email": "sam.rivera@riverbend.example",
"npi": "1234567890",
"role": "provider",
"status": "active",
"updated_at": "2026-10-02T18:11:40Z"
}
],
"has_more": false,
"next_cursor": null
}
role Who Can send cases and messages Billed
provider A clinician with a seat Yes, for themselves Yes
staff Clinical staff Yes, on a provider’s behalf No
admin Practice admins and billers No, they can only see cases No

status is active, pending (waiting for the admin to approve a seat), or inactive (removed or deactivated). Only active people can act.

Keep your copy current with the provider.activated, provider.deactivated, and provider.updated webhooks, plus a periodic updated_since sync.

Keep a mapping from each of your clinicians and staff to a Thea roster id. Match on NPI where both systems have it, otherwise on email. Plan for:

  • A clinician with no NPI on record in one system.
  • An email that differs between your system and Thea. Thea emails are unique: one account per email, across all practices.
  • Clinicians who work at several practices or locations. They have one roster record in each Thea practice.
  • Staff as well as providers. Staff need a mapping too, so they can create cases on a provider’s behalf.
  • Ambiguous matches, such as two people with the same name and no NPI. Don’t guess; ask the practice admin to resolve them.
  • Name and email changes, and people leaving (provider.deactivated).

Only show the option to send an eConsult to:

  • Clinicians mapped to an active roster member with role provider, and
  • Staff mapped to an active member with role staff, who pick the provider they’re sending for.

Everyone else needs a seat first.

For a clinician without an active seat, offer to request one:

Terminal window
curl -X POST "$THEA_API/practices/152/provider-requests" \
-H "Authorization: Bearer $THEA_PARTNER_KEY" \
-H "Thea-Practice-Key: $THEA_PRACTICE_KEY" \
-H "Content-Type: application/json" \
-d '{ "first_name": "Jordan", "last_name": "Okafor", "email": "jordan.okafor@riverbend.example", "npi": "1987654321" }'

Thea emails the practice admin and returns 202 with the request’s status (pending_admin_approval). If the admin approves, you get a provider.activated webhook. Until then, show the clinician a pending state and another way to send the referral, such as fax. Posting the same email again returns the existing request, so you can check its status.

A seat can be deactivated between showing the eConsult option and submitting the case. POST /cases then returns 422 provider-not-active. Tell the clinician, and fall back the same way.