Prescriber Enrollment | Medplum

On this page

This guide explains how to enroll a new prescriber in DoseSpot. Medplum provides two enrollment bots:

Approach Bot Best for
Admin-driven dosespot-enroll-prescriber-bot IT admin enrolls each provider manually; full control over each step
Self-service dosespot-self-enroll-prescriber-bot Provider enrolls themselves the first time they open the DoseSpot iFrame; no back-and-forth with admin

Both bots support full EPCS enrollment (IDP + TFA). The self-service bot auto-advances through each registration stage on each call, while the admin bot requires explicit initIdp/initTfa flags.

Admin-Driven Enrollment (dosespot-enroll-prescriber-bot)

Prerequisites

The user executing the bot must:

  1. Be an admin in your project (ProjectMembership.admin)
  2. Already have access to DoseSpot (DoseSpot identifier on their ProjectMembership)
  3. Have a Clinician Admin role type in DoseSpot (as specified in the practitionerRoleTypes parameter)

Enrollment Workflow Overview

Prescriber enrollment is a multi-step process. The exact steps depend on whether EPCS (controlled substance prescribing) is needed.

Basic Enrollment (non-EPCS)

  1. Admin runs the enroll bot with the prescriber's practitionerId and practitionerRoleTypes
  2. The bot creates or updates the clinician record in DoseSpot
  3. The prescriber can now log in to the DoseSpot iFrame and prescribe non-controlled medications

EPCS Enrollment

EPCS requires identity proofing (IDP) and two-factor authentication (TFA). This is a multi-step process involving both the admin and the prescriber:

  1. Admin runs the enroll bot. The Practitioner resource must have DEA number(s) in its identifier array.
  2. Prescriber logs in to the DoseSpot iFrame via the provider app and signs the required legal agreement.
  3. Admin runs the bot again with initIdp: true to initialize identity proofing.
  4. Prescriber logs in to the DoseSpot iFrame and completes the IDP process.
  5. Admin runs the bot again with initTfa: true to initialize TFA activation.
  6. Prescriber logs in to the DoseSpot iFrame and completes the TFA setup. After this, EPCS is fully enabled.

Practitioner Resource Requirements

The Practitioner resource must contain the following fields (extracted automatically by the bot):

Field Required Description Requirements
name Yes At least one name entry - family: Last name (required)
- given: Array of given names (at least one required)
birthDate Yes Date of birth Date format (e.g., "1980-05-15")
identifier Yes Must include an NPI identifier - system: "http://hl7.org/fhir/sid/us-npi"
- value: Valid 10-digit NPI that passes check digit validation (can generate HERE)
address Yes Address information Must include: line, city, state (2-letter code), postalCode
telecom Yes Contact information - Email: system: "email"
- Phone: system: "phone", use: "work"
- Fax: system: "fax", use: "work"
active Yes Boolean indicating if practitioner is active Defaults to true

DEA Number Identifier

If EPCS is needed, the Practitioner must have one or more DEA number identifiers. DEA numbers are read directly from the Practitioner's identifier array using the standard HL7 DEA NamingSystem. The assigner.display field (state) is required by DoseSpot and must be a 2-letter US state abbreviation (e.g., "NY", "CA", "WV").

{
  "type": {
    "coding": [{
      "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
      "code": "DEA"
    }]
  },
  "system": "http://terminology.hl7.org/NamingSystem/USDEANumber",
  "value": "AB1234563",
  "assigner": {
    "display": "IL"
  }
}

If a prescriber has DEA numbers for multiple states, add multiple identifier entries:

"identifier": [
  {
    "system": "http://hl7.org/fhir/sid/us-npi",
    "value": "1234567893"
  },
  {
    "type": {
      "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "DEA" }]
    },
    "system": "http://terminology.hl7.org/NamingSystem/USDEANumber",
    "value": "AB1234563",
    "assigner": { "display": "IL" }
  },
  {
    "type": {
      "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "DEA" }]
    },
    "system": "http://terminology.hl7.org/NamingSystem/USDEANumber",
    "value": "CD9876543",
    "assigner": { "display": "NY" }
  }
]

Full Practitioner resource example (with DEA)

{
  "resourceType": "Practitioner",
  "id": "ced6426b-ad93-4abe-8e75-1695d956e471",
  "name": [
    {
      "family": "Smith",
      "given": ["Jane", "Marie"],
      "prefix": ["Dr."] // Optional
    }
  ],
  "birthDate": "1980-05-15",
  "identifier": [
    {
      "system": "http://hl7.org/fhir/sid/us-npi",
      "value": "1234567893"
    },
    {
      "type": {
        "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "DEA" }]
      },
      "system": "http://terminology.hl7.org/NamingSystem/USDEANumber",
      "value": "AB1234563",
      "assigner": { "display": "IL" }
    }
  ],
  "telecom": [
    { "system": "email", "value": "jane.smith@example.com" },
    { "system": "phone", "use": "work", "value": "345-123-4567" },
    { "system": "fax", "use": "work", "value": "567-123-4568" }
  ],
  "address": [
    {
      "line": ["123 Main St", "Suite 100"],
      "city": "Springfield",
      "state": "IL",
      "postalCode": "62701"
    }
  ],
  "active": true
}

Bot Input Parameters

Parameter Required Type Description
practitionerId Yes string The ID of the FHIR Practitioner resource to enroll
practitionerRoleTypes Yes number[] Array of DoseSpot clinician role types (see below)
medicalLicenseNumbers No object[] Array of medical license numbers with state info (optional)
initIdp No boolean When true, initializes identity proofing after enrollment
initTfa No boolean When true, initializes TFA activation (requires IDP to be complete)
tfaType No string TFA type: "Mobile" (default) or "Token"

