Skip to main content

CredentialingWorkflow

APIs for managing credentialing workflows

📄️List credentialing workflows by filter criteria

Returns a paginated list of credentialing workflows that match the supplied filter criteria. Use this endpoint to search and browse workflows across practitioners; for facility-scoped workflows use the facility-specific endpoint instead. Requires a valid JWT with the appropriate workflow read permission. Supports offset-based pagination (`page`, default 0; `size`, default 50); Pass the `X-PII-View` header to include unmasked PII fields in the response. When `skipEnrichment` is true, DAL enrichment and verifiedBy user lookups are skipped and those fields will be absent from each workflow object. Returns an empty list (not 404) when no workflows match. Query params (filter, page default 0, size default 50, cursors, order, skipEnrichment) are forwarded to the DAL. The tenant-id header is forced into the filter and any client filter.tenantId is stripped. Max size is not validated in api-layer. Optional default-sort behavior may rewrite blank or malformed order when enabled.

📄️Create a single credentialing workflow for a practitioner

Creates a new credentialing workflow for a practitioner and returns the created object with a server-assigned `id` and initial status. Use this endpoint for single-practitioner workflow creation; use `POST /credentialing-workflows/bulk-create` or `POST /credentialing-workflows/v2/bulk-create` for batch operations. The practitioner identified in the request body must already exist in the system. Returns 409 if an active workflow already exists for the same practitioner and tenant.

📄️Assign multiple workflows to users via round-robin distribution

Creates user assignments for multiple credentialing workflows in a single synchronous operation. Workflows in the request are distributed evenly across the provided user IDs using round-robin assignment. Each workflow is processed independently: the response body contains both a `successful` array and a `failed` array so callers can identify any workflows that could not be assigned without needing to retry the entire batch. Returns 400 if the request body is invalid.

📄️Asynchronously create workflows for multiple practitioners (v1)

Accepts a list of practitioners and asynchronously creates a credentialing workflow for each one. The request returns 202 immediately; creation for each practitioner runs in the background and is independent — a failure for one practitioner does not block others. Results are logged server-side but are not returned in the response body and there is no polling endpoint to check completion status. Use `POST /credentialing-workflows/v2/bulk-create` for a Cloud Tasks–backed version with a trackable bulk request record.

📄️Internal Cloud Tasks callback — create one workflow in bulk job

Internal callback endpoint invoked by Google Cloud Tasks as part of the v2 bulk-create flow. Creates a single credentialing workflow for one practitioner and updates the corresponding bulk request item status on completion. This endpoint is not intended for direct client use — authenticate with the `X-Credentialing-Api-Key` header; JWT authentication is not used. Required body fields: `certifyPractitionerId`, `tenantPractitionerId`, `credentialingWorkflowBulkRequestId`, `credentialingWorkflowBulkRequestItemId`. Optional: `data` object containing the workflow creation payload; `skipAnchorGroupComputation` boolean (default false), true when the bulk request asked to skip the creation-time Anchor Group computation.

📄️Data pipeline callback

Receives callback from DI team after MDM Orchestration completes. Marks workflow data-pipeline status and syncs practitioner OV sections. The pipeline is identified by the referenced data pipeline request's pipelineName (CAQH, NPDB or LICENSE), not by the request body. The referenced request must already carry a CROSSWALK_INGESTION step in SUCCESS or ERROR status. CAQH and NPDB callbacks sync while the workflow is in any editable status; LICENSE (ODDP state license) callbacks sync only while the workflow is still NOT_STARTED and otherwise return 200 with status 'skipped' and the skip reason.

📄️Run a Death Master File check for a practitioner

Calls the downstream Death Master File (DMF) deceased-provider check service with the supplied SSN and date of birth. Use this endpoint to verify that the DMF integration is reachable and functioning; it is intended primarily as a diagnostic or administrative tool rather than a routine production call. Both `ssn` (9-digit string) and `dateOfBirth` (format `yyyy-MM-dd`) are required. Returns the raw DMF check result on 200. Returns 502 when the downstream DMF service is unavailable or returns an error.

