ChartHeroAI

DocsDeveloper Docs

Encounter workflows

Checklist Recommendations

Implement the encounter checklist recommendations endpoint ChartHero calls for partner-recommended preparation items.

v1.0

Checklist recommendations let ChartHero ask your adapter for encounter-specific preparation items that can be shown in the ChartHero encounter checklist. Use this adapter endpoint when your system has care gaps, visit-preparation tasks, risk prompts, quality measure reminders, or other workflow signals that should be considered during a specific ChartHero encounter.

This is a partner-implemented endpoint. ChartHero calls your server, sends the ChartHero patient, encounter, and authenticated actor context, and expects an ordered recommendation payload in return.

At a glance

Field Value
Method POST
Path {base_url}/v1/checklist-recommendations/fetch
Auth Authorization: <configured_authorization_header_value> (for example Bearer <token> or ApiKey <token>)
Contract version X-ChartHero-Contract-Version: 1.0
Timeouts 2 seconds to connect; 5 seconds for read/write
Retries Up to 2 total attempts; the second attempt is immediate
Max response 1 MiB
Availability Conditional: checklist_recommendations capability plus runtime workflow gating

On this page:

Endpoint

Text
POST {base_url}/v1/checklist-recommendations/fetch

base_url is the adapter base URL configured in ChartHero setup. If your service is mounted under a prefix such as /integrations/charthero, include that prefix in the configured base URL.

The /v1 path segment is the adapter endpoint namespace. The X-ChartHero-Contract-Version header is the request and response schema version for that namespace. These usually move independently: a future compatible contract update can use the same /v1 path with a newer contract-version header, while a future /v2 path would represent a larger endpoint-family change. Validate the header against the contract versions your adapter supports.

Call behavior

Treat this endpoint as a synchronous, idempotent read. ChartHero is asking for the current recommendations for one ChartHero encounter, not starting a long-running import job or asking your system to mutate state.

The request is scoped to one patient, one encounter, and one authenticated ChartHero actor. Return only recommendations that are valid for that exact context.

ChartHero validates the full response body. Unknown fields, missing required arrays, unsupported item types, malformed timestamps, or invalid enum values make the response unusable. Prefer returning fewer well-formed recommendations over a large payload with partially valid records.

Constraint Behavior
Availability ChartHero calls this endpoint only for adapter installations where the checklist_recommendations capability is enabled and the runtime workflow asks for partner checklist recommendations.
Timeout ChartHero allows 2 seconds to connect and 5 seconds for the request read/write operation.
Retries ChartHero can make up to 2 total attempts. The second attempt is immediate; ChartHero does not currently use Retry-After to delay it.
Retry triggers ChartHero retries transport timeouts, transport errors, and standard JSON error responses classified as retryable. See the Errors table for partner error cases.
Response format Return Content-Type: application/json with UTF-8 encoded JSON.
Response size Responses larger than 1 MiB are not accepted. There are no separate published item, block, or task count caps.

New conversation-derived task creation is off by default. In the default live checklist mode, ChartHero can update existing tasks but does not create new conversation-derived tasks. Installations that enable conversation task generation may create additional non-workflow tasks or blocks, but workflow blocks remain structurally protected.

Request

ChartHero sends these headers with the request:

Header Required Meaning
Authorization Yes The external_api credential configured for the adapter, sent verbatim — for example Bearer <token>, ApiKey <token>, or a bare token.
X-ChartHero-Contract-Version Yes Adapter contract version. For this contract, expect 1.0.
X-ChartHero-Request-Id Yes Opaque request identifier for logs and support correlation.
Content-Type Yes application/json.

NOTE: encounter is ChartHero's visit context. Your source system may call the same record an appointment, visit, encounter, or activity; the appointment_not_found error code is explained in Errors.

