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:
- Be an admin in your project (
ProjectMembership.admin) - Already have access to DoseSpot (DoseSpot identifier on their ProjectMembership)
- Have a Clinician Admin role type in DoseSpot (as specified in the
practitionerRoleTypesparameter)
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)
- Admin runs the enroll bot with the prescriber's
practitionerIdandpractitionerRoleTypes - The bot creates or updates the clinician record in DoseSpot
- 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:
- Admin runs the enroll bot. The Practitioner resource must have DEA number(s) in its
identifierarray. - Prescriber logs in to the DoseSpot iFrame via the provider app and signs the required legal agreement.
- Admin runs the bot again with
initIdp: trueto initialize identity proofing. - Prescriber logs in to the DoseSpot iFrame and completes the IDP process.
- Admin runs the bot again with
initTfa: trueto initialize TFA activation. - 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.
- The prescriber opens the DoseSpot iFrame in the provider app.
- DoseSpot presents a legal agreement on the prescriber's first login.
- The prescriber reviews and signs the agreement.
Expected
registrationStatusafter 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:
- The prescriber opens the DoseSpot iFrame in the provider app.
- DoseSpot presents the identity verification (Experian) flow.
- 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 |