📄️Send an event-agnostic notification email for multiple workflows

Sends the requested event email (e.g. CRED_APPROVED) for multiple credentialing workflows in a single operation, WITHOUT writing a timeline event — no status mutation, no webhook/PSV trigger. Each workflow is processed independently — a failure for one does not block others — and the response includes both `successful` and `failed` arrays. Optionally accepts `templateDataOverrides` (merged over the computed template-variable map, override wins on conflict), `subjectOverride` (replaces the tenant-configured subject when non-blank), and `bodyHtmlOverride` (replaces the tenant-configured body when non-blank; placeholders inside it still substitute from the, possibly overridden, template-variable map). All three are optional — omitting them preserves the tenant-configured email exactly. Overrides replace template CONTENT only: they do NOT bypass the per-tenant enabled check or the recipient-email resolution, so a disabled event type or a workflow with no recipient still reports as successful without sending, even when overrides are supplied.

📄️Replay credential_workflow.status.changed webhooks for given workflows

Accepts a list of workflow IDs and asynchronously replays `credential_workflow.status.changed` webhook events for each one. Returns 202 immediately; replay runs in the background. Each workflow is fetched and routed through the same webhook dispatch path used during normal status changes, so downstream subscribers receive the same payload they would have received during the original status change. Progress is logged server-side with the `[webhook-replay]` prefix. There is no polling endpoint to track completion.

📄️Change the status of multiple workflows in one request

Creates timeline events for multiple credentialing workflows in a single operation, effectively changing the status of each workflow. Each workflow is processed independently — a failure for one does not block others — and the response includes both `successful` and `failed` arrays. Use this endpoint for batch status transitions; to change the status of a single workflow use `POST /credentialing-workflows/{workflowId}/timeline-events`.

📄️Queue bulk workflow creation via Cloud Tasks with tracking (v2)

Accepts a bulk workflow creation request, writes a tracking record to the database, and enqueues one Cloud Tasks task per practitioner for reliable, independent processing. Returns 202 immediately with the bulk request tracking ID. Poll the tracking record or check individual workflow creation results using the tracking ID. Each task calls `POST /credentialing-workflows/cloud-create` internally. Use this endpoint in preference to the v1 `/bulk-create` when you need per-item status tracking or retry guarantees via Cloud Tasks.

📄️Replace an entire credentialing workflow record (deprecated)

DEPRECATED — this endpoint is marked deprecated in the source and will be removed in a future version. Prefer the targeted section endpoints (e.g. `PUT /credentialing-workflows/{workflowId}/addresses`) to update specific parts of a workflow without overwriting unrelated fields. Performs a full replacement of the credentialing workflow identified by `id`. The request body must contain the complete desired state of the workflow; any fields omitted from the body will be cleared. This operation is not idempotent if server-generated fields (e.g. `updatedAt`) differ between calls.

📄️Retrieve a single credentialing workflow by ID

Returns the full credentialing workflow record for the given `id`, including enriched practitioner data and sanction type display mappings. Use this endpoint when you need the complete state of one workflow; use `GET /credentialing-workflows` for search/list operations. Pass `X-PII-View: true` to include unmasked PII fields in the response. When `skipEnrichment` is true, DAL enrichment and verifiedBy user lookups are skipped and those fields will be absent from the response. Returns 404 if no workflow with the given `id` exists within the caller's tenant scope.

📄️Recompute and persist the Application Complete Date for a workflow (CP-33550)

Manually re-runs the canonical Application Complete Date computation (ApplicationCompleteDateService) against the given workflow, for the specified transition, and persists the result via the DAL PATCH. Wraps the existing service; adds no new business logic. Intended for the CP-33550 NM MCO backfill script. Feature-flagged via api-layer.credentialing-workflow.acd-recompute-backfill.enabled (default false → 503).

📄️Generate and store a Board Certification PDF for a workflow