JSON
{
  "patient": {
    "id": "22222222-2222-4222-8222-222222222222",
    "external_ids": [
      {
        "source": "acme_care_prod",
        "type": "patient_id",
        "value": "pat-123"
      }
    ]
  },
  "encounter": {
    "id": "encounter-1",
    "external_ids": [
      {
        "source": "acme_care_prod",
        "type": "encounter_id",
        "value": "encounter-1"
      }
    ]
  },
  "actor": {
    "actor_type": "user",
    "actor_id": "11111111-1111-4111-8111-111111111111",
    "email": "clinician@example.com",
    "display_name": "Dr. Chris Smith",
    "first_name": "Chris",
    "last_name": "Smith",
    "specialty": "Cardiology",
    "governance_role": "member",
    "functional_roles": ["provider"],
    "active": true,
    "external_ids": [
      {
        "source": "provider_acme_care_prod",
        "type": "provider_id",
        "value": "prov-456"
      }
    ]
  }
}

Request rules:

  1. patient, encounter, and actor are required.
  2. patient.id, encounter.id, and actor.actor_id are ChartHero identifiers for correlation and support. Use external_ids[] for source-system lookup when your system needs partner-owned identifiers.
  3. external_ids[] may be empty. When present, each identifier uses {source,type,value} and must match the identifier sources configured for the adapter installation.
  4. Patient, encounter, and actor/provider identifier sources are configured independently. For example, patient and encounter IDs might use acme_care_prod, while provider IDs use provider_acme_care_prod.
  5. encounter.external_ids[] carries the upstream visit, appointment, encounter, or activity identifier when one is available.
  6. In disabled or optional provider-linking modes, actor.external_ids[] may be empty.
  7. Use the request context for authorization. Do not return recommendations for a different patient, encounter, or actor than the one ChartHero sent.

NOTE: In required provider-linking mode, ChartHero fails closed before this endpoint is called when no valid provider link is available.

Actor field guarantees:

Actor field Required Meaning
actor_type Yes Actor discriminator. Checklist recommendation requests currently send user.
actor_id Yes Stable ChartHero public actor identifier.
active Yes Whether the user actor is active in the ChartHero organization.
external_ids No Partner provider identifiers when provider linking exists. This may be empty.
email, display_name, first_name, last_name, specialty No Human-readable ChartHero user context when available.
governance_role No ChartHero organization governance role when available.
functional_roles No ChartHero organization role tokens when available. This may be empty.

Security considerations

Authorize each request against the exact patient, encounter, and actor ChartHero sent. Do not return recommendations for any other subject or actor.

WARNING: Do not log authorization header values, raw source payloads, unrelated clinical records, credentials, transcripts, or bulk checklist content.

WARNING: Do not put secrets, credentials, unrelated records, raw transcripts, or bulk clinical payloads in source_metadata or provenance.source_data.

Recommendation shape

The response hierarchy is intentionally narrow:

Text
items[]
  recommendation_set
    blocks[]
      tasks[]
        subtasks[]

Each entry in items[] is a tagged union: type names the variant, and the identically named sibling object holds that variant's payload. The only published item variant is currently recommendation_set.

Use a recommendation set when several tasks were produced by the same upstream quality run, care-management engine, or partner workflow. Use blocks to group tasks the way a clinician should review them, such as diabetes review, annual wellness visit preparation, medication reconciliation, or administrative follow-up.

ChartHero ingests items[], blocks[], tasks[], and subtasks[] in the order you send them. Workflow blocks receive stronger structural protection after ingestion, while task groups are less-coupled groupings that ChartHero may reorganize as the checklist evolves.

Choosing a block type

Use type: "workflow" when the block represents a stable partner-authored unit of work. A workflow is treated as an ordered collection: ChartHero preserves the workflow task order, tracks workflow-level status and provenance, and does not insert unrelated tasks into the workflow block during checklist updates.

A workflow is not a sequential gate. ChartHero does not require the clinician to finish task 1 before task 2, and task status can change in the order the encounter actually unfolds. The ordering tells ChartHero and downstream systems how the partner intended the work to be reviewed.

