> ## Documentation Index
> Fetch the complete documentation index at: https://api.idunox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Submissions

> Accepts de-identified payload. `partnerId` MUST equal the authenticated `PartnerCredential.id`.

At least one of `markers` or `reportDocuments` MUST be present (non-empty). Extra keys on nested objects are rejected (`.strict()` Zod schemas).


Submit a de-identified **canonical Type A** JSON body (`canonical_submission_v1`). Map your intake questionnaire and blood panel in your backend before calling this endpoint — see [Canonical submission JSON](/platform/canonical-submission) and the [Input Data Preparation Guide](/api-reference/introduction).

## Request requirements

* `partnerId` must equal the UUID of the **PartnerCredential** tied to your API key.
* Include a non-empty **`markers[]`** array with all **14** Health Yourself blood marker codes.
* Structure questionnaire data under **`subject`** (not `markers.healthQuestionnaireMarkers`).
* Send **`options.requestedOutputs`** (required) and **`options.requestedOutcomes`** for the four HY wellbeing areas.
* Provide **`sourceMetadata.sourceTimestamp`** for when the intake was completed; optional **`sourceMetadata.markerRanges`** for lab reference intervals.
* On every `POST`, send non-empty **`x-correlation-id`** and **`Idempotency-Key`** headers.

The API validates the canonical schema at request time (types, enums, smoking/family conditionals, and the 14-marker panel). Rejected requests return `400` with field-level details — see [Errors](/platform/errors).

## Top-level field reference

| Field                 | Required    | Notes                                               |
| --------------------- | ----------- | --------------------------------------------------- |
| `schemaVersion`       | Yes         | `canonical_submission_v1`                           |
| `partnerId`           | Yes         | Partner credential UUID                             |
| `partnerSubmissionId` | Yes         | Your unique reference (max 512 characters)          |
| `partnerSubjectId`    | Yes         | De-identified subject reference                     |
| `subject`             | Yes         | Demographics, measurements, history, family history |
| `markers`             | Yes         | 14 blood observations (`code`, `value`, `unit`)     |
| `options`             | Yes         | `requestedOutputs` + `requestedOutcomes`            |
| `sourceMetadata`      | Recommended | `sourceTimestamp`, `markerRanges`, lab metadata     |

## Health Yourself request example

```bash theme={null}
curl -X POST "https://api.idunox.com/v1/submissions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "x-correlation-id: hy-2026-05-25-001" \
  -H "Idempotency-Key: hy-submission-0001" \
  -d @submission.json
```

`submission.json`:

```json theme={null}
{
  "schemaVersion": "canonical_submission_v1",
  "partnerId": "11111111-1111-4111-8111-111111111111",
  "partnerSubmissionId": "hy-sub-0001",
  "partnerSubjectId": "hy-pt-0001",
  "sourceMetadata": {
    "sourceSystem": "health-yourself-frontend",
    "sourceTimestamp": "2026-04-20T09:00:00.000Z",
    "labName": "Partner Central Lab",
    "facilityId": "FAC-001",
    "markerRanges": {
      "ALBUMIN": { "unit": "g/L", "lowerBound": 35, "upperBound": 50 },
      "ALT": { "unit": "U/L", "lowerBound": 7, "upperBound": 56 },
      "ALP": { "unit": "U/L", "lowerBound": 44, "upperBound": 147 },
      "AST": { "unit": "U/L", "lowerBound": 10, "upperBound": 40 },
      "CALCIUM": { "unit": "mmol/L", "lowerBound": 2.1, "upperBound": 2.55 },
      "CHOL": { "unit": "mmol/L", "lowerBound": 0.5, "upperBound": 5.2 },
      "CYSTATIN_C": { "unit": "mg/L", "lowerBound": 0.61, "upperBound": 0.95 },
      "GGT": { "unit": "U/L", "lowerBound": 9, "upperBound": 48 },
      "HDL": { "unit": "mmol/L", "lowerBound": 1.0, "upperBound": 4.65 },
      "CRP": { "unit": "mg/L", "lowerBound": 0.08, "upperBound": 3.0 },
      "LDL": { "unit": "mmol/L", "lowerBound": 0.26, "upperBound": 3.3 },
      "PHOSPHATE": { "unit": "mmol/L", "lowerBound": 0.8, "upperBound": 1.5 },
      "URATE": { "unit": "µmol/L", "lowerBound": 155, "upperBound": 357 },
      "HBA1C_MMOL_MOL": { "unit": "mmol/mol", "lowerBound": 20, "upperBound": 41 }
    }
  },
  "subject": {
    "demographics": {
      "sexAtBirth": "female",
      "ageYears": 52
    },
    "measurements": {
      "weightKg": 72.4,
      "heightCm": 168
    },
    "history": {
      "overallHealth": "good",
      "smoking": {
        "status": "former",
        "pastFrequency": "heavy",
        "pastCigsPerDay": 12,
        "startAge": 19,
        "stopAge": 41
      },
      "conditions": {
        "hasDiabetes": false,
        "hasDementia": false,
        "hasCardioCerebrovascular": false,
        "hasLungCancer": false,
        "hasKidneyDisease": false
      },
      "medications": {
        "takesRegularMedication": true
      }
    },
    "familyHistory": {
      "father": {
        "aliveStatus": "deceased",
        "deathAge": 73,
        "conditions": [
          "alzheimer_disease",
          "diabetes_mellitus",
          "cardiovascular_disease",
          "hypertension"
        ]
      },
      "mother": {
        "aliveStatus": "alive",
        "currentAge": 79,
        "conditions": ["hypertension", "diabetes_mellitus"]
      }
    }
  },
  "markers": [
    { "code": "ALBUMIN", "value": 42, "unit": "g/L" },
    { "code": "ALT", "value": 28, "unit": "U/L" },
    { "code": "ALP", "value": 85, "unit": "U/L" },
    { "code": "AST", "value": 24, "unit": "U/L" },
    { "code": "CALCIUM", "value": 2.35, "unit": "mmol/L" },
    { "code": "CHOL", "value": 5.2, "unit": "mmol/L" },
    { "code": "CYSTATIN_C", "value": 0.95, "unit": "mg/L" },
    { "code": "GGT", "value": 32, "unit": "U/L" },
    { "code": "HDL", "value": 1.4, "unit": "mmol/L" },
    { "code": "CRP", "value": 1.2, "unit": "mg/L" },
    { "code": "LDL", "value": 3.1, "unit": "mmol/L" },
    { "code": "PHOSPHATE", "value": 1.1, "unit": "mmol/L" },
    { "code": "URATE", "value": 320, "unit": "µmol/L" },
    { "code": "HBA1C_MMOL_MOL", "value": 38, "unit": "mmol/mol" }
  ],
  "options": {
    "requestedOutputs": ["inference_score_v1", "json", "html"],
    "requestedOutcomes": [
      "wellbeing.cardiovascular",
      "wellbeing.cognitive",
      "wellbeing.renal",
      "wellbeing.respiratory"
    ]
  }
}
```

## Accepted response (`202`)

```json theme={null}
{
  "submissionId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "jobId": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
  "partnerSubmissionId": "hy-sub-0001",
  "partnerSubjectId": "hy-pt-0001",
  "status": "accepted",
  "receivedAt": "2026-04-20T09:00:02.000Z"
}
```

Store `submissionId`. Poll [`GET /v1/submissions/{submissionId}`](/api-reference/endpoint/get_submissions) or wait for the [`result.ready`](/api-reference/endpoint/webhook) webhook, then call [`GET /v1/results/{resultId}`](/api-reference/endpoint/results).


## OpenAPI