Generates a Board Certification PDF document from the board certification data on the credentialing workflow identified by `id` and stores it in cloud storage. Authenticate with the X-Credentialing-Api-Key header (API key), not JWT — typically invoked from Cloud Tasks. Returns 200 with the PDF storage URL when generation succeeds. Returns 204 with no body when there are no board certifications on the workflow to generate a PDF from, or when the analyst deleted the generated document.

📄️Generate and store an NPDB report PDF for a workflow

Generates a PDF from the NPDB (National Practitioner Data Bank) report data on the credentialing workflow identified by `id` and stores it in cloud storage. Authenticate with the X-Credentialing-Api-Key header (API key), not JWT — typically invoked from Cloud Tasks. Returns 200 with the PDF storage URL when generation succeeds. Returns 204 with no body when no NPDB PDF URL is available or when the analyst deleted the generated document.

📄️Generate a Provider Summary Verification document for a workflow

Generates a Provider Summary Verification (PSV) document for the credentialing workflow identified by `id` and stores it in cloud storage. Use this endpoint to produce or refresh the PSV; use `GET /credentialing-workflows/{id}/latest-psv-pdf` to retrieve the path of the most recently generated PSV without regenerating it. This endpoint is authenticated via API key (not JWT) when invoked from Cloud Tasks. The optional `triggeringEventId` parameter associates the generation with a specific timeline event for step-tracking purposes; omit it for direct invocations. Returns a `GeneratePsvResponse` object containing the URL of the generated PSV document.

📄️Generate PDFs for all sanction types on a workflow

Generates sanction PDF documents for every sanction type present on the credentialing workflow identified by `id` and stores each in cloud storage. Authenticate with the X-Credentialing-Api-Key header (API key), not JWT — typically invoked from Cloud Tasks. Returns 200 with a `GenerateAllSanctionsPdfResponse` object containing the generated PDF URLs. Returns 204 with no body when no sanctions are found on the workflow. Returns 503 when some sanction PDFs failed and Cloud Tasks attempts remain; the PDFs that succeeded are already saved and the retry generates the rest.

📄️Retrieve the path of the latest PSV PDF for a workflow

Returns the storage path of the most recently generated Provider Summary Verification (PSV) PDF for the credentialing workflow identified by `id`, without triggering a new generation. Use `POST /credentialing-workflows/{id}/generate-psv` to generate a new PSV. Returns 200 with `{workflowId, psvPdfPath}` when a completed PSV PDF is available. Returns 202 with `{workflowId, status: 'GENERATING'}` when a PSV generation is currently in progress for the latest status transition — poll this endpoint again after a delay. Returns 404 when no PSV PDF has ever been generated for this workflow; call `generate-psv` to create one.

📄️Get the latest PSV PDF data

Returns the data the most recent Provider Summary Verification (PSV) PDF of the credentialing workflow was rendered from, exactly as stored when the PDF was generated, without regenerating it. No signed links: file paths (`psvPdfPath`, every `fileUrl` in `payload`, `mergedDocuments[].path`) are stored paths. Signed links for them come from GET `/credentialing-workflows/{id}/psv-pdf-data/{snapshotId}/signed-urls` with the response's `snapshotId`, matched by path. Returns 202 with `{workflowId, status: 'GENERATING'}` while a PSV PDF is being generated. Returns 404 with `code` `PSV_PDF_NOT_FOUND` when no PSV PDF exists, or `PSV_PDF_DATA_NOT_AVAILABLE` when the latest PSV PDF has no stored data (for example, it was generated before this endpoint existed): the PSV PDF must be regenerated, then call again. Data from an older PDF is never returned. `payload` holds only what the PDF prints: the paths the PSV template reads, the files merged into the PDF (`fileUrl`, `fileType`, `originalFileName`) and `organizationName` (the tenant's name). Any other field is left out. Returns 503 `PSV_PDF_DATA_UNAVAILABLE` where PSV PDF data is not stored.

📄️Get a presigned download URL for the workflow's latest PSV PDF

