# Diagnose

```
The Diagnose endpoint surfaces potential differential diagnoses for clinicians to consider with explainable and referenced rationale
```

## Overview

The Diagnose API analyzes a patient's clinical data — represented as a structured graph — and returns a ranked list of candidate diagnoses, each supported by evidence-based rationale drawn from clinical guidelines and diagnostic criteria.

The patient graph submitted to the Diagnose API follows the same structure produced by the [Assemble API](#assemble-api), which builds a patient graph from a FHIR bundle. It is recommended to use the Assemble API to construct and validate your patient graph before passing it to the Diagnose API.

***

## Workflow

```
FHIR Bundle ──► POST /v1/assemble ──► Patient Graph ──► POST /v1/diagnose ──► Diagnoses
```

{% stepper %}
{% step %}

### Assemble

Submit a FHIR bundle to `POST /v1/assemble` to construct a structured patient graph (`AssembledPatient`).
{% endstep %}

{% step %}

### Diagnose

Submit the resulting patient graph to `POST /v1/diagnose` to retrieve ranked candidate diagnoses.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Note:** While the Assemble API returns an `AssembledPatient` object, the Diagnose API accepts a `CustomAssembledPatient` object. This is an extended variant that supports additional metadata fields such as `family_member_history_metadata` and a custom observation metadata model. Ensure your patient graph conforms to the `CustomAssembledPatient` schema described below before submitting to the Diagnose endpoint.
{% endhint %}

***

## Endpoint

```
POST /v1/diagnose
```

### Authentication

All requests require an API key passed in the request header:

```
x-api-key: <your-api-key>
```

***

## Request

### Headers

| Header         | Value              | Required |
| -------------- | ------------------ | -------- |
| `x-api-key`    | Your API key       | Yes      |
| `Content-Type` | `application/json` | Yes      |

### Request Body

The request body must be a `CustomAssembledPatient` object — an extended form of the patient graph produced by the Assemble API. It contains the patient's clinical graph as a set of nodes, edges, and demographic information.

| Field           | Type                   | Required | Description                                                 |
| --------------- | ---------------------- | -------- | ----------------------------------------------------------- |
| `nodes`         | `CustomAssembleNode[]` | Yes      | Array of clinical graph nodes representing patient findings |
| `relationships` | `AssembleEdge[]`       | Yes      | Array of edges connecting nodes in the patient graph        |
| `demographics`  | `PatientDemographics`  | Yes      | Patient demographic information                             |

#### Patient Demographics

| Field    | Type            | Required | Description    |
| -------- | --------------- | -------- | -------------- |
| `age`    | integer \| null | Yes      | Patient age    |
| `gender` | string \| null  | Yes      | Patient gender |
| `race`   | string \| null  | Yes      | Patient race   |

#### Node Object (`CustomAssembleNode`)

Each node represents a clinical finding or concept in the patient's history. This extends the `AssembleNode` structure returned by the Assemble API with additional metadata support.

| Field                   | Type                                 | Required | Description                                       |
| ----------------------- | ------------------------------------ | -------- | ------------------------------------------------- |
| `node_type`             | string                               | Yes      | Discriminator for the node subtype                |
| `fhir_id`               | string \| null                       | Yes      | FHIR resource identifier                          |
| `notable`               | boolean                              | Yes      | Whether this node is notable/clinically important |
| `system_id`             | string \| null                       | Yes      | System identifier for the node                    |
| `system_preferred_name` | string \| null                       | Yes      | Preferred clinical name                           |
| `other_system_ids`      | string\[] \| null                    | No       | Additional system identifiers                     |
| `coding`                | `ExternalCoding[]` \| null           | No       | External coding references (e.g. SNOMED, ICD)     |
| `metadata`              | `CustomAssembleNodeMetadata` \| null | No       | Clinical metadata for the node                    |

#### External Coding (`ExternalCoding`)

| Field     | Type           | Required | Description                                   |
| --------- | -------------- | -------- | --------------------------------------------- |
| `code`    | string \| null | Yes      | Clinical code                                 |
| `system`  | string \| null | Yes      | Coding system (e.g. `http://snomed.info/sct`) |
| `display` | string \| null | Yes      | Human-readable display name                   |

#### Node Metadata (`CustomAssembleNodeMetadata`)

This extends the `AssembleNodeMetadata` structure from the Assemble API with support for `family_member_history_metadata` and a custom observation metadata model.

| Field                            | Type                                  | Required | Description                             |
| -------------------------------- | ------------------------------------- | -------- | --------------------------------------- |
| `condition_metadata`             | `ConditionMetadata` \| null           | No       | Metadata for condition nodes            |
| `observation_metadata`           | `CustomObservationMetadata` \| null   | No       | Metadata for observation nodes          |
| `intervention_metadata`          | `InterventionMetadata` \| null        | No       | Metadata for medication/procedure nodes |
| `allergy_metadata`               | `AllergyMetadata` \| null             | No       | Metadata for allergy nodes              |
| `family_member_history_metadata` | `FamilyMemberHistoryMetadata` \| null | No       | Metadata for family history nodes       |

#### Condition Metadata

| Field               | Type                 | Required | Description                      |
| ------------------- | -------------------- | -------- | -------------------------------- |
| `clinicalStatus`    | `ClinicalStatusEnum` | Yes      | Clinical status of the condition |
| `ccsr_categories`   | string\[] \| null    | No       | CCSR classification categories   |
| `ccsr_body_systems` | string\[] \| null    | No       | Affected body systems            |
| `onsetDateTime`     | datetime \| null     | No       | Date/time of condition onset     |
| `recordedDate`      | datetime \| null     | No       | Date/time condition was recorded |

**`ClinicalStatusEnum` values:**\
`active` | `recurrence` | `relapse` | `inactive` | `remission` | `resolved` | `unknown`

#### Observation Metadata (`CustomObservationMetadata`)

{% hint style="info" %}
**Note:** The Diagnose API uses a `CustomObservationMetadata` model rather than the standard `ObservationMetadata` returned by the Assemble API. The key difference is the addition of a `value_quantity` field using a `CustomQuantityType`, which corrects a known handling issue with numeric values in the standard `QuantityType`.
{% endhint %}

| Field              | Type                                    | Required | Description                          |
| ------------------ | --------------------------------------- | -------- | ------------------------------------ |
| `category`         | string\[] \| null                       | No       | Observation category                 |
| `interpretation`   | `ObservationInterpretationEnum` \| null | No       | Clinical interpretation of the value |
| `risk`             | `RiskTypeEnum`                          | Yes      | Risk classification                  |
| `risk_direction`   | `RiskDirectionEnum`                     | Yes      | Direction of risk                    |
| `observation_time` | datetime                                | Yes      | Time the observation was recorded    |
| `value_quantity`   | `CustomQuantityType` \| null            | No       | Quantitative observation value       |

**`RiskTypeEnum` values:**\*\* `optimal` | `low` | `normal` | `high`\
\&#xNAN;**`RiskDirectionEnum` values:**\*\* `high` | `very high` | `low` | `very low`

#### Quantity Type (`CustomQuantityType`)

| Field        | Type           | Required | Description                 |
| ------------ | -------------- | -------- | --------------------------- |
| `value`      | number \| null | No       | Numeric value               |
| `unit`       | string \| null | No       | Unit of measure             |
| `system`     | string \| null | No       | Unit coding system          |
| `code`       | string \| null | No       | Unit code                   |
| `comparator` | string \| null | No       | Comparator (e.g. `<`, `>=`) |

#### Intervention Metadata

| Field               | Type                     | Required | Description          |
| ------------------- | ------------------------ | -------- | -------------------- |
| `intervention_type` | `InterventionTypeEnum`   | Yes      | Type of intervention |
| `status`            | `InterventionStatusEnum` | Yes      | Current status       |
| `intervention_time` | datetime                 | Yes      | Time of intervention |

**`InterventionTypeEnum` values:**\*\* `medication` | `procedure` | `immunization`\
\&#xNAN;**`InterventionStatusEnum` values:**\*\* `active` | `on-hold` | `cancelled` | `completed` | `stopped` | `draft` | `unknown` | `entered-in-error` | `not-done` | `in-progress`

#### Allergy Metadata

| Field                | Type                             | Required | Description                    |
| -------------------- | -------------------------------- | -------- | ------------------------------ |
| `clinicalStatus`     | `ClinicalStatusEnum` \| null     | No       | Clinical status of the allergy |
| `verificationStatus` | `VerificationStatusEnum` \| null | No       | Verification status            |
| `criticality`        | `CriticalityEnum` \| null        | No       | Criticality level              |
| `recordedDate`       | datetime \| null                 | No       | Date allergy was recorded      |

**`VerificationStatusEnum` values:**\*\* `unconfirmed` | `confirmed` | `refuted` | `entered-in-error`\
\&#xNAN;**`CriticalityEnum` values:**\*\* `low` | `high` | `unable-to-assess`

#### Family Member History Metadata

{% hint style="info" %}
**Note:** This metadata type is available in the Diagnose API's `CustomAssembleNodeMetadata` but is not present in the base `AssembleNodeMetadata` returned by the Assemble API. It must be added to the patient graph prior to submitting to the Diagnose endpoint where family history is clinically relevant.
{% endhint %}

| Field      | Type                                    | Required | Description                                       |
| ---------- | --------------------------------------- | -------- | ------------------------------------------------- |
| `status`   | `FamilyMemberHistoryStatusEnum` \| null | No       | Status of the family history record               |
| `relation` | string \| null                          | No       | Relationship to patient (e.g. `father`, `mother`) |
| `sex`      | string \| null                          | No       | Sex of the family member                          |
| `onsetAge` | integer \| null                         | No       | Age of condition onset in the family member       |

**`FamilyMemberHistoryStatusEnum` values:**\*\* `partial` | `completed` | `entered-in-error` | `health-unknown`

#### Edge Object (`AssembleEdge`)

Edges follow the same structure as those produced by the Assemble API.

| Field             | Type   | Required | Description                         |
| ----------------- | ------ | -------- | ----------------------------------- |
| `source`          | string | Yes      | `system_id` of the source node      |
| `target`          | string | Yes      | `system_id` of the target node      |
| `relationship_id` | string | Yes      | Identifier of the relationship type |

***

## Response

### Success Response — `200 OK`

Returns a `DiagnoseOutput` object containing a ranked list of candidate diagnoses.

```json
{
  "diagnoses": [
    {
      "system_id": "string",
      "display_name": "string",
      "score": 0.95,
      "rationale": {
        "overview": {
          "text": "string",
          "references": []
        },
        "diagnostic_evidence": [],
        "relevant_family_history": []
      }
    }
  ]
}
```

### Response Schema

#### `DiagnoseOutput`

| Field       | Type          | Required | Description                        |
| ----------- | ------------- | -------- | ---------------------------------- |
| `diagnoses` | `Diagnosis[]` | Yes      | Ranked list of candidate diagnoses |

#### `Diagnosis`

| Field          | Type                | Required | Description                                              |
| -------------- | ------------------- | -------- | -------------------------------------------------------- |
| `system_id`    | string              | Yes      | System Interoperable Variable ID for the diagnosis       |
| `display_name` | string \| null      | No       | Human-readable diagnosis name                            |
| `score`        | number \| integer   | Yes      | Evidence score — higher values indicate stronger support |
| `rationale`    | `Rationale` \| null | No       | Detailed evidence rationale for the diagnosis            |

#### `Rationale`

| Field                     | Type                              | Description                                |
| ------------------------- | --------------------------------- | ------------------------------------------ |
| `overview`                | `DiagnosisOverview` \| null       | Summary and guideline references           |
| `diagnostic_evidence`     | `DiagnosticCriterion[]` \| null   | Criteria evaluated against patient data    |
| `relevant_family_history` | `RelevantFamilyHistory[]` \| null | Clinically relevant family history entries |

#### `DiagnosisOverview`

| Field        | Type                           | Description                                                     |
| ------------ | ------------------------------ | --------------------------------------------------------------- |
| `text`       | string \| null                 | Plain-language summary of why the diagnosis is being considered |
| `references` | `GuidelineReference[]` \| null | Clinical guidelines used to evaluate the diagnosis              |

#### `GuidelineReference`

| Field                 | Type              | Required | Description                               |
| --------------------- | ----------------- | -------- | ----------------------------------------- |
| `title`               | string            | Yes      | Title of the guideline document           |
| `authoring_societies` | string\[] \| null | No       | Organizations that authored the guideline |

#### `DiagnosticCriterion`

Represents a single diagnostic criterion evaluated against the patient's data.

| Field             | Type             | Required | Description                                                                   |
| ----------------- | ---------------- | -------- | ----------------------------------------------------------------------------- |
| `evidence_type`   | string           | Yes      | Whether this criterion `matches`, is `missing`, or `contradicts` patient data |
| `criterion`       | string           | Yes      | Criterion expression as stated in guidelines (e.g. `"TSH high"`)              |
| `patient_finding` | string \| null   | No       | The corresponding patient finding                                             |
| `fhir_id`         | string \| null   | No       | FHIR ID of the supporting resource                                            |
| `patient_value`   | string \| null   | No       | Observed value from the patient                                               |
| `time_recorded`   | datetime \| null | No       | When the finding was recorded                                                 |

#### `RelevantFamilyHistory`

| Field              | Type                           | Required | Description                                        |
| ------------------ | ------------------------------ | -------- | -------------------------------------------------- |
| `condition_name`   | string                         | Yes      | Name of the family member's condition              |
| `explanation`      | string                         | Yes      | Clinical explanation of relevance to the diagnosis |
| `relation_code`    | string \| null                 | No       | Coded relation to patient                          |
| `relation_display` | string \| null                 | No       | Human-readable relation (e.g. `"mother"`)          |
| `onset_age`        | integer \| null                | No       | Age of onset in the family member                  |
| `references`       | `GuidelineReference[]` \| null | No       | Supporting guideline references                    |

***

## Error Responses

| HTTP Status                | Description                                                            |
| -------------------------- | ---------------------------------------------------------------------- |
| `200 OK`                   | Successful response with diagnoses                                     |
| `422 Unprocessable Entity` | Request body failed validation — check field types and required fields |

### Validation Error Schema

```json
{
  "detail": [
    {
      "loc": ["body", "nodes"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

***

## Example Request

The following example submits a patient graph with a single condition node (hypothyroidism) and observation node (elevated TSH) to retrieve candidate diagnoses. This graph was first assembled using the Assemble API from a FHIR bundle, then extended with family history metadata before being submitted here.

```bash
curl -X POST https://cg-api-prod.system.com/v1/diagnose \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
  "nodes": [
    {
      "node_type": "condition",
      "fhir_id": "condition-001",
      "notable": true,
      "system_id": "sys-hypothyroidism",
      "system_preferred_name": "Hypothyroidism",
      "coding": [
        {
          "code": "40930008",
          "system": "http://snomed.info/sct",
          "display": "Hypothyroidism"
        }
      ],
      "metadata": {
        "condition_metadata": {
          "clinicalStatus": "active",
          "ccsr_body_systems": ["Endocrine system"],
          "onsetDateTime": "2023-01-15T00:00:00Z"
        }
      }
    },
    {
      "node_type": "observation",
      "fhir_id": "obs-001",
      "notable": true,
      "system_id": "sys-tsh-high",
      "system_preferred_name": "TSH elevated",
      "metadata": {
        "observation_metadata": {
          "risk": "high",
          "risk_direction": "high",
          "observation_time": "2024-03-01T08:30:00Z",
          "interpretation": "high",
          "value_quantity": {
            "value": 8.5,
            "unit": "mIU/L",
            "system": "http://unitsofmeasure.org",
            "code": "mIU/L"
          }
        }
      }
    },
    {
      "node_type": "family_history",
      "fhir_id": "fh-001",
      "notable": false,
      "system_id": "sys-fh-thyroid",
      "system_preferred_name": "Family history of thyroid disorder",
      "metadata": {
        "family_member_history_metadata": {
          "status": "completed",
          "relation": "mother",
          "sex": "female",
          "onsetAge": 52
        }
      }
    }
  ],
  "relationships": [
    {
      "source": "sys-tsh-high",
      "target": "sys-hypothyroidism",
      "relationship_id": "rel-tsh-hypothyroidism"
    },
    {
      "source": "sys-fh-thyroid",
      "target": "sys-hypothyroidism",
      "relationship_id": "rel-fh-hypothyroidism"
    }
  ],
  "demographics": {
    "age": 45,
    "gender": "female",
    "race": "white"
  }
}'
```

## Example Response

```json
{
  "diagnoses": [
    {
      "system_id": "sys-hypothyroidism-primary",
      "display_name": "Primary Hypothyroidism",
      "score": 0.92,
      "rationale": {
        "overview": {
          "text": "Patient presents with elevated TSH and active hypothyroidism diagnosis, consistent with primary hypothyroidism per ATA guidelines. Maternal history of thyroid disorder further supports this diagnosis.",
          "references": [
            {
              "title": "American Thyroid Association Guidelines for Hypothyroidism in Adults",
              "authoring_societies": ["American Thyroid Association"]
            }
          ]
        },
        "diagnostic_evidence": [
          {
            "evidence_type": "matches",
            "criterion": "TSH high",
            "patient_finding": "TSH elevated",
            "fhir_id": "obs-001",
            "patient_value": "8.5 mIU/L",
            "time_recorded": "2024-03-01T08:30:00Z"
          }
        ],
        "relevant_family_history": [
          {
            "condition_name": "Thyroid disorder",
            "explanation": "Maternal history of thyroid disorder increases risk of primary hypothyroidism.",
            "relation_code": "MTH",
            "relation_display": "mother",
            "onset_age": 52,
            "references": [
              {
                "title": "American Thyroid Association Guidelines for Hypothyroidism in Adults",
                "authoring_societies": ["American Thyroid Association"]
              }
            ]
          }
        ]
      }
    }
  ]
}
```

***

## Key Concepts

### Patient Graph and the Assemble API

The Diagnose API requires the patient's clinical data to be represented as a structured **graph**. The recommended approach is to use the `POST /v1/assemble` endpoint to generate this graph from a FHIR bundle. The Assemble API resolves FHIR resources into typed, system-mapped nodes and edges that are directly compatible with the Diagnose API's input schema.

Once assembled, the graph may be enriched with additional data — such as family member history metadata — before being submitted to the Diagnose endpoint.

* **Nodes** represent individual clinical findings such as conditions, observations, medications, allergies, and family history entries
* **Edges (Relationships)** represent the clinical connections between those findings

### Evidence Scoring

Each returned diagnosis is assigned a **score** reflecting the strength of supporting evidence from clinical guidelines and diagnostic criteria. Higher scores indicate stronger alignment with established diagnostic criteria.

### Diagnostic Evidence Types

Each `DiagnosticCriterion` within the rationale includes an `evidence_type` field indicating its relationship to the patient's data:

| Evidence Type | Meaning                                                       |
| ------------- | ------------------------------------------------------------- |
| `matches`     | The patient's data satisfies this diagnostic criterion        |
| `missing`     | This criterion is expected but absent from the patient's data |
| `contradicts` | The patient's data is inconsistent with this criterion        |

***

## Notes

* Use `POST /v1/assemble` to build the patient graph from a FHIR bundle before calling this endpoint.
* The `demographics` object requires `age`, `gender`, and `race` — all are required fields.
* The `notable` flag on each node should be set to `true` for clinically significant findings that should be weighted more heavily during diagnosis evaluation.
* Family history nodes with `family_member_history_metadata` can influence diagnosis scoring where hereditary factors are clinically relevant. This metadata is an extension beyond what the Assemble API returns and must be added manually if required.
* The `CustomObservationMetadata` used by this endpoint differs from the standard `ObservationMetadata` in the Assemble API — specifically in its handling of the `value_quantity` field. Ensure observation nodes use the `CustomQuantityType` format when submitting quantitative values.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.system.com/system/api-docs/diagnose.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