Clinician Role Types:

Value Role Description
1 Prescribing Clinician Can prescribe non-controlled and controlled medications
2 Reporting Clinician Can view and report on prescriptions; cannot prescribe
3 EPCS Coordinator Coordinates EPCS enrollment for other clinicians
4 Clinician Admin Clinic administrator; can invite and manage other users
5 Prescribing Agent Clinician Prescribes on behalf of a supervising prescriber
6 Proxy Clinician Proxy access to act on behalf of another clinician

Users that need to invite others should be added with the Clinician Admin role type (4).

Usage Examples

Step 1: Basic Enrollment

const result = await medplum.executeBot(
  { system: "https://www.medplum.com/bots", value: "dosespot-enroll-prescriber-bot" },
  {
    practitionerId: "ced6426b-ad93-4abe-8e75-1695d956e471",
    practitionerRoleTypes: [1],
  }
);
// result.doseSpotClinicianId - the DoseSpot clinician ID
// result.registrationStatus  - e.g., "Pending"

Sample output for Step 1

curl 'https://api.medplum.com/fhir/R4/Bot/YOUR_BOT_ID/$execute' \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $MY_ACCESS_TOKEN" \
  -d '{
    "practitionerId": "ced6426b-ad93-4abe-8e75-1695d956e471",
    "practitionerRoleTypes": [1]
  }'

Step 2: Prescriber Signs Legal Agreement

The prescriber must log in to the DoseSpot iFrame via the provider app and sign the required legal agreement. No bot action is needed for this step.

  1. The prescriber opens the DoseSpot iFrame in the provider app.
  2. DoseSpot presents a legal agreement on the prescriber's first login.
  3. The prescriber reviews and signs the agreement. Expected registrationStatus after this step: RegistrationSuccess

Once signed, the admin can proceed to Step 3.

Step 3: Initialize IDP

Run the bot again with initIdp: true after the prescriber has signed the legal agreement:

const result = await medplum.executeBot(
  { system: "https://www.medplum.com/bots", value: "dosespot-enroll-prescriber-bot" },
  {
    practitionerId: "ced6426b-ad93-4abe-8e75-1695d956e471",
    practitionerRoleTypes: [1],
    initIdp: true,
  }
);

// result.idpInitialized      - true if IDP was newly initialized
// result.registrationStatus  - e.g., "IDPInitializeSuccess"

Step 4: Prescriber Completes Identity Verification (IDP)

The prescriber must log in to the DoseSpot iFrame and complete the Experian identity proofing process:

  1. The prescriber opens the DoseSpot iFrame in the provider app.
  2. DoseSpot presents the identity verification (Experian) flow.
  3. The prescriber provides the required information, which may include Social Security Number, date of birth, and a credit card number.

Expected registrationStatus after this step: IDPSuccess

Once IDP is complete, the admin can proceed to Step 5.

Step 5: Initialize TFA

Run the bot again with initTfa: true after the prescriber has completed IDP:

const result = await medplum.executeBot(
  { system: "https://www.medplum.com/bots", value: "dosespot-enroll-prescriber-bot" },
  {
    practitionerId: "ced6426b-ad93-4abe-8e75-1695d956e471",
    practitionerRoleTypes: [1],
    initTfa: true,
    tfaType: "Mobile", // or "Token" for hardware token
  }
);

// result.tfaInitialized      - true if TFA was newly initialized
// result.registrationStatus  - e.g., "IDPSuccess"

Step 6: Complete TFA Setup

The prescriber must log in to the DoseSpot iFrame one final time to complete the TFA setup. Once complete, EPCS is fully enabled.

Bot Response

The bot returns the following fields:

Field Type Description
doseSpotClinicianId number The DoseSpot clinician ID
projectMembership ProjectMembership The updated ProjectMembership with DoseSpot identifier
practitioner Practitioner The updated Practitioner with registration status extension and EPCS qualification (if applicable)
registrationStatus string Current DoseSpot registration status
idpInitialized boolean Whether IDP was initialized in this run
tfaInitialized boolean Whether TFA was initialized in this run

Registration Statuses

Status Meaning Next Action
Pending Clinician created; legal agreement not yet signed Prescriber logs in to iFrame and signs agreement (Step 2)
RegistrationSuccess Legal agreement signed; IDP not yet initiated Admin runs bot with initIdp: true (Step 3)
RegistrationError Registration failed Check enrollment data and re-run the bot
IDPInitializeSuccess IDP initiated by admin; prescriber has not yet completed it Prescriber logs in to iFrame and completes identity verification (Step 4)
IDPSuccess Identity proofing complete; TFA not yet initiated Admin runs bot with initTfa: true (Step 5)
IDPError Identity proofing failed Prescriber must retry IDP in the iFrame
TFAActivateInit TFA activation initiated; prescriber has not yet completed setup Prescriber logs in to iFrame and completes TFA setup (Step 6)
TFAActivatedSuccess TFA setup complete; EPCS fully enabled No action needed — EPCS is active
TFAActivatedError TFA activation failed Re-initiate TFA (run bot with initTfa: true again)
TFADeactivateInit TFA deactivation in progress Wait for deactivation to complete before re-initiating
TFADeactivatedSuccess TFA successfully deactivated Re-initiate TFA if needed (run bot with initTfa: true)
TFADeactivatedError TFA deactivation failed Contact DoseSpot support