Returns a tenant-scoped, server-resolved presigned download URL (valid for 1 hour) for the most recently generated Provider Summary Verification (PSV) PDF for the credentialing workflow identified by `id`. The storage path is always resolved server-side from the workflow's timeline events and never accepted from the client (no query parameters are supported). Returns 200 with a `PsvPdfDownloadResponse` when a completed PSV PDF is available. Returns 202 with `{workflowId, status: 'GENERATING'}` when a PSV generation is currently in progress — poll this endpoint again after a delay. Returns 404 when no PSV PDF has ever been generated for this workflow, or when the workflow does not belong to the requesting tenant.

📄️Get signed download links for a PSV PDF snapshot

Signs every file of one stored PSV PDF snapshot, by the `snapshotId` the latest-psv-pdf-data response returns, without returning its data: the PSV PDF, each supporting document and section attachment once per `path`, and the documents merged into the PDF. Match the links to the payload by `path`. Every link expires at `signedUrlExpiresAt`; call again for new ones. Any snapshot of the workflow can be refreshed; `latest` is false when the workflow has a newer PSV PDF, then get its data from latest-psv-pdf-data. A file that cannot be signed has no link and is listed in `errors`. Returns 404 with `code` `PSV_PDF_DATA_NOT_FOUND` when no snapshot with that id belongs to the workflow. Returns 503 `PSV_PDF_DATA_UNAVAILABLE` where PSV PDF data is not stored.

📄️Bulk-delete application-verification records from a credentialing workflow

Deletes multiple appVerifications records in one action. Each recordId uses the '{section}-{index}' format (e.g. 'appVerifications-3'); section must be appVerifications. Deletion is a single read-modify-write and archives each removed record into deletedData.practitioner.appVerifications (CP-37047), matching single-record delete behaviour for this section; appVerifications keeps its own endpoint because its request DTO differs from the generic section bulk-delete. Partial failures (malformed, wrong section, out-of-bounds, duplicate recordIds) are reported per record and do not block the valid deletions. NOTE: recordIds are positional, so this request must not be retried automatically — a replay after a successful-but-unseen response would delete whatever records shifted into those indices. The removed records are kept in deletedData, but there is no restore endpoint and they stay removed from the live section. Re-fetch the section and rebuild recordIds before any retry.

📄️Read the Clean / Non-Clean verdict and its reasons

Returns the file-type verdict of the credentialing workflow identified by `workflowId` as a typed view: the displayed verdict (the analyst's value in force, else the derived one; PENDING before PSV Complete), whether it is frozen and why, the platform findings with their `ruleKey` and whether each is hidden from the packet, the newest analyst change, the verdict derived at PSV Complete, and `evaluation` (DERIVED, NOT_EVALUATED for Couldn't evaluate, or null). The same shape as `fileType` on the shared members read. Works for standalone workflows and a shared member's own tenant page. Answers 404 when PSV transparency is not switched on for the tenant.

📄️Change the Clean / Non-Clean verdict or hide its reasons

Sets the analyst's File Type on the credentialing workflow identified by `workflowId`, and/or which of its findings are hidden from the PSV packet, while the workflow is at PSV Complete and its verdict is not frozen. The same change as the shared page's member File Type route, for a workflow whose tenant has PSV transparency switched on. `hiddenFindingRuleKeys` is the full set of findings to hide; without `fileType` the save is hide-only: it writes no analyst File Type, so the verdict stays the platform's, and needs no reason. A Non-Clean change always needs a reason; a Clean change needs one while a finding stays unhidden; either needs one when the verdict could not be evaluated or there is none. Repeating the newest analyst change with the same hides is a 204 that writes nothing. A written change asks for the PSV packet to be regenerated. Answers 404 when PSV transparency is not switched on.

📄️Retry the file-type verdict that could not be evaluated

