Skip to content

Run Record Health Check from Apex

Detailed page. Use “On this page” to jump directly to the section you need.

Use this page to run Record Health Check from Apex and read the returned results before the current transaction continues.

Use this page when implementing an Apex caller. If the process can be built in Flow, stop and use Run Record Health Check from Flow. Writing the Apex caller requires Author Apex and the organization’s normal code review, tests, and deployment process.

The rhc. before an Apex type tells Salesforce that the installed Record Health Check package owns that type. The rhc__ in a Check Set name has a different purpose: it appears when the package delivered that Custom Metadata record. Always copy the Check or Check Set Qualified API Name from Setup.

Use this Apex API when code needs health results before the current transaction can continue. For example, the Apex process can stop, choose a branch, or collect records that need follow-up.

Example: Stop account escalation when required data is missing

Section titled “Example: Stop account escalation when required data is missing”

An Apex service prepares an Account escalation and already has the Account ID. Before continuing, it runs Account Data Quality. A FAIL adds the Account to a review list; PASS allows the escalation to continue. Use this API because the Apex service needs the result immediately.

Do not use this API for an unlimited number of records. Use Queueable Apex when the work can happen later and fits in one request. Use Batch Apex when the records need several transactions.

  1. Activate and test the Check or Check Set.
  2. Assign the running user the packaged Record Health Check User Permission Set. Use Record Health Check Admin only when that user also configures Checks or views diagnostics. Both include Custom Permission label: Record Health Check Run, Custom Permission API name: rhc__Record_Health_Check_Run, and access to the package Apex classes.
  3. Confirm that the running user can access the target records, fields, and Framework Custom Metadata required by the selected Checks.
  4. In Setup, go to Custom Metadata Types → Record Health Check Set → Manage Records and copy the Check Set Qualified API Name. One included with the installed package normally begins with rhc__; one created by an administrator normally does not.
  5. Keep the request at or below 200 records and review the planned-evaluation limits for the Check Set.
  6. Decide which statuses the code must handle and whether Platform Events are required.

The running user needs Record Health Check User for the package Custom Permission and package Apex access, plus ordinary access to evaluated data. The developer needs Author Apex to create or change the caller, but Author Apex does not grant permission to run Record Health Check as an end user. A returned FAIL is business output; a returned ERROR is a health result needing operations review; an AuthorizationException means no response was returned to the caller.

Evaluate a Check Set for several records:

// Copy the exact Check Set Qualified API Name from Setup.
// A Check Set included with the installed package might be rhc__Example_Account_Check_Builder_Guide.
String checkSetApiName = 'My_Account_Checks';
// accountIds is a List<Id> collected by the Apex process that needs the result.
rhc.RecordHealthCheckRequest request = rhc.RecordHealthCheckRequest.forCheckSet(
checkSetApiName,
accountIds
).withRunId('nightly-' + System.now().formatGMT('yyyyMMdd-HHmmss-SSS'));
rhc.RecordHealthCheckResponse response = rhc.RecordHealthCheck.evaluate(request);
Set<Id> recordsNeedingAttention = new Set<Id>();
for (rhc.RecordHealthCheckResultItem item : response.results) {
if (item.evaluation.status == rhc.RecordHealthCheckStatus.FAIL) {
recordsNeedingAttention.add(item.evaluation.recordId);
}
}

The example collects business failures for the Apex process to handle. In production, pass that set to the approved notification or result-saving code for the process. Do not write record details to a debug log.

The code does four things:

  1. Selects the Check Set named by checkSetApiName.
  2. Supplies the Account IDs to check.
  3. Adds a Run ID chosen by this Apex process so administrators can connect related jobs and results.
  4. Treats FAIL as a returned business result instead of an Apex exception.

withRunId is optional. Use a value that is safe to retain and meaningful to the calling process. Record Health Check generates a Run ID when the supplied value is blank.

Step 2: Run one Check when a Check Set is unnecessary

Section titled “Step 2: Run one Check when a Check Set is unnecessary”

Evaluate one Check by its Custom Metadata QualifiedApiName:

// Copy the exact Check Qualified API Name from Setup.
// A Check included with the installed package might start with rhc__.
String checkApiName = 'My_Customer_Contact_Required';
rhc.RecordHealthCheckResponse response = rhc.RecordHealthCheck.evaluate(
rhc.RecordHealthCheckRequest.forCheck(
checkApiName,
accountId
)
);

A Check created by an administrator in your org normally does not start with rhc__. Copy the exact value from Setup → Custom Metadata Types → Record Health Check → Manage Records.

The first example collects only FAIL records to keep the code short. Production code should make an intentional decision for every status it can receive:

StatusMeaningTypical Apex action
PASSThe record met the condition.Continue.
FAILThe record did not meet the business condition.Start approved follow-up or show guidance.
SKIPPEDThe Check did not apply.Continue or report separately.
UNABLE_TO_EVALUATEAccess, data, or configuration prevented a reliable answer.Inspect reasonCode and correct the cause.
ERRORThe Framework contained an evaluator or system problem as result data.Send non-sensitive context to monitoring.

Exceptions remain a separate channel. Authorization, invalid requests, Framework failures, and fatal plugin side effects can prevent a normal response and should follow the caller’s fault or monitoring path.

rhc.RecordHealthCheckRequest requires exactly one selection and a non-null list of record IDs. The factories are:

FactorySelection
forCheckSet(qualifiedApiName, recordId)One Check Set and one record
forCheckSet(qualifiedApiName, recordIds)One Check Set and several records
forCheck(qualifiedApiName, recordId)One Check and one record
forCheck(qualifiedApiName, recordIds)One Check and several records

Options are applied with chainable methods:

MethodDefaultPurpose
withResultMode(...)EVALUATIONChoose EVALUATION, EVALUATION_WITH_DISPLAY, or SUMMARY
withEventPublication(...)NONEChoose NONE, ACTIONABLE, or ALL publication
withRunId(...)Generated when blankSupply text that connects this call with related jobs or results
withExecutionOrigin(...)APEX_APIRecord whether Apex, Batch, Queueable, Scheduled, Future, Agent, or a Record Health Check class started the work
withDiagnosticContractVersion(...)Not requestedRequest the authorized diagnostic 2.0 projection; omit it for the normal response contract

An Apex request publishes nothing unless the code explicitly selects a publication mode. Metadata fields still decide whether a requested event is enabled. Execution origin reports where the request started. It does not grant or prove access. Record Health Check Flow actions and Lightning components set their own origin automatically.

Diagnostic contract 2.0 is opt-in. The running user must also have authorized diagnostic access; requesting the version does not grant permission. Read the result with response.diagnostics(). See Authorized diagnostics.

Start with the default EVALUATION result mode and NONE publication mode. Add display data or Platform Events only when another automation has a defined use for them.

Result modes control response content:

Moderesults contentUse it when…
EVALUATIONEvery selected result with machine-readable evaluation dataCode needs every outcome without display text
EVALUATION_WITH_DISPLAYEvery selected result with evaluation and authorized display dataApex must display Record Health Check messages, values, or actions
SUMMARYCounts plus FAIL, UNABLE_TO_EVALUATE, and ERROR resultsApex needs totals and only records requiring attention

This section explains the values returned by Record Health Check.

Every call returns rhc.RecordHealthCheckResponse with:

FieldMeaning
runIdText used to connect this evaluation with related jobs or results
recordIdsRecord IDs after nulls and repeated IDs are removed
checkQualifiedApiNamesOrdered Checks selected for the run
resultsOrdered rhc.RecordHealthCheckResultItem entries
summaryFinal counts for each status; it does not contain one combined status field

Each item always has evaluation. It has display only when the request uses EVALUATION_WITH_DISPLAY. Machine values use rhc.RecordHealthCheckValue, so callers do not receive untyped Object values.

evaluation contains recordId, checkQualifiedApiName, status, severity, reasonCode, found, comparisonOperator, and expected. The summary fields are passed, failed, skipped, unable, and systemError; summary.total() returns their sum. Derive a business decision from those explicit counts rather than expecting summary.status.

found and expected identify their value type as STRING, BOOLEAN, NUMBER, DATE, DATETIME, ID, COUNT, or LIST. Use the matching typed value field instead of parsing display text.

rhc.RecordHealthCheckResponse response =
rhc.RecordHealthCheck.evaluate(request);
if (response.summary.systemError > 0 || response.summary.unable > 0) {
// Send approved, non-sensitive run information to operational monitoring.
}

The summary does not have one combined status. Read passed, failed, skipped, unable, and systemError separately so the caller does not treat a business failure as a system failure.

These are the global types used by the request and response. Most code creates only a request and reads a response. Record Health Check creates the result types inside the response.