Use type: "task_group" when the tasks are related but can stand on their own. Task groups are less-coupled display groupings for agenda items, checks, discussion topics, or follow-up work. ChartHero may prioritize, regroup, or separate non-workflow tasks as the checklist evolves.

Block type When to use it
workflow The tasks belong to a stable ordered process, such as annual wellness visit preparation, medication reconciliation, or a partner care-gap review that should remain intact.
task_group The tasks are related suggestions, reminders, or agenda items that can be reviewed independently or reorganized by ChartHero.

Use subtasks for granular checks inside a parent task. Do not use subtasks as a second independent recommendation list. If a child item can stand alone, make it a task.

Success response

Return 200 with items. Use an empty array when there is nothing to show.

No recommendations:

JSON
{
  "items": []
}

A simple task group:

JSON
{
  "items": [
    {
      "type": "recommendation_set",
      "recommendation_set": {
        "title": "Visit Preparation Suggestions",
        "blocks": [
          {
            "type": "task_group",
            "title": "Related Recommendations",
            "tasks": [
              {
                "title": "Discuss eye exam"
              }
            ]
          }
        ]
      }
    }
  ]
}

A workflow with provenance:

JSON
{
  "items": [
    {
      "type": "recommendation_set",
      "recommendation_set": {
        "title": "ACO Pre-Visit Plan",
        "generated_at": "2026-06-30T14:00:00Z",
        "blocks": [
          {
            "type": "workflow",
            "title": "Diabetes Review",
            "description": "Review open diabetes care gaps.",
            "tasks": [
              {
                "title": "Address A1c gap",
                "note": "Most recent A1c is outside the measure window.",
                "rationale": "Open care gap from the partner quality engine.",
                "category": "HEDIS",
                "task_type": "CARE_GAP",
                "priority": "HIGH",
                "requires_action": true,
                "subtasks": [
                  {
                    "title": "Order A1c if clinically appropriate",
                    "kind": "check"
                  }
                ],
                "provenance": {
                  "type": "STANDARD",
                  "source_id": "gap-123",
                  "source_system": "OTHER",
                  "source_type": "CARE_GAP",
                  "captured_at": "2026-06-30T13:00:00Z",
                  "source_data": {
                    "format": "json",
                    "payload": {
                      "measure": "A1C_TESTING",
                      "source_record_id": "gap-123"
                    }
                  }
                },
                "source_metadata": {
                  "source_url": "https://partner.example/gaps/gap-123"
                }
              }
            ]
          }
        ],
        "source_metadata": {
          "run_id": "quality-run-789"
        }
      }
    }
  ]
}

Field reference

Required fields

Fields not listed as required are optional unless noted. Arrays are required when listed as required, but they may be empty unless the table says otherwise. On tasks and subtasks, only title is required; provenance, priority, requires_action, category, task_type, note, and rationale are optional.

Object Required fields Optional fields
Response items None
Item type, recommendation_set None
Recommendation set title, blocks generated_at, provenance, source_metadata
Block type, title, tasks description, provenance, source_metadata
Task title note, rationale, task_type, kind, priority, requires_action, category, subtasks, provenance, source_metadata
Subtask title note, rationale, task_type, kind, priority, requires_action, provenance, source_metadata
Provenance source_id, source_system, source_type, captured_at type, source_data
Source data format, payload None

provenance itself is optional at every recommendation level. When you include it, source_id, source_system, source_type, and captured_at are required.

Defaults

Field Default
provenance.type STANDARD
task.kind, subtask.kind task
task.requires_action, subtask.requires_action false
task.subtasks []

Field length limits

Field Limit
source_id 500 characters
title 200 characters
description, note, rationale 2,000 characters

Allowed values

Enum casing is significant. Send the exact casing shown below: response shape discriminators such as recommendation_set, workflow, task_group, task, and check are lowercase, while clinical classification fields such as priority, task_type, category, and provenance.type use uppercase values.