Evaluates the clean / non-clean rules again for the workflow identified by `workflowId` when its file-type verdict could not be evaluated, and stores the result. Synchronous: bounded by the rule-engine timeout plus a read and a write. The workflow must be at PSV Complete with a verdict that is not frozen. A verdict that is already derived answers DERIVED without calling the rules engine; a workflow at PSV Complete with no verdict yet is evaluated. Re-read the workflow for the value.

📄️Create a PSV_COMPLETED override timeline event for a workflow

Creates an override timeline event for the credentialing workflow identified by `workflowId`. Only events of type `PSV_COMPLETED` may be overridden, except that a shared member whose tenant has PSV transparency switched on may also be moved to `PSV_READY`, `SENT_TO_COMMITTEE` or `CRED_APPROVED` past its open PSV blockers. The request body must include `isOverride: true` and a non-empty `overrideReason`; omitting either field will result in a validation error. A different (elevated) permission is required for this endpoint compared to the standard `POST /{workflowId}/timeline-events`. Returns 409 if the workflow is not the latest version for this practitioner — resolve by operating on the most recent workflow record.

📄️List pipeline runs for a credentialing workflow

Returns a paginated list of pipeline runs associated with the credentialing workflow identified by `workflowId`. Requires JWT permission `CREDENTIALING_WORKFLOW_PIPELINE_TRIGGER`. A pipeline run represents a single execution of an automated data verification or enrichment pipeline (e.g. NPDB query) against the workflow. Supports optional `filter` (JSON object with field/operator pairs, e.g. `{'createdAt':{'gte':'2023-01-01T00:00:00Z'}}`), `order` (JSON object, e.g. `{'createdAt':'desc'}`), and offset-based `page`/`size` pagination. Set `includeSteps` to `true` to embed individual pipeline step detail in each run object.

📄️Check which NPDB-required practitioner fields are present

Validates that all practitioner fields required by the tenant's NPDB pipeline configuration are present and non-empty on the workflow identified by `workflowId`. Requires JWT permission `CREDENTIALING_WORKFLOW_PIPELINE_TRIGGER`. Returns the validation result without triggering the pipeline — use this endpoint before calling `POST /pipeline-runs` to confirm the workflow is ready. The set of required fields is tenant-configured. Returns 200 with a `NpdbRequiredFieldsCheckResponse` indicating which fields pass and which are missing. Returns 400 if the workflow is missing a linked practitioner.

📄️Read the workflow's PSV progression and open blockers

Evaluates the PSV rules of the credentialing workflow identified by `workflowId` once and answers READY or BLOCKED with every failed rule, each with its `coverKey`. A rule already acknowledged by an earlier move in the current PSV stretch reads `covered` and does not block. The same logic and shape as the shared page's member progression read. The standalone tenant page's Withdraw / Cancel prompt lists the uncovered items before PSV Complete and sends the chosen `coverKey`s back as `hiddenCoverKeys` on `POST /{workflowId}/timeline-events`. Writes nothing. Answers 404 when PSV transparency is not switched on for the tenant.

📄️Replace all supporting documents on a credentialing workflow

Replaces the entire supporting documents array on the credentialing workflow identified by `workflowId` with the provided list (full-replacement PUT semantics). Any document currently on the workflow that is not included in the request will be removed from the workflow record. Send an empty array (`[]`) to remove all supporting documents. To add a single new document without affecting existing ones, use `POST /credentialing-workflows/{workflowId}/supporting-documents`.

📄️Bulk-delete supporting-document records from a credentialing workflow

Deletes multiple supporting-document records in one action. Each recordId uses the '{section}-{index}' format (e.g. 'supportingDocuments-3'); section must be supportingDocuments. Deletion is a single read-modify-write and hard-deletes the records (no tombstone), matching single-record delete behaviour. Partial failures (malformed, wrong section, out-of-bounds, duplicate recordIds) are reported per record and do not block the valid deletions.

📄️List timeline events for a credentialing workflow