````yaml POST /v1/submissions
openapi: 3.1.0
info:
  title: IduScore Partner & Platform API
  description: >-
    Partner-facing JSON API for de-identified clinical submissions (canonical
    Type A, not FHIR at ingestion).


    **Authentication:** Send `X-Api-Key: <key>` **or** `Authorization: Bearer
    <key>` on every `/v1/*` request (except preflight `OPTIONS`).


    **Writes (`POST`):** Client MUST send non-empty `x-correlation-id` and
    `Idempotency-Key`. The server does not synthesize these from the request id.


    **Tenant scope:** Credentials resolve to a tenant; all IDs are tenant-scoped
    (cross-tenant access returns `404` where applicable).


    **Request id:** Responses may echo `x-request-id` when the client sent it;
    otherwise the server generates one (see error envelope `requestId`).


    **Partner responses:** Read APIs return **IduScore wellbeing** language only
    — stable `wellbeing.*` outcome ids,

    plain-English labels, and optional `notices[].message` lines (no internal
    warning codes or model identifiers).

    Use **`GET /openapi.yaml`** for request/response examples aligned with this
    contract.



    ---

    **Merged spec (this file):** includes **Platform** and **Diagnostics** paths
    from the service implementation in addition to the **Type A** `/v1` product
    routes. The slimmer `type-a-partner-v1.*` files are the same contract for
    submissions, jobs, and results.
  version: 0.1.0
  license:
    name: Proprietary
servers:
  - url: https://api.idunox.com
    description: Production partner API (documented base URL for examples and playground)
security: []
tags:
  - name: Submissions
    description: Ingestion and submission reads
  - name: Jobs
    description: Processing job status
  - name: Results
    description: Inference / scoring results
  - name: Webhooks
    description: >
      Outbound HTTPS callbacks the platform may POST to a URL you register (not
      paths on the IduScore Partner API;

      `/_reference/...` entries document payload and headers for your
      implementer only).
  - name: Platform
    description: >-
      Liveness, readiness, and OpenAPI document discovery. **No API key**
      required.
  - name: Diagnostics
    description: >-
      Validates the same **partner API key** and (for `POST`) write headers as
      other `/v1` routes. Returns `204` when valid.
