Errors and request IDs
Confirm all non-2xx responses use the standard error body.
Adapter reference
Use adapter readiness checks before activating an installation.
v1.0Use this checklist before activating an adapter installation. These checks are implementation guidance, not an automated certification suite.
Run the required checks for every installation, then add conditional checks only for enabled capabilities and approved optional flows.
| Area | Required result |
|---|---|
| Base URL | Every enabled route is available under one configured base_url. |
| Authentication | Missing or bad Authorization header values return 401 unauthorized. Valid values without endpoint access return 403 forbidden. |
| Contract version | Unsupported X-ChartHero-Contract-Version values fail with 400 unsupported_contract_version. |
| Validate connection | POST accepts {} and returns exactly {"status":"ok"} on success. |
| Launch URL | Production launch URLs contain exactly one ctx parameter and no raw PHI query parameters. |
| Launch context | Valid launch_state returns patient context. Unknown, mismatched, or unauthorized launch state returns standard errors. |
| Checklist recommendations | When enabled, a known patient and encounter can return items: [] or valid recommendation sets. |
| Request IDs | Every adapter request logs X-ChartHero-Request-Id with endpoint, timestamp, environment, and outcome. |
| Error body | Every non-2xx response uses error_code, message, and retryable. |
| Error diagnostics | When the receiver is implemented, POST returns exactly {"status":"accepted"} and never calls back into ChartHero. |
| Label | Test scope |
|---|---|
| Required for setup | Always test before validating or activating the installation |
| Required for first launch | Always test before launch enablement |
| Conditional | Test when the capability or provider-linking mode is enabled |
| Optional approved flow | Test only when ChartHero explicitly approved the flow for the installation |
| Optional, default off | Test before the organization turns the optional setting on |
Request:
POST /v1/validate-connection
Authorization: Bearer <partner_issued_token>
X-ChartHero-Contract-Version: 1.0
X-ChartHero-Request-Id: req_test_validate_connection
Content-Type: application/json
{}
Expected success:
{
"status": "ok"
}
Also test a missing Authorization header, an invalid authorization header value, an unsupported contract version, and a valid credential without permission for the endpoint.
Generate test launch URLs that cover:
ctx with a small object launch_state.ctx where launch_state resolves to a patient launch.ctx where launch_state resolves to an encounter launch.ctx with top-level actor.actor_id, actor.email, or actor.external_ids[] when provider linking is required.actor criteria rejection when provider linking is required.exp.exp - iat greater than five minutes.jti.aud, wrong iss, wrong kid, wrong alg, wrong typ, or unsupported enc.ChartHero should reject invalid launch payloads before it opens patient-bearing state.
For POST /v1/launch/context, verify:
| Scenario | Expected response |
|---|---|
| Known patient-only launch state | 200 with patient. |
| Known encounter launch state | 200 with encounter and required encounter.patient when the encounter was found. |
| Launch state resolves to matching patient and encounter | 200 and the embedded patient asserts they belong together. |
| Launch state resolves to mismatched patient and encounter | 409 identifier_mismatch. |
| Launch state resolves to an unknown patient | 404 patient_not_found. |
| Launch state resolves to an unknown appointment | 404 appointment_not_found. |
| Actor cannot access context | 403 permission_denied. |
If setup_defaults is returned, test that malformed defaults cause the response to fail validation. ChartHero does not ignore invalid defaults.
When provider linking is enabled, verify the configured mode:
| Mode | Tests |
|---|---|
disabled |
ChartHero can launch without a provider/user link. Test both launch without mapped provider identifiers and any adapter authorization that uses the enriched ChartHero actor with external_ids: []. |
optional |
Launch succeeds when a valid link exists and follows the configured fallback when no link exists. |
required |
ChartHero fails closed before partner calls when actor criteria are missing or conflicting, or when no active, non-conflicting provider/user link exists and verified-email auto-link cannot repair the missing link. |
For POST /v1/providers/search, test fixed limit: 100, offset echoing, next_offset, no duplicate same-source/type identifiers with different values, inactive provider handling, and the 50,000 provider limit.
For POST /v1/users/resolve-by-email, test exact verified-email lookup, no-match, ambiguous-match, inactive users omitted as external_user_not_found, and email-not-durable-identity cases. Successful lookup responses must return an external user with active: true.
When checklist recommendations are enabled, verify:
| Scenario | Expected response |
|---|---|
| Known patient and encounter with no partner recommendations | 200 with {"items":[]}. |
| Known patient and encounter with recommendations | 200 with recommendation_set items, blocks, and tasks that validate against the generated schema. |
| Request actor has no mapped provider identifiers in an approved fallback mode | Response follows the installation's approved authorization fallback. |
| Patient cannot be found | 404 patient_not_found. |
| Encounter or appointment cannot be found | 404 appointment_not_found. |
| Patient and encounter do not belong together | 409 identifier_mismatch. |
| Unsupported item type or malformed recommendation payload | Do not return 200; return 400 invalid_request or fix the response before enabling. |
Also test optional fields you plan to send, especially generated_at,
provenance.captured_at, priority, requires_action, source_data, and
partner-stable key or external_id values.
Test the receiver before an organization enables error_diagnostics.enabled.
These are conditional tests: run them only for installations that will turn the
setting on.
Request:
POST /v1/diagnostics/errors
Authorization: Bearer <partner_issued_token>
Content-Type: application/json
X-ChartHero-Contract-Version: 1.0
X-ChartHero-Request-Id: req_test_error_diagnostic
X-ChartHero-Diagnostic-Id: diag_2f1dcb4ce6764fbeaa89fe86487b7e37
{
"diagnostic_id": "diag_2f1dcb4ce6764fbeaa89fe86487b7e37",
"source_endpoint": "/v1/launch/context",
"error_code": "response_json_invalid",
"message": "POST /v1/launch/context returned a successful response that was empty, invalid JSON, or not a JSON object. Return one JSON object matching the endpoint contract.",
"response_status": 200,
"occurred_at": "2026-08-06T15:42:18Z"
}
Expected success:
{
"status": "accepted"
}
Verify each case:
| Scenario | Expected response |
|---|---|
Valid diagnostic with matching header and body diagnostic_id |
200 with exactly {"status":"accepted"} and no extra fields. |
Header X-ChartHero-Diagnostic-Id does not match body diagnostic_id |
400 invalid_request. |
Missing required field, unknown extra field, or malformed diagnostic_id |
400 invalid_request. |
| Missing or invalid Authorization header value | 401 unauthorized. |
| Valid credential without access to this endpoint | 403 forbidden. |
Unsupported X-ChartHero-Contract-Version |
400 unsupported_contract_version. |
Each of the six error_code values, including null response_status for transport_timeout and transport_error |
200 for every code; do not special-case one code. |
Otherwise valid request whose non-empty message differs from the example but remains at most 512 characters |
200; require the public string bounds, but do not compare it with the catalog. |
| Receiving a diagnostic | No outbound call back to ChartHero, and no change to the original workflow's state. |
| Slow or failing receiver | ChartHero drops the diagnostic after one attempt and never retries it; confirm no queue or replay expectation on your side. |
Also confirm the setting stays off until these tests pass, and that the optional
X-ChartHero-Diagnostic-Id header on normal adapter calls is logged but never
required.
The manual request above is a partner-local contract-conformance fixture. It does not claim that ChartHero observed a source failure and is not a ChartHero-emitted readiness event.
Log enough for both teams to debug without exposing secrets or raw PHI:
| Log field | Include |
|---|---|
request_id |
X-ChartHero-Request-Id |
endpoint |
Adapter route name |
environment |
Partner environment handling the request |
outcome |
Status code and stable error code |
contract_version |
Requested X-ChartHero-Contract-Version |
timestamp |
Server-side receive or completion time |
diagnostic_id |
X-ChartHero-Diagnostic-Id when present; it is optional and absent unless error diagnostics is enabled |
Do not log authorization header values, launch key material, compact JWE plaintext, raw clinical content, transcripts, or unnecessary patient demographics.
Confirm all non-2xx responses use the standard error body.
Inspect exact endpoint schemas and response contracts.
Check contract changes.