Returns a paginated list of timeline events for the credentialing workflow identified by `workflowId`. Timeline events represent status transitions and key milestones in a workflow's credentialing lifecycle (e.g. `IN_PROGRESS`, `CRED_APPROVED`). Supports optional `filter`, `order`, and offset-based `page`/`size` pagination. Use `GET /credentialing-workflows/{workflowId}/timeline-events/status-options` to discover which status transitions are valid before creating a new event. Filter values must be string maps only; in and nin filter forms from older docs are dropped by the api-layer parser and have no effect. Path workflowId is auto-added to the filter.

📄️Record a status transition event for a credentialing workflow

Creates a new timeline event (status transition) for the credentialing workflow identified by `workflowId`. This is the primary mechanism for advancing a workflow through its credentialing lifecycle. Call `GET /credentialing-workflows/{workflowId}/timeline-events/status-options` first to retrieve the set of valid `name` values (status transitions) available to the current user. Only works on the latest workflow version for a practitioner — returns 409 if a newer version exists. Creating certain events (e.g. triggering PSV generation) may cause asynchronous side effects. To override a completed PSV event, use `POST /credentialing-workflows/{workflowId}/override-timeline-events`.

📄️Undo the most recent timeline event on a workflow

Deletes the most recent timeline event (by creation date) for the credentialing workflow identified by `workflowId` and returns the deleted event object. Use this to reverse an incorrectly applied status transition. Only works on the latest workflow version for a practitioner. Cannot delete events of type `CRED_APPROVED` or `CRED_DENIED` because their side effects (e.g. downstream notifications) cannot be reversed. Note: there is a small race window — if another timeline event is created concurrently between the fetch and the delete, the previously-latest event will be deleted instead of the one you intended.

📄️Discover valid status transitions for a workflow

Returns the timeline event status options available to the current user for the credentialing workflow identified by `workflowId`. Results are filtered by the caller's permissions — only transitions the caller is authorized to create are returned. Call this endpoint before `POST /credentialing-workflows/{workflowId}/timeline-events` to determine which `name` values are valid and which additional parameters each transition requires. Returns a `StatusOptionsResponse` object.

📄️Update credentialing date fields on a CRED_APPROVED timeline event

Partially updates the timeline event identified by `eventId` and its associated workflow in a single atomic transaction. Only applicable to events of type `CRED_APPROVED`. Supports updates to the following fields: `nextCredentialingDate` (ISO-8601 date), `nextCredentialingDateSource` (origin of the date value), `changeReason` (free-text explanation for the date change), and `nextCredentialingDateChangeLog` (a free-text log entry for date change history). Both the timeline event and the workflow record are updated atomically — either both succeed or neither is changed.

📄️Add a record to a named section of a credentialing workflow

Creates a new record in the specified `sectionName` of the credentialing workflow identified by `workflowId`. Supported sections: `appVerifications`, `boardCertifications`, `cds`, `dea`, `educationTraining`, `hospitalAffiliations`, `licenses`, `licensureActions`, `malpracticeInsurance`, `npdbReports`, `performanceIndicators`, `practiceLocations`, `professionalIds`, `sanctions`, `siteVisits`, `specialties`, `supportingDocuments`. The request body schema varies by section — refer to the schema definition for the target section to determine required and optional fields.

📄️Bulk-delete records from one credentialing workflow section

Deletes multiple records from a single section in one action (CP-36357, CP-37276). The supported sections are enumerated on the sectionName parameter; any other section is rejected with 400. Each recordId uses the '{section}-{index}' format (e.g. 'practiceLocations-3') and its section must match the sectionName path parameter, so a request can never delete outside the section it targets. Deletion is a single read-modify-write and soft-deletes the records: each removed record is archived into deletedData with the supplied intent/reason/reasonText, exactly as the single-record delete does. Partial failures (malformed, wrong section, out-of-bounds recordIds) are reported per record and do not block the valid deletions. NOTE: recordIds are positional, so this request must not be retried automatically — a replay after a successful-but-unseen response would delete whatever records shifted into those indices. Re-fetch the section and rebuild recordIds before any retry.