paths:
  /v1/submissions:
    post:
      tags:
        - Submissions
      summary: Submit Type A canonical JSON (async pipeline)
      description: >
        Accepts de-identified payload. `partnerId` MUST equal the authenticated
        `PartnerCredential.id`.


        At least one of `markers` or `reportDocuments` MUST be present
        (non-empty). Extra keys on nested objects are rejected (`.strict()` Zod
        schemas).
      operationId: submitTypeASubmission
      parameters:
        - $ref: '#/components/parameters/HeaderCorrelationIdRequired'
        - $ref: '#/components/parameters/HeaderIdempotencyKeyRequired'
        - $ref: '#/components/parameters/HeaderRequestIdOptional'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TypeASubmissionBody'
            examples:
              healthYourselfCanonical:
                summary: Health Yourself — full 14-marker canonical submission
                value:
                  schemaVersion: canonical_submission_v1
                  partnerId: 11111111-1111-4111-8111-111111111111
                  partnerSubmissionId: hy-sub-0001
                  partnerSubjectId: hy-pt-0001
                  sourceMetadata:
                    sourceSystem: health-yourself-frontend
                    sourceTimestamp: '2026-04-20T09:00:00.000Z'
                    labName: Partner Central Lab
                    facilityId: FAC-001
                    markerRanges:
                      ALBUMIN:
                        unit: g/L
                        lowerBound: 35
                        upperBound: 50
                      ALT:
                        unit: U/L
                        lowerBound: 7
                        upperBound: 56
                      ALP:
                        unit: U/L
                        lowerBound: 44
                        upperBound: 147
                      AST:
                        unit: U/L
                        lowerBound: 10
                        upperBound: 40
                      CALCIUM:
                        unit: mmol/L
                        lowerBound: 2.1
                        upperBound: 2.55
                      CHOL:
                        unit: mmol/L
                        lowerBound: 0.5
                        upperBound: 5.2
                      CYSTATIN_C:
                        unit: mg/L
                        lowerBound: 0.61
                        upperBound: 0.95
                      GGT:
                        unit: U/L
                        lowerBound: 9
                        upperBound: 48
                      HDL:
                        unit: mmol/L
                        lowerBound: 1
                        upperBound: 4.65
                      CRP:
                        unit: mg/L
                        lowerBound: 0.08
                        upperBound: 3
                      LDL:
                        unit: mmol/L
                        lowerBound: 0.26
                        upperBound: 3.3
                      PHOSPHATE:
                        unit: mmol/L
                        lowerBound: 0.8
                        upperBound: 1.5
                      URATE:
                        unit: µmol/L
                        lowerBound: 155
                        upperBound: 357
                      HBA1C_MMOL_MOL:
                        unit: mmol/mol
                        lowerBound: 20
                        upperBound: 41
                  subject:
                    demographics:
                      sexAtBirth: female
                      ageYears: 52
                    measurements:
                      weightKg: 72.4
                      heightCm: 168
                    history:
                      overallHealth: good
                      smoking:
                        status: former
                        pastFrequency: heavy
                        pastCigsPerDay: 12
                        startAge: 19
                        stopAge: 41
                      conditions:
                        hasDiabetes: false
                        hasDementia: false
                        hasCardioCerebrovascular: false
                        hasLungCancer: false
                        hasKidneyDisease: false
                      medications:
                        takesRegularMedication: true
                    familyHistory:
                      father:
                        aliveStatus: deceased
                        deathAge: 73
                        conditions:
                          - alzheimer_disease
                          - diabetes_mellitus
                          - cardiovascular_disease
                          - hypertension
                      mother:
                        aliveStatus: alive
                        currentAge: 79
                        conditions:
                          - hypertension
                          - diabetes_mellitus
                  markers:
                    - code: ALBUMIN
                      value: 42
                      unit: g/L
                    - code: ALT
                      value: 28
                      unit: U/L
                    - code: ALP
                      value: 85
                      unit: U/L
                    - code: AST
                      value: 24
                      unit: U/L
                    - code: CALCIUM
                      value: 2.35
                      unit: mmol/L
                    - code: CHOL
                      value: 5.2
                      unit: mmol/L
                    - code: CYSTATIN_C
                      value: 0.95
                      unit: mg/L
                    - code: GGT
                      value: 32
                      unit: U/L
                    - code: HDL
                      value: 1.4
                      unit: mmol/L
                    - code: CRP
                      value: 1.2
                      unit: mg/L
                    - code: LDL
                      value: 3.1
                      unit: mmol/L
                    - code: PHOSPHATE
                      value: 1.1
                      unit: mmol/L
                    - code: URATE
                      value: 320
                      unit: µmol/L
                    - code: HBA1C_MMOL_MOL
                      value: 38
                      unit: mmol/mol
                  options:
                    requestedOutputs:
                      - inference_score_v1
                      - json
                      - html
                    requestedOutcomes:
                      - wellbeing.cardiovascular
                      - wellbeing.cognitive
                      - wellbeing.renal
                      - wellbeing.respiratory
              deidentifiedReportOnly:
                summary: Report metadata without blood markers
                value:
                  schemaVersion: canonical_submission_v1
                  partnerId: 11111111-1111-4111-8111-111111111111
                  partnerSubmissionId: partner-ext-sub-0002
                  partnerSubjectId: partner-ext-pt-0002
                  subject:
                    demographics:
                      sexAtBirth: female
                      birthYear: 1972
                  reportDocuments:
                    - documentType: lab_summary
                      effectiveAt: '2025-01-11T14:00:00.000Z'
                      summaryText: >-
                        De-identified summary bullets only. No patient name,
                        MRN, or contact details.
                  options:
                    requestedOutputs:
                      - score
            example:
              schemaVersion: canonical_submission_v1
              partnerId: 11111111-1111-4111-8111-111111111111
              partnerSubmissionId: hy-sub-0001
              partnerSubjectId: hy-pt-0001
              sourceMetadata:
                sourceSystem: health-yourself-frontend
                sourceTimestamp: '2026-04-20T09:00:00.000Z'
                labName: Partner Central Lab
                facilityId: FAC-001
                markerRanges:
                  ALBUMIN:
                    unit: g/L
                    lowerBound: 35
                    upperBound: 50
                  ALT:
                    unit: U/L
                    lowerBound: 7
                    upperBound: 56
                  ALP:
                    unit: U/L
                    lowerBound: 44
                    upperBound: 147
                  AST:
                    unit: U/L
                    lowerBound: 10
                    upperBound: 40
                  CALCIUM:
                    unit: mmol/L
                    lowerBound: 2.1
                    upperBound: 2.55
                  CHOL:
                    unit: mmol/L
                    lowerBound: 0.5
                    upperBound: 5.2
                  CYSTATIN_C:
                    unit: mg/L
                    lowerBound: 0.61
                    upperBound: 0.95
                  GGT:
                    unit: U/L
                    lowerBound: 9
                    upperBound: 48
                  HDL:
                    unit: mmol/L
                    lowerBound: 1
                    upperBound: 4.65
                  CRP:
                    unit: mg/L
                    lowerBound: 0.08
                    upperBound: 3
                  LDL:
                    unit: mmol/L
                    lowerBound: 0.26
                    upperBound: 3.3
                  PHOSPHATE:
                    unit: mmol/L
                    lowerBound: 0.8
                    upperBound: 1.5
                  URATE:
                    unit: µmol/L
                    lowerBound: 155
                    upperBound: 357
                  HBA1C_MMOL_MOL:
                    unit: mmol/mol
                    lowerBound: 20
                    upperBound: 41
              subject:
                demographics:
                  sexAtBirth: female
                  ageYears: 52
                measurements:
                  weightKg: 72.4
                  heightCm: 168
                history:
                  overallHealth: good
                  smoking:
                    status: former
                    pastFrequency: heavy
                    pastCigsPerDay: 12
                    startAge: 19
                    stopAge: 41
                  conditions:
                    hasDiabetes: false
                    hasDementia: false
                    hasCardioCerebrovascular: false
                    hasLungCancer: false
                    hasKidneyDisease: false
                  medications:
                    takesRegularMedication: true
                familyHistory:
                  father:
                    aliveStatus: deceased
                    deathAge: 73
                    conditions:
                      - alzheimer_disease
                      - diabetes_mellitus
                      - cardiovascular_disease
                      - hypertension
                  mother:
                    aliveStatus: alive
                    currentAge: 79
                    conditions:
                      - hypertension
                      - diabetes_mellitus
              markers:
                - code: ALBUMIN
                  value: 42
                  unit: g/L
                - code: ALT
                  value: 28
                  unit: U/L
                - code: ALP
                  value: 85
                  unit: U/L
                - code: AST
                  value: 24
                  unit: U/L
                - code: CALCIUM
                  value: 2.35
                  unit: mmol/L
                - code: CHOL
                  value: 5.2
                  unit: mmol/L
                - code: CYSTATIN_C
                  value: 0.95
                  unit: mg/L
                - code: GGT
                  value: 32
                  unit: U/L
                - code: HDL
                  value: 1.4
                  unit: mmol/L
                - code: CRP
                  value: 1.2
                  unit: mg/L
                - code: LDL
                  value: 3.1
                  unit: mmol/L
                - code: PHOSPHATE
                  value: 1.1
                  unit: mmol/L
                - code: URATE
                  value: 320
                  unit: µmol/L
                - code: HBA1C_MMOL_MOL
                  value: 38
                  unit: mmol/mol
              options:
                requestedOutputs:
                  - inference_score_v1
                  - json
                  - html
                requestedOutcomes:
                  - wellbeing.cardiovascular
                  - wellbeing.cognitive
                  - wellbeing.renal
                  - wellbeing.respiratory
      responses:
        '202':
          description: Accepted — submission persisted; pipeline job enqueued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TypeASubmissionAcceptedResponse'
              example:
                submissionId: aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa
                jobId: bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb
                partnerSubmissionId: partner-ext-sub-0001
                partnerSubjectId: partner-ext-pt-0001
                status: accepted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: Idempotency-Key reused with a different request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: IDEMPOTENCY_MISMATCH
                  message: >-
                    Idempotency-Key was already used with a different request
                    body
                  requestId: 550e8400-e29b-41d4-a716-446655440000
                  correlationId: corr-example-1
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - partnerApiKey: []
        - partnerBearer: []