Field Allowed values
item.type recommendation_set
block.type workflow, task_group
actor.actor_type user
actor.governance_role owner, admin, manager, member
actor.functional_roles[] Adapter-visible role tokens. provider is common, but this is not a closed enum.
task.kind, subtask.kind task, check
task.priority, subtask.priority URGENT, HIGH, MEDIUM, LOW
task.task_type, subtask.task_type CARE_GAP, PREVENTIVE, CHRONIC, ACUTE, DIAGNOSTIC, MEDICATION, REFERRAL, COUNSELING, ADMINISTRATIVE, OTHER
task.category AWV, HEDIS, RAF_HCC, CHRONIC_CONDITIONS, PREVENTIVE, ACUTE, CARE_COORDINATION, ADMINISTRATIVE
provenance.type STANDARD
provenance.source_system CHARTHERO_USPSTF, CHARTHERO_HEDIS, CHARTHERO_AWV, CHARTHERO_TEMPLATE, ARCADIA, EPIC, CERNER, ATHENA, OTHER
provenance.source_type USPSTF_RECOMMENDATION, HEDIS_MEASURE, CMS_AWV, CARE_GAP, EHR_ALERT, MANUAL_ENTRY, AI_DETECTED, WORKFLOW_TEMPLATE
provenance.source_data.format json, text

provenance.type currently allows only STANDARD; the field is reserved for future provenance variants.

For source_data, use format: "json" when payload is a structured JSON value such as an object or array. Use format: "text" when payload is a short human-readable string.

Provenance Identity

Use provenance when a recommendation item corresponds to a stable upstream source object. source_id, source_system, and source_type describe that upstream origin. Recommendation import/dedupe behavior is not part of this v1 endpoint contract.

Metadata and provenance

Provenance tells ChartHero and the clinician why an item exists. source_metadata and provenance.source_data serve different purposes:

Field Where it appears Use it for
source_metadata Recommendation set, block, task, or subtask Small partner-owned metadata that helps your system reconcile or debug a recommendation, such as a run ID, source URL, confidence score, or display hint. ChartHero treats it as opaque metadata.
provenance.source_data Inside provenance The small source snippet or structured source fact that explains why the recommendation exists.

See Security considerations for data that must not be included in either field.

Errors

Return the standard adapter error body with a stable error_code.

Case Status error_code retryable
Request body is malformed or cannot be interpreted 400 invalid_request false
Contract version is unsupported 400 unsupported_contract_version false
Authorization header value is missing or invalid 401 unauthorized false
Authorization header value is valid but not allowed to use this endpoint 403 forbidden false
Patient cannot be found in your system 404 patient_not_found false
Encounter or appointment cannot be found in your system 404 appointment_not_found false
Patient and encounter identifiers do not belong together 409 identifier_mismatch false
Endpoint is rate limited 429 rate_limited true
Endpoint is temporarily unavailable 503 temporarily_unavailable true

Use appointment_not_found when your system cannot resolve the external visit context carried in encounter.external_ids[], whether your source system calls that record an appointment, visit, encounter, or activity. The request field is named encounter because ChartHero is asking for recommendations for one ChartHero encounter.

Example:

JSON
{
  "error_code": "patient_not_found",
  "message": "Patient was not found in the partner system.",
  "retryable": false
}

Use retryable: true only when a later identical request is likely to succeed, such as rate_limited or temporarily_unavailable. See Request IDs and errors for the full error body and request-correlation headers.

Example: receive and respond

A minimal handler authenticates ChartHero's call, checks the contract version, logs the request ID, looks up the scoped patient and encounter, and returns recommendation sets in ChartHero's schema.

This example is illustrative. lookupPatient, lookupEncounter, lookupRecommendations, and toChartHeroRecommendationSet represent your adapter-specific lookup and schema-mapping code. Validate the request body, handle temporary downstream failures with 5xx retryable errors, and transform upstream data before returning it.

JS
import express from 'express';

const app = express();
app.use(express.json());