TypeCaller responsibility
RecordHealthCheckCall evaluate(request)
RecordHealthCheckRequestSelect a Check or Check Set and the records to check
RecordHealthCheckSelectionRead the selected Check or Check Set Qualified API Name
RecordHealthCheckOptionsRead-only result, publication, Run ID, and origin choices copied by with... methods
RecordHealthCheckResultModeSelect EVALUATION, EVALUATION_WITH_DISPLAY, or SUMMARY
RecordHealthCheckEventPublicationSelect NONE, ACTIONABLE, or ALL Platform Events
RecordHealthCheckExecutionOriginAttribute monitoring output to the actual caller context
RecordHealthCheckResponseRead the Run ID, record IDs, ordered results, and summary
RecordHealthCheckResultItemRead one evaluation and its optional display data
RecordHealthCheckEvaluationResultRead machine status, reason, severity, and typed values
RecordHealthCheckResultDisplayRender authorized messages, formatted values, and action information
RecordHealthCheckAdminDetailRead authorized configuration/resolution diagnostics when present
RecordHealthCheckRunSummaryRead explicit status counts and total()
RecordHealthCheckStatusCompare results with shared status constants and isActionable(...)
RecordHealthCheckValueRead typed machine values without parsing display text

The Apex Check extension types (RecordHealthCheckPlugin, RecordHealthCheckScope, and RecordHealthCheckOutcome) are documented separately in the Apex Check contract. Background-job entry points are documented in Queueable, Batch, and Scheduled.

Understand returned results and exceptions

Section titled “Understand returned results and exceptions”
SituationWhat Apex receivesWhat to do
A record does not meet a CheckA FAIL resultHandle it as a business result. Do not treat it as an exception.
Record access, field access, data, or configuration prevents an answerAn UNABLE_TO_EVALUATE result when Record Health Check can identify the affected record or CheckRead reasonCode and correct the access, data, or configuration problem.
A Check encounters a contained evaluator problemAn ERROR resultSend approved, non-sensitive details to monitoring.
The user lacks the Record Health Check Run Custom PermissionAuthorizationExceptionAssign the required Permission Set or stop the process.
The request is invalid or Record Health Check cannot create a responseAn Apex exceptionCatch only exceptions the Apex process can recover from. Let unknown exceptions reach normal monitoring.
An Apex Check attempts a forbidden write, callout, email, event, or background jobAn exception and rolled-back transactionCorrect the Apex Check. Do not convert this failure to FAIL.

Requests do not publish Platform Events unless you enable publication. Add withEventPublication(rhc.RecordHealthCheckEventPublication.ACTIONABLE) to publish actionable results, or use ALL when an integration needs every result.

This option controls Platform Events only. It does not filter the normal Apex response. With the default EVALUATION result mode, response.results still contains PASS and every other returned status.

// Copy the exact Check Set Qualified API Name from Setup.
String checkSetApiName = 'My_Account_Checks';
rhc.RecordHealthCheckRequest request =
// Use ACTIONABLE to publish only FAIL, UNABLE_TO_EVALUATE, and ERROR.
// Use ALL to publish every result, including PASS and SKIPPED.
// Use NONE when this Apex code reads response.results directly.
rhc.RecordHealthCheckRequest.forCheckSet(
checkSetApiName,
accountIds
).withEventPublication(
rhc.RecordHealthCheckEventPublication.ACTIONABLE
);

Publishing is not the same as saving. A Flow, Apex trigger, or external integration must receive and process the Platform Events if the organization needs permanent history or follow-on action.

  • Every public execution entry point requires Custom Permission label: Record Health Check Run (API name: rhc__Record_Health_Check_Run).
  • One request accepts at most 200 records. The package keeps its internal implementation value private; code in an org where the package is installed must use 200 as the supported limit.
  • Query, compare-query, and conforming Apex Checks run once for all records in the request.
  • Formula Checks use one platform Formula evaluation per expression and record, so the request may need fewer records.
  • Record and query access runs in user mode. Apex Checks created in the org must enforce their own user-mode access and should extend rhc.RecordHealthCheckContractTest.
  • MaxQueryRows__c limits query rows for one request.

Test with representative records and the effective access used in production. Include:

  • one PASS and one business FAIL;
  • SKIPPED when the Check can be inapplicable;
  • an UNABLE_TO_EVALUATE access or configuration case;
  • contained ERROR handling;
  • an invalid request or unauthorized caller that throws; and
  • Platform Event behavior when publication is enabled.

Assert machine-readable status, reason code, and typed values. Do not make business logic depend on formatted display text.

SymptomCheck first
AuthorizationException is thrownThe running user’s Record Health Check Run Custom Permission and Apex class access
No Check is selectedThe qualified API name, including the package prefix returned by Salesforce
A record returns UNABLE_TO_EVALUATEreasonCode, record visibility, field access, and Check configuration
The response has no display textUse EVALUATION_WITH_DISPLAY and confirm the user is authorized for that display data
No Platform Event appearsRequest publication mode, Check metadata event setting, and the Flow, Apex trigger, or integration that should receive it
A request over 200 records failsSplit the records or use Batch Apex