components:
  parameters:
    HeaderCorrelationIdRequired:
      name: x-correlation-id
      in: header
      required: true
      schema:
        type: string
        minLength: 1
      description: >-
        Client-supplied correlation id for writes; bound to error logs and
        payloads where applicable.
    HeaderIdempotencyKeyRequired:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 1
      description: >-
        Client key for at-most-once submit semantics (24h scope). Reuse with the
        same body returns the same `submissionId`/`jobId`; reuse with a
        different body returns 409.
    HeaderRequestIdOptional:
      name: x-request-id
      in: header
      required: false
      schema:
        type: string
      description: Optional; echoed when possible. Server generates when absent.
  schemas:
    TypeASubmissionBody:
      type: object
      additionalProperties: false
      required:
        - schemaVersion
        - partnerId
        - partnerSubmissionId
        - partnerSubjectId
        - subject
        - options
      properties:
        schemaVersion:
          type: string
          enum:
            - canonical_submission_v1
        partnerId:
          type: string
          format: uuid
        partnerSubmissionId:
          type: string
          minLength: 1
          maxLength: 512
        partnerSubjectId:
          type: string
          minLength: 1
          maxLength: 512
        subject:
          $ref: '#/components/schemas/TypeASubject'
        markers:
          type: array
          items:
            $ref: '#/components/schemas/TypeAMarker'
        reportDocuments:
          type: array
          items:
            $ref: '#/components/schemas/TypeAReportDocumentMeta'
        questionnaire:
          $ref: '#/components/schemas/TypeAQuestionnaire'
        options:
          $ref: '#/components/schemas/TypeASubmissionOptions'
        sourceMetadata:
          $ref: '#/components/schemas/TypeASourceMetadata'
        clinicalExtensions:
          type: object
          maxProperties: 64
          additionalProperties: true
          description: >
            Optional partner extensions; keys scanned for disallowed direct
            identifiers. Rules enforced in Zod.
      description: >
        Canonical Type A ingestion JSON (`canonical_submission_v1`). At least
        one of `markers` or `reportDocuments`

        must be non-empty (Zod `superRefine`). Cross-field smoking and
        family-history rules are Zod-only.
    TypeASubmissionAcceptedResponse:
      type: object
      additionalProperties: false
      required:
        - submissionId
        - jobId
        - partnerSubmissionId
        - partnerSubjectId
        - status
      properties:
        submissionId:
          type: string
          format: uuid
        jobId:
          type: string
          format: uuid
        partnerSubmissionId:
          type: string
        partnerSubjectId:
          type: string
        status:
          type: string
          enum:
            - accepted
          description: >
            Partner-facing ingestion outcome for this endpoint. The persisted
            `Submission.status`

            in PostgreSQL continues to reflect pipeline state (e.g. PROCESSING).
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - requestId
          properties:
            code:
              type: string
              description: Machine-readable error code (e.g. VALIDATION_ERROR, NOT_FOUND).
            message:
              type: string
            requestId:
              type: string
            correlationId:
              type: string
              description: >-
                Present when the request established a correlation id (writes
                always send `x-correlation-id`).
            details:
              description: Optional structured validation or domain hints (shape varies).
      description: Matches `errorEnvelopeSchema` in src/lib/error-envelope.ts
    TypeASubject:
      type: object
      additionalProperties: false
      required:
        - demographics
      properties:
        demographics:
          $ref: '#/components/schemas/TypeASubjectDemographics'
        measurements:
          $ref: '#/components/schemas/TypeASubjectMeasurements'
        history:
          $ref: '#/components/schemas/TypeASubjectHistory'
        familyHistory:
          $ref: '#/components/schemas/TypeASubjectFamilyHistory'
    TypeAMarker:
      type: object
      additionalProperties: false
      required:
        - code
        - value
        - unit
      properties:
        code:
          type: string
          minLength: 1
          maxLength: 200
        value:
          oneOf:
            - type: string
              maxLength: 2000
            - type: number
        unit:
          type: string
          minLength: 1
          maxLength: 64
        observedAt:
          type: string
          format: date-time
    TypeAReportDocumentMeta:
      type: object
      additionalProperties: false
      required:
        - documentType
      properties:
        documentType:
          type: string
          minLength: 1
          maxLength: 200
        effectiveAt:
          type: string
          format: date-time
        sourceSystem:
          type: string
          maxLength: 200
        summaryText:
          type: string
          maxLength: 8000
    TypeAQuestionnaire:
      type: object
      additionalProperties: false
      properties:
        futureWellbeingImportance:
          type: string
          enum:
            - not_at_all
            - slightly
            - moderately
            - very
            - extremely
            - unknown
            - prefer_not_to_say
        futureWellbeingOutlook:
          type: string
          enum:
            - much_better
            - somewhat_better
            - about_the_same
            - somewhat_worse
            - much_worse
            - unknown
            - prefer_not_to_say
    TypeASubmissionOptions:
      type: object
      additionalProperties: false
      required:
        - requestedOutputs
      properties:
        requestedOutputs:
          type: array
          minItems: 1
          items:
            type: string
            enum:
              - inference_score_v1
              - score
              - json
              - pdf
              - html
        requestedOutcomes:
          type: array
          maxItems: 8
          items:
            type: string
            minLength: 1
            maxLength: 128
          description: >
            Optional IduScore outcome requests. **Preferred:** public outcome
            ids — the same values as

            **GET /v1/results** → `outcome.outcomeId`
            (`PartnerOutcomePublicId`), e.g. `wellbeing.cardiovascular`,

            `wellbeing.renal`, `wellbeing.cognitive`, `wellbeing.respiratory`
            (`wellbeing.kidney` and `renal.wellbeing`

            are accepted as synonyms for the renal/kidney registry outcome).
            Legacy string aliases (e.g.

            `cardiovascular_wellbeing_10y`) and internal registry stable ids are
            still accepted and normalized.

            Omitted → server default.
    TypeASourceMetadata:
      type: object
      additionalProperties: false
      properties:
        sourceSystem:
          type: string
          minLength: 1
          maxLength: 200
        sourceTimestamp:
          type: string
          format: date-time
        labName:
          type: string
          maxLength: 200
        facilityId:
          type: string
          maxLength: 200
        markerRanges:
          type: object
          maxProperties: 200
          description: >
            Optional lab-defined reference intervals keyed by blood marker code
            (e.g. `ALT`, `CHOL`, `HBA1C_MMOL_MOL`).

            When present for a marker, value validation uses these bounds
            instead of the default analytical preset;

            `unit` must match the preset required unit for that marker.
          additionalProperties:
            type: object
            additionalProperties: false
            required:
              - unit
              - lowerBound
              - upperBound
            properties:
              unit:
                type: string
                minLength: 1
                maxLength: 64
              lowerBound:
                type: number
              upperBound:
                type: number
    TypeASubjectDemographics:
      type: object
      additionalProperties: false
      required:
        - sexAtBirth
      properties:
        sexAtBirth:
          type: string
          enum:
            - male
            - female
        ageYears:
          type: integer
          minimum: 0
          maximum: 120
        birthYear:
          type: integer
          minimum: 1900
          maximum: 2100
        ethnicity:
          type: string
          maxLength: 200
        educationYears:
          type: integer
          minimum: 0
          maximum: 40
      description: >
        At least one of `ageYears` or `birthYear` is required at validation time
        (Zod `superRefine`).
    TypeASubjectMeasurements:
      type: object
      additionalProperties: false
      properties:
        weightKg:
          type: number
          minimum: 0
          maximum: 300
        heightCm:
          type: number
          minimum: 0
          maximum: 250
        bmi:
          type: number
          exclusiveMinimum: 0
          maximum: 100
        systolicBpMmhg:
          type: number
          exclusiveMinimum: 0
          maximum: 300
        systolicBp:
          type: number
          exclusiveMinimum: 0
          maximum: 300
        diastolicBp:
          type: number
          exclusiveMinimum: 0
          maximum: 300
    TypeASubjectHistory:
      type: object
      additionalProperties: false
      properties:
        overallHealth:
          type: string
          enum:
            - excellent
            - very_good
            - good
            - fair
            - poor
            - unknown
        smoking:
          $ref: '#/components/schemas/TypeASmoking'
        conditions:
          $ref: '#/components/schemas/TypeASubjectConditions'
        medications:
          $ref: '#/components/schemas/TypeASubjectMedications'
        alcoholUse:
          type: string
          enum:
            - 'yes'
            - 'no'
            - unknown
        alcoholDrinksPerWeek:
          type: number
        physicalActivityLevel:
          type: string
          enum:
            - low
            - moderate
            - high
        physicalActivityMetMinWeek:
          type: number
        dietQualityScore:
          type: number
    TypeASubjectFamilyHistory:
      type: object
      additionalProperties: false
      properties:
        father:
          $ref: '#/components/schemas/TypeASubjectFamilyParent'
        mother:
          $ref: '#/components/schemas/TypeASubjectFamilyParent'
    TypeASmoking:
      type: object
      additionalProperties: false
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - never
            - former
            - current
            - prefer_not_to_say
        pastFrequency:
          type: string
          enum:
            - none
            - light
            - moderate
            - heavy
            - unknown
        currentFrequency:
          type: string
          enum:
            - none
            - light
            - moderate
            - heavy
            - unknown
        currentCigsPerDay:
          type: number
          minimum: 0
          maximum: 200
        pastCigsPerDay:
          type: number
          minimum: 0
          maximum: 200
        startAge:
          type: integer
          minimum: 0
          maximum: 120
        stopAge:
          type: integer
          minimum: 0
          maximum: 120
      description: >
        Cross-field rules (never vs current vs former) enforced in Zod — see
        `canonical-type-a-v1.contract.ts`.
    TypeASubjectConditions:
      type: object
      additionalProperties: false
      properties:
        hasDiabetes:
          type: boolean
        hasDementia:
          type: boolean
        hasCardioCerebrovascular:
          type: boolean
        hasLungCancer:
          type: boolean
        hasKidneyDisease:
          type: boolean
    TypeASubjectMedications:
      type: object
      additionalProperties: false
      required:
        - takesRegularMedication
      properties:
        takesRegularMedication:
          type: boolean
        classes:
          type: array
          maxItems: 64
          items:
            type: string
            minLength: 1
            maxLength: 100
    TypeASubjectFamilyParent:
      type: object
      additionalProperties: false
      required:
        - aliveStatus
      properties:
        aliveStatus:
          type: string
          enum:
            - alive
            - deceased
            - unknown
        currentAge:
          type: integer
          minimum: 0
          maximum: 120
        deathAge:
          type: integer
          minimum: 0
          maximum: 120
        conditions:
          type: array
          maxItems: 32
          items:
            $ref: '#/components/schemas/TypeAFamilyHistoryConditionCode'
      description: |
        Conditional `deathAge` / `currentAge` rules enforced in Zod.
    TypeAFamilyHistoryConditionCode:
      type: string
      enum:
        - diabetes_mellitus
        - cardiovascular_disease
        - cerebrovascular_disease
        - dementia
        - alzheimer_disease
        - kidney_disease
        - lung_cancer
        - other_malignancy
        - hypertension
        - none_known
        - unknown
  responses:
    BadRequest:
      description: Validation or missing required headers / bad UUID parameter
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: VALIDATION_ERROR
              message: Invalid submission payload
              requestId: 550e8400-e29b-41d4-a716-446655440000
              correlationId: corr-example-1
              details: {}
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: INVALID_API_KEY
              message: Invalid or expired API key
              requestId: 550e8400-e29b-41d4-a716-446655440000
    Forbidden:
      description: >-
        Tenant inactive, `partnerId` mismatch, or submission restricted to
        another credential via `metadata.partnerId`
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    InternalError:
      description: Unhandled failure
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: INTERNAL_ERROR
              message: Internal server error
              requestId: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    partnerApiKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Plaintext API key issued for the tenant (stored hashed server-side).
    partnerBearer:
      type: http
      scheme: bearer
      bearerFormat: opaque
      description: Same secret as X-Api-Key, sent as a Bearer token.

````