// The full Authorization header value you issued to ChartHero,
// e.g. "Bearer abc123", "ApiKey abc123", or a bare token.
// Fail closed at startup: with no expected value, a request with no
// Authorization header would otherwise compare undefined === undefined.
const CHARTHERO_AUTHORIZATION = process.env.CHARTHERO_AUTHORIZATION;
if (!CHARTHERO_AUTHORIZATION) {
  throw new Error('CHARTHERO_AUTHORIZATION must be set');
}
const SUPPORTED_CONTRACT_VERSION = '1.0';

app.post('/v1/checklist-recommendations/fetch', (req, res) => {
  const requestId = req.get('x-charthero-request-id') ?? 'missing';
  console.info('checklist recommendation request', { request_id: requestId });

  // Production adapters should validate req.body before reading nested fields.
  if (req.get('authorization') !== CHARTHERO_AUTHORIZATION) {
    return res.status(401).json({
      error_code: 'unauthorized',
      message: 'Invalid authorization',
      retryable: false,
    });
  }

  if (req.get('x-charthero-contract-version') !== SUPPORTED_CONTRACT_VERSION) {
    return res.status(400).json({
      error_code: 'unsupported_contract_version',
      message: 'Unsupported contract version',
      retryable: false,
    });
  }

  const patientExternalId = req.body.patient?.external_ids?.find(
    (identifier) =>
      identifier.source === 'acme_care_prod' && identifier.type === 'patient_id',
  )?.value;
  const encounterExternalId = req.body.encounter?.external_ids?.find(
    (identifier) =>
      identifier.source === 'acme_care_prod' && identifier.type === 'encounter_id',
  )?.value;

  const patient = lookupPatient({
    chartheroId: req.body.patient?.id,
    externalId: patientExternalId,
  });

  if (!patient) {
    return res.status(404).json({
      error_code: 'patient_not_found',
      message: 'Patient was not found',
      retryable: false,
    });
  }

  const encounter = lookupEncounter({
    chartheroId: req.body.encounter?.id,
    externalId: encounterExternalId,
    patient,
  });

  if (!encounter) {
    return res.status(404).json({
      error_code: 'appointment_not_found',
      message: 'Encounter was not found',
      retryable: false,
    });
  }

  const recommendations = lookupRecommendations({
    actor: req.body.actor,
    encounter,
    patient,
  });

  return res.status(200).json({
    items: recommendations.map(toChartHeroRecommendationSet),
  });
});

app.listen(8080);

To self-test your endpoint, send the same shape ChartHero sends. This curl uses a minimal actor payload; most actor profile fields are optional.

cURL
curl -sS -X POST https://ehr.example.com/integrations/charthero/v1/checklist-recommendations/fetch \
  -H 'Authorization: Bearer <partner_issued_token>' \
  -H 'X-ChartHero-Contract-Version: 1.0' \
  -H 'X-ChartHero-Request-Id: req_test_checklist_recommendations' \
  -H 'Content-Type: application/json' \
  -d '{
    "patient": {
      "id": "22222222-2222-4222-8222-222222222222",
      "external_ids": [
        { "source": "acme_care_prod", "type": "patient_id", "value": "pat-123" }
      ]
    },
    "encounter": {
      "id": "encounter-1",
      "external_ids": [
        { "source": "acme_care_prod", "type": "encounter_id", "value": "encounter-1" }
      ]
    },
    "actor": {
      "actor_type": "user",
      "actor_id": "11111111-1111-4111-8111-111111111111",
      "email": "clinician@example.com",
      "display_name": "Dr. Chris Smith",
      "active": true,
      "external_ids": []
    }
  }'

Logging

Log enough to debug a recommendation request without leaking unnecessary clinical data.

Log field Include
request_id X-ChartHero-Request-Id
endpoint checklist-recommendations/fetch
outcome Status code and stable error code
contract_version X-ChartHero-Contract-Version
recommendation_count Number of returned top-level items
timestamp Server-side receive or completion time

See Security considerations for fields and payloads that must stay out of logs.

Next steps

ChartHeroAI

Developer documentation for ChartHero APIs, adapters, and integrations.

HIPAA-aligned safeguards

BAA available

ChartHero AI LLC