openapi: 3.1.0
info:
  title: MediSynth API
  version: 1.0.0
  summary: Versioned API for deterministic synthetic patient cohorts and retained export artifacts.
  description: |
    MediSynth generates seedable synthetic patient cohorts, simulates upstream HIE/provider
    source variation, stores retained artifacts for 30 days, meters usage, and exposes
    downloadable JSON, NDJSON, FHIR, raw C-CDA-style, and raw HL7-style outputs for product
    demos, QA, migrations, and integration testing.

    Artifacts can return `409 artifact_not_ready` while a retained job is queued, running, processing, generating, in_progress, failed, stale, canceled, or still preparing export output.
servers:
  - url: https://api.cloud.medisynth.io/v1
    description: Production API edge
  - url: http://localhost:8081/v1
    description: Local API development
tags:
  - name: Health
  - name: Cohorts
  - name: Workspace Jobs
  - name: Artifacts
  - name: FHIR Bulk Export
  - name: Upstream Simulator
  - name: Reference Library
  - name: Billing
  - name: API Keys
  - name: Stripe
  - name: Admin
security:
  - bearerAuth: []
  - apiKeyAuth: []
paths:
  /v1/sso/discovery:
    get:
      tags: [SSO]
      operationId: discoverWorkspaceSSO
      security: []
      parameters:
        - { name: email, in: query, schema: { type: string, format: email } }
        - { name: domain, in: query, schema: { type: string } }
      responses:
        "200": { description: Workspace SSO discovery result. }
  /v1/workspace/tenants/{tenantID}/sso:
    parameters:
      - { name: tenantID, in: path, required: true, schema: { type: string } }
    get:
      tags: [SSO]
      operationId: getWorkspaceSSO
      x-required-role: admin
      responses: { "200": { description: OIDC configuration without its client secret. } }
    put:
      tags: [SSO]
      operationId: configureWorkspaceSSO
      x-required-role: owner
      requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/WorkspaceSSOConfig" } } } }
      responses: { "200": { description: Saved OIDC configuration. } }
  /v1/workspace/tenants/{tenantID}/scim-token:
    post:
      tags: [SCIM]
      operationId: rotateWorkspaceSCIMToken
      x-required-role: owner
      parameters:
        - { name: tenantID, in: path, required: true, schema: { type: string } }
      responses: { "201": { description: One-time plaintext SCIM bearer token. } }
  /v1/scim/v2/Users:
    get:
      tags: [SCIM]
      operationId: listSCIMUsers
      security: [{ scimBearerAuth: [] }]
      responses: { "200": { description: SCIM ListResponse. } }
    post:
      tags: [SCIM]
      operationId: createSCIMUser
      security: [{ scimBearerAuth: [] }]
      responses: { "201": { description: Provisioned SCIM user. } }
  /v1/scim/v2/Users/{id}:
    parameters:
      - { name: id, in: path, required: true, schema: { type: string } }
    get:
      tags: [SCIM]
      operationId: getSCIMUser
      security: [{ scimBearerAuth: [] }]
      responses: { "200": { description: SCIM user. } }
    put:
      tags: [SCIM]
      operationId: replaceSCIMUser
      security: [{ scimBearerAuth: [] }]
      responses: { "200": { description: Replaced SCIM user. } }
    patch:
      tags: [SCIM]
      operationId: patchSCIMUser
      security: [{ scimBearerAuth: [] }]
      responses: { "200": { description: Updated SCIM user. } }
  /v1/:
    get:
      tags: [Health]
      operationId: getApiRoot
      security: []
      summary: Read API root metadata.
      responses:
        "200":
          description: API root status.
          content:
            application/json:
              schema:
                type: object
                required: [service, status, version]
                properties:
                  service:
                    type: string
                    example: MediSynth API
                  status:
                    type: string
                    example: running
                  version:
                    type: string
                    example: v1
  /v1/heartbeat:
    get:
      tags: [Health]
      operationId: getHeartbeat
      security: []
      summary: Lightweight uptime probe.
      responses:
        "200":
          description: API is reachable.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Heartbeat"
    head:
      tags: [Health]
      operationId: headHeartbeat
      security: []
      summary: Lightweight uptime probe without a response body.
      responses:
        "200":
          description: API is reachable.
  /v1/status:
    get:
      tags: [Health]
      operationId: getStatus
      security: []
      summary: Read public product status.
      responses:
        "200":
          description: Current product status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusResponse"
    head:
      tags: [Health]
      operationId: headStatus
      security: []
      summary: Read public product status headers.
      responses:
        "200":
          description: Current product status is reachable.
  /v1/generate-patients:
    post:
      tags: [Cohorts]
      operationId: generatePatientsLegacy
      deprecated: true
      summary: Generate patients with the legacy smoke-test request contract.
      description: Prefer retained workspace cohort jobs for customer workloads.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GeneratePatientsRequest"
      responses:
        "200":
          description: Generated synthetic dataset.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GeneratedDataset"
        "422":
          $ref: "#/components/responses/InlineGenerationMemoryExceeded"
        default:
          $ref: "#/components/responses/Error"
  /v1/capabilities:
    get:
      tags: [Cohorts]
      operationId: getCapabilities
      summary: Discover platform capabilities (formats, limits, scenarios).
      description: >-
        Unauthenticated discovery surface: the supported export and document
        formats, request limits (max population, max formats), and the built-in
        scenarios — so SDKs and integrations can self-configure without
        hard-coding them.
      security: []
      responses:
        "200":
          description: Platform capabilities.
          content:
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/scenarios:
    get:
      tags: [Cohorts]
      operationId: listCohortScenarios
      summary: List built-in cohort recipes.
      responses:
        "200":
          description: Built-in deterministic cohort specs.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/CohortSpec"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/hie-providers:
    get:
      tags: [Cohorts]
      operationId: listHIEProviders
      summary: List built-in HIE provider profiles.
      responses:
        "200":
          description: Built-in HIE provider configurations.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HIEProvider"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/region-presets:
    get:
      tags: [Cohorts]
      operationId: listRegionPresets
      summary: List built-in geographic region presets.
      responses:
        "200":
          description: Built-in geographic region presets with demographics.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/RegionPreset"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/topology/validate:
    post:
      tags: [Cohorts]
      operationId: validateTopology
      summary: Validate a cohort topology.
      description: Accepts either a full cohort spec or a standalone HIE topology graph and reports cycles, dangling gateway references, and unreachable sources.
      requestBody:
        $ref: "#/components/requestBodies/TopologyValidateRequest"
      responses:
        "200":
          description: Topology validation report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TopologyValidationResponse"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/topology/preview:
    post:
      tags: [Cohorts]
      operationId: previewTopology
      summary: Preview delivery routes for source systems through a topology.
      description: Resolves the per-source document delivery hops for the supplied HIE topology. When no topology is supplied a default hub-and-spoke topology is generated.
      requestBody:
        $ref: "#/components/requestBodies/TopologyPreviewRequest"
      responses:
        "200":
          description: Per-source delivery routes.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TopologyPreviewResponse"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/topology/presets:
    get:
      tags: [Cohorts]
      operationId: listTopologyPresets
      summary: List built-in HIE topology presets.
      responses:
        "200":
          description: Built-in topology templates.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TopologyPreset"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/validate:
    post:
      tags: [Cohorts]
      operationId: validateCohort
      summary: Validate a cohort spec without generating records.
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: Validation report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ValidationReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/preview:
    post:
      tags: [Cohorts]
      operationId: previewCohort
      summary: Preview patient counts, provider spread, and identity variance.
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: Cohort preview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortPreview"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/generate:
    post:
      tags: [Cohorts]
      operationId: generateCohortInline
      deprecated: true
      summary: Generate an inline cohort dataset for local diagnostics.
      description: Prefer retained workspace cohort jobs for customer workloads.
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: Generated synthetic dataset.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GeneratedDataset"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/export/fhir:
    post:
      tags: [Cohorts]
      operationId: exportCohortFhir
      summary: Generate FHIR Bundle and NDJSON artifacts inline.
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: FHIR export envelope.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FhirExport"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/export/ndjson/{fileName}:
    post:
      tags: [Cohorts]
      operationId: exportCohortNdjsonFile
      summary: Generate and stream one NDJSON artifact inline.
      parameters:
        - $ref: "#/components/parameters/FileName"
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: NDJSON file content.
          content:
            application/x-ndjson:
              schema:
                type: string
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/cohorts/export/flat/{fileName}:
    post:
      tags: [Cohorts]
      operationId: exportCohortFlatFile
      summary: Generate and stream one flat-file artifact inline.
      parameters:
        - $ref: "#/components/parameters/FileName"
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "200":
          description: Flat-file artifact content. Supports CSV, JSON, plain-text, and ZIP artifacts such as X12 837/835 stubs, HL7 v2 ORU_R01 message concatenations, and the patient-documents.zip archive.
          content:
            text/csv:
              schema:
                type: string
            text/plain:
              schema:
                type: string
            application/json:
              schema:
                type: string
            application/zip:
              schema:
                type: string
                format: binary
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/retrieve:
    post:
      tags: [Upstream Simulator]
      operationId: retrieveUpstreamSimulatorDocuments
      summary: Retrieve source-system views for one synthetic person.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpstreamRetrieveRequest"
      responses:
        "200":
          description: Source-system retrieval responses with documents and transform hints.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpstreamRetrieveResponse"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/xca/query:
    post:
      tags: [Upstream Simulator]
      operationId: xcaQuerySimulatorDocuments
      summary: Query an IHE XCA responding gateway for simulated document metadata.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpstreamRetrieveRequest"
      responses:
        "200":
          description: IHE XCA AdhocQueryResponse SOAP envelope with XDS metadata. ExtrinsicObject entries include an availabilityStatus slot and a status attribute (Approved or Deprecated). Lifecycle associations (RPLC, APND, XFRM) are emitted when documents declare a parent relationship.
          content:
            application/soap+xml:
              schema:
                type: string
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/xcpd/discover:
    post:
      tags: [Upstream Simulator]
      operationId: xcpdDiscoverSimulatorPatients
      summary: Discover patients across simulated communities using IHE XCPD-style demographics matching.
      description: Returns deterministic exact, probable, and possible source-record matches, including duplicate and ambiguous identities. Each match contains an xcaQuery object that can be sent to the XCA query endpoint.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/XCPDDiscoveryRequest"
      responses:
        "200":
          description: Patient discovery results grouped by input query.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/XCPDDiscoveryResponse"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/xca/retrieve:
    post:
      tags: [Upstream Simulator]
      operationId: xcaRetrieveSimulatorDocuments
      summary: Retrieve documents from an IHE XCA responding gateway.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpstreamRetrieveRequest"
      responses:
        "200":
          description: IHE XCA RetrieveDocumentSetResponse SOAP envelope with base64 document payloads.
          content:
            application/soap+xml:
              schema:
                type: string
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/trust/status:
    get:
      tags: [Upstream Simulator]
      operationId: getUpstreamTrustStatus
      summary: Summarize endpoint trust status for a generated HIE cohort.
      description: Generates a small cohort (population 4) from the supplied spec and returns a compact trust status summary derived from endpoint trust drifts.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpstreamRetrieveRequest"
      responses:
        "200":
          description: Trust status summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrustStatusResponse"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/upstream/trust/audit:
    post:
      tags: [Upstream Simulator]
      operationId: upstreamTrustAudit
      summary: Generate a FHIR trust audit bundle for a synthetic cohort.
      description: Generates a cohort from the supplied spec and returns a FHIR Bundle containing Endpoint, OrganizationAffiliation, AuditEvent, and break-glass release-routing Provenance resources.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpstreamRetrieveRequest"
      responses:
        "200":
          description: Structured trust-audit result with endpoint, certificate, consent, drift, and FHIR evidence.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrustAuditResult"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "422":
          $ref: "#/components/responses/InlineGenerationRejected"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/directory/endpoint/{endpointID}:
    get:
      tags: [Simulator Directory]
      operationId: getSimulatorDirectoryEndpoint
      summary: Look up a mocked HIE Endpoint directory entry.
      parameters:
        - name: endpointID
          in: path
          required: true
          schema:
            type: string
        - name: sourceSystems
          in: query
          schema:
            type: string
            example: regional-hie,lab-network,claims-feed
        - name: spec
          in: query
          schema:
            type: string
      responses:
        "200":
          description: FHIR R4 Endpoint resource.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DirectoryEndpoint"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/directory/organization-affiliation/{affiliationID}:
    get:
      tags: [Simulator Directory]
      operationId: getSimulatorDirectoryAffiliation
      summary: Look up a mocked HIE OrganizationAffiliation directory entry.
      parameters:
        - name: affiliationID
          in: path
          required: true
          schema:
            type: string
        - name: sourceSystems
          in: query
          schema:
            type: string
            example: regional-hie,lab-network,claims-feed
        - name: spec
          in: query
          schema:
            type: string
      responses:
        "200":
          description: FHIR R4 OrganizationAffiliation resource.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DirectoryAffiliation"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/directory/network/{networkID}/endpoints:
    get:
      tags: [Simulator Directory]
      operationId: getSimulatorDirectoryNetworkEndpoints
      summary: List mocked Endpoint resources belonging to a network.
      parameters:
        - name: networkID
          in: path
          required: true
          schema:
            type: string
        - name: sourceSystems
          in: query
          schema:
            type: string
            example: regional-hie,lab-network,claims-feed
        - name: spec
          in: query
          schema:
            type: string
      responses:
        "200":
          description: FHIR R4 Bundle of Endpoint resources.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DirectoryEndpointBundle"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/directory/endpoints:
    get:
      tags: [Simulator Directory]
      operationId: getSimulatorDirectoryOrganizationEndpoints
      summary: Query mocked Endpoint resources by managing organization.
      parameters:
        - name: organization
          in: query
          required: true
          schema:
            type: string
        - name: sourceSystems
          in: query
          schema:
            type: string
            example: regional-hie,lab-network,claims-feed
        - name: spec
          in: query
          schema:
            type: string
      responses:
        "200":
          description: FHIR R4 Bundle of Endpoint resources.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DirectoryEndpointBundle"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/simulator/directory/affiliations:
    get:
      tags: [Simulator Directory]
      operationId: getSimulatorDirectoryAffiliations
      summary: Query mocked OrganizationAffiliation resources.
      parameters:
        - name: organization
          in: query
          schema:
            type: string
        - name: network
          in: query
          schema:
            type: string
        - name: sourceSystems
          in: query
          schema:
            type: string
            example: regional-hie,lab-network,claims-feed
        - name: spec
          in: query
          schema:
            type: string
      responses:
        "200":
          description: FHIR R4 Bundle of OrganizationAffiliation resources.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DirectoryAffiliationBundle"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/conformance/packs:
    get:
      tags: [HIE Scenario Checks]
      operationId: listConformancePacks
      security: []
      summary: List available HIE interoperability scenario check packs.
      responses:
        "200":
          description: HIE interoperability scenario pack summaries. These routing, trust, and lifecycle checks are not FHIR or IHE certification tests.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConformancePackListResponse"
        default:
          $ref: "#/components/responses/Error"
  /v1/conformance/packs/{packID}/run:
    post:
      tags: [HIE Scenario Checks]
      operationId: runConformancePack
      summary: Run a single HIE interoperability scenario check pack.
      parameters:
        - name: packID
          in: path
          required: true
          schema:
            type: string
        - name: outputFormat
          in: query
          required: false
          description: CI result serialization. JSON is the default; JUnit XML and SARIF 2.1.0 are available for CI ingestion.
          schema:
            type: string
            enum: [json, junit, sarif]
            default: json
      responses:
        "200":
          description: HIE scenario run result with per-assertion outcomes. This checks generated routing, trust, or lifecycle patterns; it does not certify FHIR or IHE conformance.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConformancePackResult"
            application/xml:
              schema:
                type: string
              example: '<?xml version="1.0" encoding="UTF-8"?><testsuite name="Break-glass denial" tests="1" failures="0"><testcase name="break_glass_required_exists" classname="break-glass-denial"/></testsuite>'
            application/sarif+json:
              schema:
                type: object
                description: SARIF 2.1.0 log with one result per scenario assertion.
        "402":
          $ref: "#/components/responses/PaymentRequired"
        "404":
          $ref: "#/components/responses/NotFound"
        default:
          $ref: "#/components/responses/Error"
  /v1/fhir/metadata:
    get:
      tags: [FHIR REST]
      operationId: getFhirMetadata
      security: []
      summary: FHIR R4 CapabilityStatement for the retained-cohort read/search surface.
      description: >
        Returns the FHIR R4 (4.0.1) CapabilityStatement for MediSynth's read/search
        surface over retained synthetic cohorts. The statement is explicit about
        which resource interactions are enabled — metadata itself is public and
        unmetered; gated read/search operations (when enabled) use the fhir-rest
        entitlement and the fhir.rest.calls usage dimension.
      responses:
        "200":
          description: FHIR R4 CapabilityStatement.
          content:
            application/fhir+json:
              schema:
                $ref: "#/components/schemas/FHIRCapabilityStatement"
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRCapabilityStatement"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Patient:
    get:
      tags: [FHIR REST]
      operationId: searchFhirPatients
      summary: Search FHIR Patients in a retained cohort.
      description: >
        Bounded v1 search over a retained cohort's FHIR Patients (name/given:
        case-insensitive contains; birthdate: exact; gender: exact), with keyset
        pagination (default 50, max 100 entries). Requires the fhir-rest
        entitlement and meters one fhir.rest.calls unit. Search is supported
        for cohorts up to 250,000 patients; larger cohorts return an actionable
        error and remain downloadable via artifacts.
      parameters:
        - $ref: "#/components/parameters/CohortJob"
        - name: name
          in: query
          schema: { type: string }
          description: Case-insensitive substring match on family name.
        - name: given
          in: query
          schema: { type: string }
          description: Case-insensitive substring match on given names.
        - name: birthdate
          in: query
          schema: { type: string, format: date }
        - name: gender
          in: query
          schema: { type: string, enum: [female, male, other, unknown] }
        - name: _count
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - name: _cursor
          in: query
          schema: { type: string }
          description: Opaque keyset cursor from a previous page's next link.
      responses:
        "200":
          description: FHIR searchset Bundle.
          content:
            application/fhir+json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
        "402":
          description: The fhir-rest entitlement is required (upgrade).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: The cohort exceeds the 250,000-patient search cap.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Patient/{patientID}:
    get:
      tags: [FHIR REST]
      operationId: getFhirPatient
      summary: Read one FHIR Patient by id from a retained cohort.
      description: >
        Returns the FHIR Patient resource for the given id from the resolved
        retained cohort (explicit cohortJob or the tenant's latest available
        job). Requires the fhir-rest entitlement and meters one fhir.rest.calls
        unit. ID reads remain available for cohorts above the search cap.
      parameters:
        - name: patientID
          in: path
          required: true
          schema: { type: string }
        - $ref: "#/components/parameters/CohortJob"
      responses:
        "200":
          description: FHIR Patient resource.
          content:
            application/fhir+json:
              schema: { type: object }
            application/json:
              schema: { type: object }
        "402":
          description: The fhir-rest entitlement is required (upgrade).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: No Patient with that id exists in the cohort.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Observation:
    get:
      tags: [FHIR REST]
      operationId: searchFhirObservations
      summary: Search FHIR Observations in a retained cohort.
      description: >
        Bounded search over a retained cohort's FHIR Observations (code/category:
        token match; patient: reference match), keyset pagination. Requires the
        fhir-rest entitlement and meters one fhir.rest.calls unit.
      parameters:
        - $ref: "#/components/parameters/CohortJob"
        - name: code
          in: query
          schema: { type: string }
        - name: category
          in: query
          schema: { type: string }
        - name: patient
          in: query
          schema: { type: string }
        - name: _count
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - name: _cursor
          in: query
          schema: { type: string }
      responses:
        "200":
          description: FHIR searchset Bundle.
          content:
            application/fhir+json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
        "402":
          description: The fhir-rest entitlement is required (upgrade).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Observation/{resourceID}:
    get:
      tags: [FHIR REST]
      operationId: getFhirObservation
      summary: Read one FHIR Observation by id from a retained cohort.
      parameters:
        - name: resourceID
          in: path
          required: true
          schema: { type: string }
        - $ref: "#/components/parameters/CohortJob"
      responses:
        "200":
          description: FHIR Observation resource.
          content:
            application/fhir+json:
              schema: { type: object }
            application/json:
              schema: { type: object }
        "404":
          description: No Observation with that id exists in the cohort.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Condition:
    get:
      tags: [FHIR REST]
      operationId: searchFhirConditions
      summary: Search FHIR Conditions in a retained cohort.
      parameters:
        - $ref: "#/components/parameters/CohortJob"
        - name: code
          in: query
          schema: { type: string }
        - name: patient
          in: query
          schema: { type: string }
        - name: _count
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - name: _cursor
          in: query
          schema: { type: string }
      responses:
        "200":
          description: FHIR searchset Bundle.
          content:
            application/fhir+json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/Condition/{resourceID}:
    get:
      tags: [FHIR REST]
      operationId: getFhirCondition
      summary: Read one FHIR Condition by id from a retained cohort.
      parameters:
        - name: resourceID
          in: path
          required: true
          schema: { type: string }
        - $ref: "#/components/parameters/CohortJob"
      responses:
        "200":
          description: FHIR Condition resource.
          content:
            application/fhir+json:
              schema: { type: object }
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/DocumentReference:
    get:
      tags: [FHIR REST]
      operationId: searchFhirDocumentReferences
      summary: Search FHIR DocumentReferences in a retained cohort.
      parameters:
        - $ref: "#/components/parameters/CohortJob"
        - name: type
          in: query
          schema: { type: string }
        - name: patient
          in: query
          schema: { type: string }
        - name: _count
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - name: _cursor
          in: query
          schema: { type: string }
      responses:
        "200":
          description: FHIR searchset Bundle.
          content:
            application/fhir+json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBundle"
        default:
          $ref: "#/components/responses/Error"

  /v1/fhir/DocumentReference/{resourceID}:
    get:
      tags: [FHIR REST]
      operationId: getFhirDocumentReference
      summary: Read one FHIR DocumentReference by id from a retained cohort.
      parameters:
        - name: resourceID
          in: path
          required: true
          schema: { type: string }
        - $ref: "#/components/parameters/CohortJob"
      responses:
        "200":
          description: FHIR DocumentReference resource.
          content:
            application/fhir+json:
              schema: { type: object }
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"

  /v1/reference/ccda/vendors:
    get:
      tags: [Reference Library]
      operationId: listReferenceCcdaVendors
      security: []
      summary: List vendors in the C-CDA reference corpus.
      description: >
        Browse the vendored real-world C-CDA R2.1 reference corpus (synthetic ONC
        certification samples describing fictional patients — no PHI). Returns the
        vendor directories with document counts.
      responses:
        "200":
          description: Vendor directories with document counts.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReferenceVendorList"
        default:
          $ref: "#/components/responses/Error"
  /v1/reference/ccda/documents:
    get:
      tags: [Reference Library]
      operationId: listReferenceCcdaDocuments
      security: []
      summary: List reference C-CDA documents with structural metadata.
      parameters:
        - name: vendor
          in: query
          required: false
          schema:
            type: string
          description: Filter documents to a single vendor directory.
      responses:
        "200":
          description: Reference documents with detected sections and templateIds.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReferenceDocumentList"
        default:
          $ref: "#/components/responses/Error"
  /v1/reference/ccda/profile:
    get:
      tags: [Reference Library]
      operationId: getReferenceCcdaGeneratedProfile
      security: []
      summary: Structural profile of a MediSynth-generated C-CDA.
      description: >
        Returns the document type, header templateIds, and section list of a
        MediSynth-generated C-CDA, parsed with the same extractor used for the
        reference corpus so a real vendor document can be compared against
        MediSynth's own generated output.
      responses:
        "200":
          description: Generated C-CDA structural profile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReferenceGeneratedProfile"
        default:
          $ref: "#/components/responses/Error"
  /v1/reference/ccda/documents/{documentID}:
    get:
      tags: [Reference Library]
      operationId: getReferenceCcdaDocument
      security: []
      summary: Read one reference C-CDA document's metadata.
      parameters:
        - name: documentID
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Reference document metadata.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReferenceDocument"
        "404":
          description: Reference document not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"
  /v1/reference/ccda/documents/{documentID}/content:
    get:
      tags: [Reference Library]
      operationId: downloadReferenceCcdaDocument
      security: []
      summary: Stream the raw C-CDA XML for one reference document.
      parameters:
        - name: documentID
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Raw C-CDA R2.1 document.
          content:
            application/xml:
              schema:
                type: string
        "404":
          description: Reference document not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          $ref: "#/components/responses/Error"
  /v1/communications/subscriptions:
    post:
      tags: [Communications]
      operationId: subscribeCommunications
      summary: Subscribe to product or incident communications.
      description: Public product and status pages use this endpoint to store email preferences for product updates, planned maintenance, incident updates, and resolutions.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CommunicationSubscriptionRequest"
      responses:
        "201":
          description: Communication subscription preference saved.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CommunicationSubscription"
        default:
          $ref: "#/components/responses/Error"
  /v1/communications/subscriptions/preferences:
    get:
      tags: [Communications]
      operationId: getCommunicationPreferencesPage
      summary: Render a branded communication preferences page.
      description: Browser-safe preferences endpoint for product and incident email footers. The page lets recipients update topic selections with the server-generated footer token.
      security: []
      parameters:
        - in: query
          name: token
          required: true
          schema:
            type: string
            minLength: 1
          description: Server-generated communication preferences token from the email footer URL.
      responses:
        "200":
          description: Communication preferences page.
          content:
            text/html:
              schema:
                type: string
        "404":
          description: Preferences token was invalid or expired.
          content:
            text/html:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Communications]
      operationId: updateCommunicationPreferencesPage
      summary: Update communication preferences from a branded form.
      description: Saves selected product and incident email topics from the token-backed preferences page. Submitting no topics marks the subscription inactive.
      security: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required: [token]
              properties:
                token:
                  type: string
                  minLength: 1
                topics:
                  type: array
                  items:
                    type: string
                    enum: [product-updates, incident-updates]
      responses:
        "200":
          description: Updated communication preferences page.
          content:
            text/html:
              schema:
                type: string
        "404":
          description: Preferences token was invalid or expired.
          content:
            text/html:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
  /v1/communications/subscriptions/unsubscribe:
    get:
      tags: [Communications]
      operationId: unsubscribeCommunicationsPage
      summary: Unsubscribe from a branded email link.
      description: Browser-safe unsubscribe endpoint for product and incident email footers. The response is a simple confirmation page and never echoes the token.
      security: []
      parameters:
        - in: query
          name: token
          required: true
          schema:
            type: string
            minLength: 1
          description: Server-generated unsubscribe token from the email footer URL.
      responses:
        "200":
          description: Communication subscription preference marked inactive and rendered as a confirmation page.
          content:
            text/html:
              schema:
                type: string
        "404":
          description: Unsubscribe token was invalid or expired.
          content:
            text/html:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Communications]
      operationId: unsubscribeCommunications
      summary: Unsubscribe from product or incident communications.
      description: Public branded email footers call this endpoint with a server-generated token. The token is not returned in public responses.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CommunicationUnsubscribeRequest"
      responses:
        "200":
          description: Communication subscription preference marked inactive.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CommunicationSubscription"
        "404":
          $ref: "#/components/responses/Error"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/plans:
    get:
      tags: [Billing]
      operationId: listBillingPlans
      summary: List available plans, quotas, and overage limits.
      responses:
        "200":
          description: Billing plans.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BillingPlan"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/pricing:
    get:
      tags: [Billing]
      operationId: getBillingPricing
      summary: Public marketing-facing pricing catalog.
      description: Returns the same numeric plan values as /v1/billing/plans plus presentation fields (highlights, taglines, featured flags) used by the landing page. This endpoint is public and unauthenticated so the static pricing fallback can hydrate from the live catalog.
      responses:
        "200":
          description: Pricing model.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PricingModel"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me:
    get:
      tags: [Billing]
      operationId: getCurrentBillingTenant
      summary: Get or create the authenticated user's billing workspace.
      description: Uses the authenticated email claim to return the existing tenant summary or create a new workspace when the user signs in for the first time.
      responses:
        "200":
          description: Current tenant summary for the authenticated account.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/export:
    get:
      tags: [Billing]
      operationId: exportCurrentAccountData
      summary: Download a complete account data export.
      description: Returns a JSON document containing the tenant profile, plan, usage summary, full usage ledger, artifact-access ledger, credit transactions, coupon redemptions, account activity, saved recipes, and redacted API-key metadata. Generated cohort artifacts are excluded; they contain only synthetic patients, are downloadable per job, and expire after the retention window.
      responses:
        "200":
          description: Account data export document delivered as a JSON attachment.
          content:
            application/json:
              schema:
                type: object
                required: [schemaVersion, generatedAt, account]
                properties:
                  schemaVersion:
                    type: integer
                  generatedAt:
                    type: string
                  notes:
                    type: string
                  account:
                    $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/account/deletion:
    post:
      tags: [Billing]
      operationId: requestCurrentAccountDeletion
      summary: Request account deletion (grace period + purge).
      description: Deactivates the workspace immediately - all active API keys are revoked and generation, checkout, and key issuance are blocked - and schedules a hard purge after a 30-day grace window. During grace the deletion can be canceled and login keeps working. At purge time the sign-in user is deleted, cohort jobs and retained artifacts are removed, and the tenant record is anonymized; usage and payment records are retained without personal identifiers under the legal-obligation basis.
      responses:
        "202":
          description: Deletion scheduled; tenant summary reflects the pending state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Billing]
      operationId: cancelCurrentAccountDeletion
      summary: Cancel a pending account deletion during the grace window.
      description: Reactivates the workspace. Previously revoked API keys stay revoked; issue or rotate keys to restore programmatic access.
      responses:
        "200":
          description: Deletion canceled; tenant summary reflects the reactivated state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/api-keys:
    post:
      tags: [API Keys]
      operationId: issueCurrentBillingApiKey
      summary: Issue an API key for the authenticated user's workspace.
      description: Derives the tenant from the verified session email. The one-time secret is returned only at creation.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/APIKeyNameRequest"
      responses:
        "201":
          description: API key metadata plus one-time secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/api-keys/{prefix}:
    delete:
      tags: [API Keys]
      operationId: revokeCurrentBillingApiKey
      summary: Revoke an API key for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - $ref: "#/components/parameters/APIKeyPrefix"
      responses:
        "200":
          description: Revoked API key metadata.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/api-keys/{prefix}/rotate:
    post:
      tags: [API Keys]
      operationId: rotateCurrentBillingApiKey
      summary: Rotate an API key for the authenticated user's workspace.
      description: Derives the tenant from the verified session email, revokes the old secret, and returns a replacement one-time secret.
      parameters:
        - $ref: "#/components/parameters/APIKeyPrefix"
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/APIKeyNameRequest"
      responses:
        "201":
          description: Replacement API key metadata plus one-time secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/usage/export:
    get:
      tags: [Billing]
      operationId: exportCurrentBillingUsage
      summary: Export usage ledger rows for the authenticated user's workspace.
      description: Derives the tenant from the verified session email. Date filters accept RFC3339 timestamps or YYYY-MM-DD dates.
      parameters:
        - name: format
          in: query
          schema:
            type: string
            enum: [json, csv]
            default: json
        - name: from
          in: query
          schema:
            type: string
          description: Inclusive lower bound as RFC3339 or YYYY-MM-DD.
        - name: to
          in: query
          schema:
            type: string
          description: Inclusive upper bound as RFC3339 or YYYY-MM-DD.
      responses:
        "200":
          description: Usage ledger export.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageExport"
            text/csv:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/usage-alerts:
    get:
      tags: [Billing]
      operationId: listCurrentUsageAlerts
      summary: List usage alerts for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      responses:
        "200":
          description: Workspace usage alerts.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlertList"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Billing]
      operationId: createCurrentUsageAlert
      summary: Create a usage alert threshold for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUsageAlertRequest"
      responses:
        "201":
          description: Usage alert created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/usage-alerts/{alertID}:
    get:
      tags: [Billing]
      operationId: getCurrentUsageAlert
      summary: Read a single usage alert for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - $ref: "#/components/parameters/AlertID"
      responses:
        "200":
          description: Usage alert details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Billing]
      operationId: updateCurrentUsageAlert
      summary: Update a usage alert threshold for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - $ref: "#/components/parameters/AlertID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateUsageAlertRequest"
      responses:
        "200":
          description: Usage alert updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Billing]
      operationId: deleteCurrentUsageAlert
      summary: Delete a usage alert for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - $ref: "#/components/parameters/AlertID"
      responses:
        "204":
          description: Usage alert deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/checkout-sessions:
    post:
      tags: [Billing]
      operationId: createCurrentBillingCheckoutSession
      summary: Create a Stripe-backed checkout session for the authenticated user's workspace.
      description: Derives the tenant from the verified session email for credit top-ups and subscription plan checkout.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CheckoutSessionRequest"
      responses:
        "201":
          description: Checkout session.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutSession"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/portal-sessions:
    post:
      tags: [Billing]
      operationId: createCurrentBillingPortalSession
      summary: Create a Stripe Billing Portal session for the authenticated user's workspace.
      description: Derives the tenant from the verified session email and requires a completed Stripe checkout with a stored customer ID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillingPortalSessionRequest"
      responses:
        "201":
          description: Billing portal session.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillingPortalSession"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/coupons/redemptions:
    post:
      tags: [Billing]
      operationId: redeemCurrentBillingCoupon
      summary: Redeem a coupon for the authenticated user's workspace.
      description: Derives the tenant from the verified session email and returns the updated tenant summary.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RedeemCouponRequest"
      responses:
        "201":
          description: Updated tenant summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/invoices:
    get:
      tags: [Billing]
      operationId: listCurrentBillingInvoices
      summary: List finalized invoices for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: A page of invoices, newest first. `nextCursor` is present when more pages remain.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceListResponse"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/invoices/preview:
    get:
      tags: [Billing]
      operationId: previewCurrentBillingInvoice
      summary: Preview the current billing period invoice.
      description: Returns a draft invoice reflecting current usage and plan without persisting it.
      responses:
        "200":
          description: Draft invoice preview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Invoice"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/invoices/{invoiceID}:
    get:
      tags: [Billing]
      operationId: getCurrentBillingInvoice
      summary: Read a specific invoice for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      parameters:
        - name: invoiceID
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Invoice details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Invoice"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/plan/change:
    post:
      tags: [Billing]
      operationId: requestCurrentPlanChange
      summary: Request a plan change for the authenticated user's workspace.
      description: Creates a pending plan change. Enterprise plan changes require support contact.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlanChangeRequest"
      responses:
        "201":
          description: Pending plan change created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PendingPlanChange"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Billing]
      operationId: cancelCurrentPlanChange
      summary: Cancel a pending plan change for the authenticated user's workspace.
      description: Removes any pending plan change request.
      responses:
        "204":
          description: Pending plan change canceled.
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/me/plan/preview:
    post:
      tags: [Billing]
      operationId: previewCurrentPlanChange
      summary: Preview a plan change for the authenticated user's workspace.
      description: Returns the projected impact of a plan change without committing it.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlanPreviewRequest"
      responses:
        "200":
          description: Plan change preview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlanPreviewResponse"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants:
    post:
      tags: [Billing]
      operationId: createBillingTenant
      summary: Create a tenant workspace for the authenticated account.
      description: |
        Production tenant creation requires a verified bearer session. Non-admin
        self-service creation binds the workspace email to the verified claim and
        starts on the free plan; paid plan upgrades settle through Stripe checkout
        webhooks or admin-managed Enterprise workflows.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTenantRequest"
      responses:
        "201":
          description: Created tenant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Tenant"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}:
    get:
      tags: [Billing]
      operationId: getBillingTenant
      summary: Read tenant summary, usage, API keys, coupons, and activity.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Tenant summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/api-keys:
    post:
      tags: [API Keys]
      operationId: issueBillingApiKey
      summary: Issue a named tenant API key.
      description: The one-time secret is returned only at creation.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/APIKeyNameRequest"
      responses:
        "201":
          description: API key metadata plus one-time secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/api-keys/{prefix}:
    delete:
      tags: [API Keys]
      operationId: revokeBillingApiKey
      summary: Revoke an active tenant API key.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/APIKeyPrefix"
      responses:
        "200":
          description: Revoked API key metadata.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/api-keys/{prefix}/rotate:
    post:
      tags: [API Keys]
      operationId: rotateBillingApiKey
      summary: Rotate an active tenant API key.
      description: Revokes the old secret and returns a replacement one-time secret.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/APIKeyPrefix"
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/APIKeyNameRequest"
      responses:
        "201":
          description: Replacement API key metadata plus one-time secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIKey"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/usage:
    post:
      tags: [Billing]
      operationId: recordBillingUsage
      summary: Record external usage for a tenant (advanced).
      description: >-
        Advanced external-metering route. MediSynth generation, simulation,
        conversion, and delivery workflows record their own usage automatically;
        do not submit those events again. Use this endpoint only for an authorized
        workflow that is not already metered by the service. The event is
        idempotent when the caller supplies a stable Idempotency-Key.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UsageRecordRequest"
      responses:
        "202":
          description: Usage accepted.
          content:
            application/json:
              schema:
                type: object
                required: [status]
                properties:
                  status:
                    type: string
                    example: accepted
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/usage/export:
    get:
      tags: [Billing]
      operationId: exportBillingUsage
      summary: Export tenant usage ledger rows.
      description: Returns persisted usage ledger rows for billing review, support reconciliation, and customer admin reporting. Date filters accept RFC3339 timestamps or YYYY-MM-DD dates.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - name: format
          in: query
          schema:
            type: string
            enum: [json, csv]
            default: json
        - name: from
          in: query
          schema:
            type: string
          description: Inclusive lower bound as RFC3339 or YYYY-MM-DD.
        - name: to
          in: query
          schema:
            type: string
          description: Inclusive upper bound as RFC3339 or YYYY-MM-DD.
      responses:
        "200":
          description: Usage ledger export.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageExport"
            text/csv:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/usage-alerts:
    get:
      tags: [Billing]
      operationId: listUsageAlerts
      summary: List usage alerts for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Tenant usage alerts.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlertList"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Billing]
      operationId: createUsageAlert
      summary: Create a usage alert threshold for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUsageAlertRequest"
      responses:
        "201":
          description: Usage alert created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/usage-alerts/{alertID}:
    get:
      tags: [Billing]
      operationId: getUsageAlert
      summary: Read a single usage alert.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/AlertID"
      responses:
        "200":
          description: Usage alert details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Billing]
      operationId: updateUsageAlert
      summary: Update a usage alert threshold.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/AlertID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateUsageAlertRequest"
      responses:
        "200":
          description: Usage alert updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageAlert"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Billing]
      operationId: deleteUsageAlert
      summary: Delete a usage alert.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/AlertID"
      responses:
        "204":
          description: Usage alert deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/checkout-sessions:
    post:
      tags: [Billing]
      operationId: createBillingCheckoutSession
      summary: Create a Stripe-backed checkout session.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CheckoutSessionRequest"
      responses:
        "201":
          description: Checkout session.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckoutSession"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/portal-sessions:
    post:
      tags: [Billing]
      operationId: createBillingPortalSession
      summary: Create a Stripe Billing Portal session for a tenant.
      description: Requires a completed Stripe checkout with a stored customer ID. The customer ID is not returned in tenant summaries.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillingPortalSessionRequest"
      responses:
        "201":
          description: Billing portal session.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillingPortalSession"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/tenants/{tenantID}/coupons/redemptions:
    post:
      tags: [Billing]
      operationId: redeemBillingCoupon
      summary: Redeem a coupon for free generation allowance.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RedeemCouponRequest"
      responses:
        "201":
          description: Updated tenant summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/billing/stripe/webhook:
    post:
      tags: [Stripe]
      operationId: handleStripeWebhook
      summary: Receive signed Stripe checkout events.
      description: Stripe calls this endpoint directly; customer API clients should not call it.
      x-internal: true
      security: []
      parameters:
        - name: Stripe-Signature
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
      responses:
        "200":
          description: Event accepted.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/recipes:
    get:
      tags: [Workspace Recipes]
      operationId: listCurrentWorkspaceTenantRecipes
      summary: List saved cohort recipes for the authenticated user's workspace.
      description: Derives the tenant from the verified session email. Browser console clients should prefer this route over route-supplied tenant IDs.
      responses:
        "200":
          description: Authenticated workspace saved recipes.
          content:
            application/json:
              schema:
                type: object
                required: [recipes]
                properties:
                  recipes:
                    type: array
                    items:
                      $ref: "#/components/schemas/TenantRecipe"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Recipes]
      operationId: saveCurrentWorkspaceTenantRecipe
      summary: Save or update a cohort recipe for the authenticated user's workspace.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SaveTenantRecipeRequest"
      responses:
        "201":
          description: Saved workspace recipe.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantRecipe"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/recipes/{recipeID}:
    delete:
      tags: [Workspace Recipes]
      operationId: deleteCurrentWorkspaceTenantRecipe
      summary: Delete a saved cohort recipe from the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/RecipeID"
      responses:
        "204":
          description: Recipe deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/recipes:
    get:
      tags: [Workspace Recipes]
      operationId: listWorkspaceTenantRecipes
      summary: List saved cohort recipes for a tenant.
      description: Returns tenant-scoped cohort templates saved from the console. These recipes can be loaded, edited, and reused for repeatable generation jobs.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Tenant saved recipes.
          content:
            application/json:
              schema:
                type: object
                required: [recipes]
                properties:
                  recipes:
                    type: array
                    items:
                      $ref: "#/components/schemas/TenantRecipe"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Recipes]
      operationId: saveWorkspaceTenantRecipe
      summary: Save or update a tenant cohort recipe.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SaveTenantRecipeRequest"
      responses:
        "201":
          description: Saved tenant recipe.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantRecipe"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/recipes/{recipeID}:
    delete:
      tags: [Workspace Recipes]
      operationId: deleteWorkspaceTenantRecipe
      summary: Delete a saved tenant cohort recipe.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/RecipeID"
      responses:
        "204":
          description: Recipe deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs:
    get:
      tags: [Workspace Jobs]
      operationId: listWorkspaceCohortJobs
      summary: List retained cohort jobs for a tenant.
      description: >-
        Requires an `X-API-Key` scoped to the `{tenantID}` named in the path, or
        an authenticated workspace session with access to that workspace — a
        caller-supplied tenant ID alone is never sufficient. Pages are
        keyset-cursor based: pass the `nextCursor` value from a previous
        response as `cursor` to fetch the following page; the window is stable
        even when jobs are created between requests.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: A page of tenant cohort jobs, newest first. `nextCursor` is present when more pages remain.
          content:
            application/json:
              schema:
                type: object
                required: [jobs]
                properties:
                  jobs:
                    type: array
                    items:
                      $ref: "#/components/schemas/CohortJob"
                  nextCursor: { type: string }
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Jobs]
      operationId: createWorkspaceCohortJob
      summary: Create a retained cohort generation job.
      description: Returns compact job metadata and artifact inventory. Artifacts are retained for 30 days.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/from-scenario:
    post:
      tags: [Workspace Jobs]
      operationId: createWorkspaceCohortJobFromScenario
      summary: Create a retained cohort job from a built-in scenario preset.
      description: Expands the selected built-in scenario into a full cohort spec and starts a retained generation job.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioRequest"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-scenarios/{scenarioName}/customize:
    post:
      tags: [Workspace Jobs]
      operationId: customizeWorkspaceScenario
      summary: Customize a built-in scenario preset for a tenant.
      description: Resolves the selected built-in scenario, applies optional population, seed, and field-level overrides, validates the result, and returns the customized cohort spec without creating a job.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ScenarioName"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioCustomizeRequest"
      responses:
        "200":
          description: Customized cohort spec.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortSpec"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/from-scenario-customized:
    post:
      tags: [Workspace Jobs]
      operationId: createWorkspaceCohortJobFromScenarioCustomized
      summary: Create a retained cohort job from a customized built-in scenario preset.
      description: Resolves the selected built-in scenario, applies optional population, seed, and field-level overrides, validates the result, and starts a retained generation job.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioCustomizedJobRequest"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-designer:
    post:
      tags: [Workspace Jobs]
      operationId: designCurrentWorkspaceCohort
      summary: Design a validated cohort specification from a natural-language description.
      description: Uses the authenticated workspace plan and catalogs to produce a cohort specification ready for refinement.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CohortDesignerRequest"
      responses:
        "200":
          description: A validated cohort specification and any repairs applied.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortDesignerResponse"
        "429":
          description: >-
            Design rate limit reached. `code` is `ai_designer_rate_limited` when
            the per-tenant daily cap is exhausted, `ai_designer_burst_limited`
            when the per-tenant burst cap (short rolling window) is exceeded, or
            `ai_designer_busy` when the upstream model is throttling. All three
            are retryable.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: Too many design requests. Please wait a moment and try again.
                type: https://api.medisynth.io/errors/ai_designer_burst_limited
                title: Too many design requests
                status: 429
                code: ai_designer_burst_limited
                detail: Too many design requests. Please wait a moment and try again.
                retryable: true
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs:
    get:
      tags: [Workspace Jobs]
      operationId: listCurrentWorkspaceCohortJobs
      summary: List retained cohort jobs for the authenticated user's workspace.
      description: Derives the tenant from the verified session email. Use tenant-scoped routes with API keys for server-to-server clients.
      parameters:
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: A page of authenticated workspace cohort jobs, newest first. `nextCursor` is present when more pages remain.
          content:
            application/json:
              schema:
                type: object
                required: [jobs]
                properties:
                  jobs:
                    type: array
                    items:
                      $ref: "#/components/schemas/CohortJob"
                  nextCursor: { type: string }
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Jobs]
      operationId: createCurrentWorkspaceCohortJob
      summary: Create a retained cohort job for the authenticated user's workspace.
      description: Derives the tenant from the verified session email, then runs the same entitlement, idempotency, dispatch, retention, and metering path as the tenant-scoped job route.
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortSpec"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/from-scenario:
    post:
      tags: [Workspace Jobs]
      operationId: createCurrentWorkspaceCohortJobFromScenario
      summary: Create a retained cohort job from a built-in scenario preset for the authenticated user.
      description: Derives the tenant from the verified session email, expands the selected built-in scenario into a full cohort spec, and starts a retained generation job.
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioRequest"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-scenarios/{scenarioName}/customize:
    post:
      tags: [Workspace Jobs]
      operationId: customizeCurrentWorkspaceScenario
      summary: Customize a built-in scenario preset for the authenticated user.
      description: Resolves the selected built-in scenario, applies optional population, seed, and field-level overrides, validates the result, and returns the customized cohort spec without creating a job.
      parameters:
        - $ref: "#/components/parameters/ScenarioName"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioCustomizeRequest"
      responses:
        "200":
          description: Customized cohort spec.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortSpec"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/from-scenario-customized:
    post:
      tags: [Workspace Jobs]
      operationId: createCurrentWorkspaceCohortJobFromScenarioCustomized
      summary: Create a retained cohort job from a customized built-in scenario preset for the authenticated user.
      description: Resolves the selected built-in scenario, applies optional population, seed, and field-level overrides, validates the result, and starts a retained generation job.
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        $ref: "#/components/requestBodies/CohortScenarioCustomizedJobRequest"
      responses:
        "202":
          description: Job accepted or idempotently recovered.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}:
    get:
      tags: [Workspace Jobs]
      operationId: getWorkspaceCohortJob
      summary: Read one retained cohort job.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Cohort job.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortJob"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Workspace Jobs]
      operationId: dismissWorkspaceCohortJob
      summary: Dismiss a failed or stale cohort job from Needs-attention.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200": { description: Job marked expired, content: { application/json: { schema: { $ref: "#/components/schemas/WorkspaceCohortJobResponse" } } } }
        default: { $ref: "#/components/responses/Error" }
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/attestation/verify:
    get:
      tags: [Workspace Jobs]
      operationId: verifyWorkspaceCohortJobAttestation
      summary: Verify a cohort job's detached Ed25519 attestation signature.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Signature validity, signer identity, public key, and scorecard summary.
          content:
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/scorecard.sarif.json:
    get:
      tags: [Workspace Jobs]
      operationId: getWorkspaceCohortJobSARIF
      summary: Export a cohort job's conformance scorecard as SARIF 2.1.0.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Deterministic SARIF 2.1.0 log.
          content:
            application/sarif+json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}:
    get:
      tags: [Workspace Jobs]
      operationId: getCurrentWorkspaceCohortJob
      summary: Read one retained cohort job from the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Cohort job.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CohortJob"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Workspace Jobs]
      operationId: dismissCurrentWorkspaceCohortJob
      summary: Dismiss a failed or stale cohort job from Needs-attention.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200": { description: Job marked expired, content: { application/json: { schema: { $ref: "#/components/schemas/WorkspaceCohortJobResponse" } } } }
        default: { $ref: "#/components/responses/Error" }
  /v1/workspace/me/cohort-jobs/{jobID}/attestation/verify:
    get:
      tags: [Workspace Jobs]
      operationId: verifyCurrentWorkspaceCohortJobAttestation
      summary: Verify a cohort job's detached Ed25519 attestation signature.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Signature validity, signer identity, public key, and scorecard summary.
          content:
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/scorecard.sarif.json:
    get:
      tags: [Workspace Jobs]
      operationId: getCurrentWorkspaceCohortJobSARIF
      summary: Export a cohort job's conformance scorecard as SARIF 2.1.0.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Deterministic SARIF 2.1.0 log.
          content:
            application/sarif+json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/attestations/verify:
    post:
      tags: [Attestations]
      operationId: verifyAttestationPublic
      summary: Publicly verify a signed MediSynth attestation (stateless, unauthenticated).
      description: >-
        Verifies a detached Ed25519 attestation signature against MediSynth's
        trusted signing key, so any third party can confirm that a certificate a
        customer shares with them was genuinely signed by MediSynth. Stateless:
        the caller supplies the attestation and signature bytes; nothing is
        looked up and no tenant data is returned.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [attestation, signatureBase64]
              properties:
                attestation:
                  type: string
                  description: The exact attestation.json content (verbatim bytes).
                signatureBase64:
                  type: string
                  description: Base64 of the attestation.sig bytes.
      responses:
        "200":
          description: Signature validity, signer key ID, public key, and algorithm.
          content:
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/cancel:
    post:
      tags: [Workspace Jobs]
      operationId: cancelCurrentWorkspaceCohortJob
      summary: Cancel a queued retained cohort job in the authenticated user's workspace.
      description: Queued jobs move to `canceled`; terminal or already-running jobs return a conflict.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Canceled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [job]
                properties:
                  job:
                    $ref: "#/components/schemas/CohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/retry:
    post:
      tags: [Workspace Jobs]
      operationId: retryCurrentWorkspaceCohortJob
      summary: Retry a failed, stale, expired, or canceled retained cohort job in the authenticated user's workspace.
      description: Creates a new queued job with the original spec and a `retriedFromJob` pointer for audit lineage.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "202":
          description: Retry job accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/cancel:
    post:
      tags: [Workspace Jobs]
      operationId: cancelWorkspaceCohortJob
      summary: Cancel a queued retained cohort job.
      description: Queued jobs move to `canceled`; terminal or already-running jobs return a conflict.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Canceled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [job]
                properties:
                  job:
                    $ref: "#/components/schemas/CohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/retry:
    post:
      tags: [Workspace Jobs]
      operationId: retryWorkspaceCohortJob
      summary: Retry a failed, stale, expired, or canceled retained cohort job.
      description: Creates a new queued job with the original spec and a `retriedFromJob` pointer for audit lineage.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "202":
          description: Retry job accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        "429":
          $ref: "#/components/responses/ConcurrentGenerationLimit"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/artifacts:
    get:
      tags: [Artifacts]
      operationId: listWorkspaceCohortJobArtifacts
      summary: List retained artifact inventory for a job.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Artifact inventory.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtifactInventory"
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/artifacts:
    get:
      tags: [Artifacts]
      operationId: listCurrentWorkspaceCohortJobArtifacts
      summary: List retained artifact inventory for a job in the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Artifact inventory.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtifactInventory"
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/artifacts/{fileName}:
    get:
      tags: [Artifacts]
      operationId: downloadCurrentWorkspaceCohortJobArtifact
      summary: Stream a retained artifact for a job in the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/JobID"
        - $ref: "#/components/parameters/FileName"
      responses:
        "200":
          description: Artifact file content. JSON artifacts include manifest, patients, FHIR bundle, quality-report.json, and the signed synthetic-data attestation.json; attestation.sig is its detached Ed25519 signature. NDJSON artifacts include FHIR resource files, source document files, and source-responses.ndjson provider response envelopes.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
            application/x-ndjson:
              schema:
                type: string
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/cohort-jobs/{jobID}/artifacts/{fileName}/download-url:
    get:
      tags: [Artifacts]
      operationId: createCurrentWorkspaceCohortJobArtifactDownloadUrl
      summary: Create a short-lived direct download URL for a retained artifact in the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/JobID"
        - $ref: "#/components/parameters/FileName"
      responses:
        "200":
          description: Signed download URL response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtifactDownloadURL"
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/artifacts/{fileName}:
    get:
      tags: [Artifacts]
      operationId: downloadWorkspaceCohortJobArtifact
      summary: Stream a retained artifact through the authenticated API.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
        - $ref: "#/components/parameters/FileName"
      responses:
        "200":
          description: Artifact file content. JSON artifacts include manifest, patients, FHIR bundle, quality-report.json, and the signed synthetic-data attestation.json; attestation.sig is its detached Ed25519 signature. NDJSON artifacts include FHIR resource files, source document files, and source-responses.ndjson provider response envelopes.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
            application/x-ndjson:
              schema:
                type: string
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/artifacts/{fileName}/download-url:
    get:
      tags: [Artifacts]
      operationId: createWorkspaceCohortJobArtifactDownloadUrl
      summary: Create a short-lived direct download URL for a retained artifact.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
        - $ref: "#/components/parameters/FileName"
      responses:
        "200":
          description: Signed download URL response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtifactDownloadURL"
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/fhir/Group/{tenantID}/$export:
    get:
      tags: [FHIR Bulk Export]
      operationId: kickoffFHIRBulkExport
      summary: Kick off a FHIR Bulk Data $export for a retained cohort job.
      description: |
        Initiates a FHIR Bulk Data export view over an existing retained cohort job.
        Returns `202 Accepted` with a `Content-Location` header pointing at the status
        endpoint. The cohort job must be `available`; otherwise this returns
        `409 artifact_not_ready`.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - name: _jobId
          in: query
          required: true
          schema:
            type: string
          description: Retained cohort job ID to export.
          example: job-000001
        - name: _type
          in: query
          required: false
          schema:
            type: string
          description: Comma-separated FHIR resource types to include in the manifest (e.g. Patient,Observation).
          example: Patient,Observation
      responses:
        "202":
          description: Export accepted; poll the `Content-Location` URL for status.
          headers:
            Content-Location:
              description: Absolute URL of the bulk export status endpoint.
              schema:
                type: string
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/fhir/Group/me/$export:
    get:
      tags: [FHIR Bulk Export]
      operationId: kickoffCurrentFHIRBulkExport
      summary: Kick off a FHIR Bulk Data $export for the current user's retained cohort job.
      description: |
        Session-scoped version of the tenant kickoff endpoint. Derives the tenant from
        the authenticated user's workspace membership.
      parameters:
        - name: _jobId
          in: query
          required: true
          schema:
            type: string
          description: Retained cohort job ID to export.
          example: job-000001
        - name: _type
          in: query
          required: false
          schema:
            type: string
          description: Comma-separated FHIR resource types to include in the manifest.
          example: Patient,Observation
      responses:
        "202":
          description: Export accepted; poll the `Content-Location` URL for status.
          headers:
            Content-Location:
              description: Absolute URL of the bulk export status endpoint.
              schema:
                type: string
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/fhir/export/{jobID}/status:
    get:
      tags: [FHIR Bulk Export]
      operationId: getFHIRBulkExportStatus
      summary: Poll the status of a FHIR Bulk Data export job.
      description: |
        Returns `200 OK` with the Bulk Data manifest once the cohort job is available,
        or `202 Accepted` while the underlying cohort job is still running.
      parameters:
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Export complete. The response body follows the FHIR Bulk Data manifest format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBulkExportStatus"
        "202":
          description: Export still in progress.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRBulkExportStatus"
        default:
          $ref: "#/components/responses/Error"
  /v1/fhir/export/{jobID}/{fileName}:
    get:
      tags: [FHIR Bulk Export]
      operationId: downloadFHIRBulkExportFile
      summary: Download a single NDJSON file from a completed FHIR Bulk Data export.
      parameters:
        - $ref: "#/components/parameters/JobID"
        - $ref: "#/components/parameters/FileName"
      responses:
        "200":
          description: NDJSON file content containing one FHIR resource per line.
          content:
            application/x-ndjson:
              schema:
                type: string
        "409":
          description: Artifacts are not ready yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: cohort job artifacts are not ready
                type: https://api.medisynth.io/errors/artifact_not_ready
                title: Cohort job artifacts are not ready
                status: 409
                code: artifact_not_ready
                detail: cohort job artifacts are not ready
                retryable: true
                jobId: job-000001
                jobStatus: running
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/scheduled-cohort-jobs:
    get:
      tags: [Workspace Jobs]
      operationId: listCurrentWorkspaceScheduledCohortJobs
      summary: List scheduled cohort jobs for the authenticated user's workspace.
      description: Derives the tenant from the verified session email.
      responses:
        "200":
          description: Scheduled cohort jobs.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScheduledCohortJobList"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Jobs]
      operationId: createCurrentWorkspaceScheduledCohortJob
      summary: Create a scheduled cohort job for the authenticated user's workspace.
      requestBody:
        $ref: "#/components/requestBodies/CreateScheduledCohortJobRequest"
      responses:
        "201":
          description: Scheduled cohort job created.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/scheduled-cohort-jobs/{jobID}:
    get:
      tags: [Workspace Jobs]
      operationId: getCurrentWorkspaceScheduledCohortJob
      summary: Read one scheduled cohort job from the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "200":
          description: Scheduled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Workspace Jobs]
      operationId: updateCurrentWorkspaceScheduledCohortJob
      summary: Update a scheduled cohort job in the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/ScheduledJobID"
      requestBody:
        $ref: "#/components/requestBodies/CreateScheduledCohortJobRequest"
      responses:
        "200":
          description: Updated scheduled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Workspace Jobs]
      operationId: deleteCurrentWorkspaceScheduledCohortJob
      summary: Delete a scheduled cohort job from the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "204":
          description: Scheduled cohort job deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/scheduled-cohort-jobs/{jobID}/trigger:
    post:
      tags: [Workspace Jobs]
      operationId: triggerCurrentWorkspaceScheduledCohortJob
      summary: Trigger a scheduled cohort job on demand for the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "202":
          description: Scheduled cohort job triggered.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/connectors/{connectorID}/metrics:
    get:
      tags: [Connectors]
      operationId: getCurrentWorkspaceConnectorMetrics
      summary: Read delivery metrics for one connector in the authenticated user's workspace.
      parameters:
        - $ref: "#/components/parameters/ConnectorID"
      responses:
        "200":
          description: Connector delivery metrics.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConnectorMetrics"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/scheduled-cohort-jobs:
    get:
      tags: [Workspace Jobs]
      operationId: listWorkspaceScheduledCohortJobs
      summary: List scheduled cohort jobs for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Scheduled cohort jobs.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScheduledCohortJobList"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Jobs]
      operationId: createWorkspaceScheduledCohortJob
      summary: Create a scheduled cohort job for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        $ref: "#/components/requestBodies/CreateScheduledCohortJobRequest"
      responses:
        "201":
          description: Scheduled cohort job created.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/scheduled-cohort-jobs/{jobID}:
    get:
      tags: [Workspace Jobs]
      operationId: getWorkspaceScheduledCohortJob
      summary: Read one scheduled cohort job for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "200":
          description: Scheduled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Workspace Jobs]
      operationId: updateWorkspaceScheduledCohortJob
      summary: Update a scheduled cohort job for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ScheduledJobID"
      requestBody:
        $ref: "#/components/requestBodies/CreateScheduledCohortJobRequest"
      responses:
        "200":
          description: Updated scheduled cohort job.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Workspace Jobs]
      summary: Delete a scheduled cohort job for a tenant.
      operationId: deleteWorkspaceScheduledCohortJob
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "204":
          description: Scheduled cohort job deleted.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/scheduled-cohort-jobs/{jobID}/trigger:
    post:
      tags: [Workspace Jobs]
      operationId: triggerWorkspaceScheduledCohortJob
      summary: Trigger a scheduled cohort job on demand for a tenant.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ScheduledJobID"
      responses:
        "202":
          description: Scheduled cohort job triggered.
          content:
            application/json:
              schema:
                type: object
                required: [scheduledJob]
                properties:
                  scheduledJob:
                    $ref: "#/components/schemas/ScheduledCohortJob"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/validate/fhir:
    post:
      tags: [Validation]
      operationId: validateCurrentWorkspaceFHIR
      summary: Validate a FHIR Bundle for the current workspace.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: A FHIR Bundle resource.
      responses:
        "200":
          description: FHIR validation report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRValidationReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/validate/fhir:
    post:
      tags: [Validation]
      operationId: validateWorkspaceFHIR
      summary: Validate a FHIR Bundle for a tenant workspace.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: A FHIR Bundle resource.
      responses:
        "200":
          description: FHIR validation report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRValidationReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/validate/ccda:
    post:
      tags: [Validation]
      operationId: validateCurrentWorkspaceCCDA
      summary: Validate a C-CDA document for the current workspace.
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
          text/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
      responses:
        "200":
          description: C-CDA conformance report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CCDAConformanceReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/validate/ccda:
    post:
      tags: [Validation]
      operationId: validateWorkspaceCCDA
      summary: Validate a C-CDA document for a tenant workspace.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
          text/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
      responses:
        "200":
          description: C-CDA conformance report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CCDAConformanceReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/validate/x12:
    post:
      tags: [Validation]
      operationId: validateCurrentWorkspaceX12
      summary: Validate X12 5010 837P/835 interchanges for the current workspace.
      description: Requires an authenticated current-workspace bearer session. API keys must use the tenant-scoped operation instead.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/EDI-X12:
            schema:
              type: string
              description: One or more concatenated X12 5010 837P or 835 interchanges.
          text/plain:
            schema:
              type: string
              description: One or more concatenated X12 5010 837P or 835 interchanges.
      responses:
        "200":
          description: X12 conformance report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/X12ConformanceReport"
        "413":
          $ref: "#/components/responses/Error"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/validate/x12:
    post:
      tags: [Validation]
      operationId: validateWorkspaceX12
      summary: Validate X12 5010 837P/835 interchanges for a tenant workspace.
      description: Requires either a tenant-scoped API key with data-read access or an authenticated admin bearer session authorized for the tenant.
      security:
        - apiKeyAuth: []
        - bearerAuth: []
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/EDI-X12:
            schema:
              type: string
              description: One or more concatenated X12 5010 837P or 835 interchanges.
          text/plain:
            schema:
              type: string
              description: One or more concatenated X12 5010 837P or 835 interchanges.
      responses:
        "200":
          description: X12 conformance report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/X12ConformanceReport"
        "413":
          $ref: "#/components/responses/Error"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/capabilities:
    get:
      tags: [Conversion]
      operationId: getConversionCapabilities
      summary: Report whether the FHIR converter is configured.
      responses:
        "200":
          description: Converter capability report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConversionCapabilityReport"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/ccda-to-fhir/me:
    post:
      tags: [Conversion]
      operationId: convertCurrentWorkspaceCCDAToFHIR
      summary: Convert a C-CDA document to FHIR for the current workspace.
      description: Convert a C-CDA document to FHIR for the current workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      parameters:
        - $ref: "#/components/parameters/PreserveHIE"
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
            example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
          text/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
            example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
      responses:
        "200":
          description: Converted FHIR Bundle.
          content:
            application/fhir+json:
              schema:
                type: object
                additionalProperties: true
              example:
                resourceType: Bundle
                id: converted-001
                type: document
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/ccda-to-fhir/tenants/{tenantID}:
    post:
      tags: [Conversion]
      operationId: convertWorkspaceCCDAToFHIR
      summary: Convert a C-CDA document to FHIR for a tenant workspace.
      description: Convert a C-CDA document to FHIR for a tenant workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/PreserveHIE"
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
            example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
          text/xml:
            schema:
              type: string
              format: xml
              description: A C-CDA ClinicalDocument XML body.
            example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
      responses:
        "200":
          description: Converted FHIR Bundle.
          content:
            application/fhir+json:
              schema:
                type: object
                additionalProperties: true
              example:
                resourceType: Bundle
                id: converted-001
                type: document
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fhir-to-ccda/me:
    post:
      tags: [Conversion]
      operationId: convertCurrentWorkspaceFHIRToCCDA
      summary: Convert a FHIR Bundle to C-CDA for the current workspace.
      description: Convert a FHIR Bundle to C-CDA for the current workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      parameters:
        - $ref: "#/components/parameters/PreserveHIE"
      requestBody:
        required: true
        content:
          application/fhir+json:
            schema:
              type: object
              additionalProperties: true
              description: A FHIR Bundle resource.
            example:
              resourceType: Bundle
              type: document
              entry:
                - resource:
                    resourceType: Patient
                    id: p1
      responses:
        "200":
          description: Converted C-CDA ClinicalDocument XML.
          content:
            application/xml:
              schema:
                type: string
                format: xml
              example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fhir-to-ccda/tenants/{tenantID}:
    post:
      tags: [Conversion]
      operationId: convertWorkspaceFHIRToCCDA
      summary: Convert a FHIR Bundle to C-CDA for a tenant workspace.
      description: Convert a FHIR Bundle to C-CDA for a tenant workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/PreserveHIE"
      requestBody:
        required: true
        content:
          application/fhir+json:
            schema:
              type: object
              additionalProperties: true
              description: A FHIR Bundle resource.
            example:
              resourceType: Bundle
              type: document
              entry:
                - resource:
                    resourceType: Patient
                    id: p1
      responses:
        "200":
          description: Converted C-CDA ClinicalDocument XML.
          content:
            application/xml:
              schema:
                type: string
                format: xml
              example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/health:
    get:
      tags: [Conversion]
      operationId: getCurrentConversionHealth
      summary: Check FHIR converter health for the current workspace.
      responses:
        "200":
          description: Converter health report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConversionHealthReport"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/health/tenants/{tenantID}:
    get:
      tags: [Conversion]
      operationId: getWorkspaceConversionHealth
      summary: Check FHIR converter health for a tenant workspace.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Converter health report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConversionHealthReport"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fhir-to-corpus/me:
    post:
      tags: [Conversion]
      operationId: convertCurrentWorkspaceFHIRToCorpus
      summary: Convert a FHIR Bundle to a C-CDA corpus summary for the current workspace.
      description: Convert a FHIR Bundle to a C-CDA corpus summary for the current workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      requestBody:
        required: true
        content:
          application/fhir+json:
            schema:
              type: object
              additionalProperties: true
              description: A FHIR Bundle resource.
            example:
              resourceType: Bundle
              type: document
              entry:
                - resource:
                    resourceType: Patient
                    id: p1
      responses:
        "200":
          description: C-CDA corpus summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRToCorpusResponse"
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fhir-to-corpus/tenants/{tenantID}:
    post:
      tags: [Conversion]
      operationId: convertWorkspaceFHIRToCorpus
      summary: Convert a FHIR Bundle to a C-CDA corpus summary for a tenant workspace.
      description: Convert a FHIR Bundle to a C-CDA corpus summary for a tenant workspace. Synthetic or de-identified documents only — MediSynth is a no-BAA service; do not submit real patient data. Conversion calls are logged with the input size and a content fingerprint, never the content.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/fhir+json:
            schema:
              type: object
              additionalProperties: true
              description: A FHIR Bundle resource.
            example:
              resourceType: Bundle
              type: document
              entry:
                - resource:
                    resourceType: Patient
                    id: p1
      responses:
        "200":
          description: C-CDA corpus summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FHIRToCorpusResponse"
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fidelity/me:
    get:
      tags: [Conversion]
      operationId: getCurrentWorkspaceConversionFidelity
      summary: Evaluate converter fidelity in HIE preservation mode for the current workspace.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GeneratedDataset"
      responses:
        "200":
          description: Converter fidelity report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConverterFidelityReport"
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/convert/fidelity/tenants/{tenantID}:
    get:
      tags: [Conversion]
      operationId: getWorkspaceConversionFidelity
      summary: Evaluate converter fidelity in HIE preservation mode for a tenant workspace.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GeneratedDataset"
      responses:
        "200":
          description: Converter fidelity report.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConverterFidelityReport"
        "503":
          description: FHIR converter is not configured.
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/workspaces:
    get:
      tags: [Workspace]
      operationId: getCurrentWorkspaceList
      summary: List the workspaces the authenticated user belongs to.
      description: >-
        Returns every workspace the authenticated session can access, unioning
        the user's default (email-owned) workspace with all memberships from the
        reverse index. Powers the frontend workspace switcher.
      responses:
        "200":
          description: The user's accessible workspaces.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceList"
        "401":
          $ref: "#/components/responses/Error"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/onboarding:
    get:
      tags: [Workspace]
      operationId: getCurrentWorkspaceOnboarding
      summary: Getting-started checklist for the authenticated workspace.
      description: >-
        Live getting-started progress derived from existing signals (API keys,
        cohort jobs, membership) with the next incomplete step, so the console can
        guide a new user to their first end-to-end run.
      responses:
        "200":
          description: Onboarding checklist.
          content:
            application/json:
              schema: { type: object }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/audit-log/export:
    get:
      tags: [Workspace]
      operationId: exportCurrentWorkspaceAuditLog
      summary: Export the authenticated workspace's tamper-evident audit trail (Admin+).
      description: >-
        Streams the workspace's access-control audit events as NDJSON (one event
        per line) in hash-chain order, each carrying its prevHash/entryHash so the
        download can be independently re-verified for tampering. The
        X-Audit-Chain-Verified and X-Audit-Event-Count response headers report the
        server-side verification result. For SIEM/compliance ingestion.
      responses:
        "200":
          description: NDJSON audit events.
          content:
            application/x-ndjson:
              schema: { type: string }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/audit-log/export:
    get:
      tags: [Workspace]
      operationId: exportWorkspaceAuditLog
      summary: Export a tenant's tamper-evident audit trail (Admin+).
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: NDJSON audit events.
          content:
            application/x-ndjson:
              schema: { type: string }
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/me/quota:
    get:
      tags: [Workspace Quota]
      operationId: getCurrentWorkspaceQuota
      summary: Read the current workspace quota status.
      responses:
        "200":
          description: Workspace quota status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceQuota"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/quota:
    get:
      tags: [Workspace Quota]
      operationId: getWorkspaceQuota
      summary: Read the quota status for a tenant workspace.
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Workspace quota status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceQuota"
        "429":
          $ref: "#/components/responses/RateLimitExceeded"
        default:
          $ref: "#/components/responses/Error"
  /admin/overview:
    get:
      tags: [Admin]
      operationId: getAdminOverview
      summary: Read the admin console overview.
      description: Returns real tenant, usage, retained cohort, coupon, and admin-account data for the authenticated operator.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Admin overview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminOverview"
        default:
          $ref: "#/components/responses/Error"
  /admin/cohort-jobs:
    get:
      tags: [Admin]
      operationId: listAdminCohortJobs
      summary: List cohort jobs across tenants for the admin operations console.
      security:
        - bearerAuth: []
      parameters:
        - { name: status, in: query, schema: { type: string } }
        - { name: tenantId, in: query, schema: { type: string } }
        - { name: phase, in: query, schema: { type: string } }
        - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: A filtered page of compact cohort jobs ordered newest first.
          content:
            application/json:
              schema:
                type: object
                required: [jobs]
                properties:
                  jobs:
                    type: array
                    items: { $ref: "#/components/schemas/CohortJob" }
                  nextCursor: { type: string }
        default:
          $ref: "#/components/responses/Error"
  /admin/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/redrive:
    post:
      tags: [Admin]
      operationId: redriveAdminWorkspaceCohortJob
      summary: Redrive a failed, stale, expired, or canceled tenant cohort job as an admin.
      description: Creates a linked replacement job using the original spec and normal billing/quota controls. The original job remains immutable for audit history.
      security:
        - bearerAuth: []
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "202":
          description: Admin redrive job accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceCohortJobResponse"
        default:
          $ref: "#/components/responses/Error"
  /admin/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/worker-logs:
    get:
      tags: [Admin]
      operationId: getAdminWorkspaceCohortJobWorkerLogs
      summary: Read bounded worker log events for a cohort job inside the admin console.
      security:
        - bearerAuth: []
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Worker log events; empty when none are found.
          content:
            application/json:
              schema:
                type: object
                required: [events]
                properties:
                  events:
                    type: array
                    maxItems: 500
                    items:
                      type: object
                      required: [timestamp, message, logStream]
                      properties:
                        timestamp: { type: string, format: date-time }
                        message: { type: string }
                        logStream: { type: string }
        default: { $ref: "#/components/responses/Error" }
  /admin/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/partitions/retry:
    post:
      tags: [Admin]
      operationId: retryAdminWorkspaceCohortJobPartitions
      summary: Retry failed child partitions for a running or stale partitioned cohort job.
      description: Requeues only failed child partitions for an existing partitioned parent job, or re-dispatches the finalizer when all child partitions are already available. Successful partition artifacts are reused and usage remains unmetered until final retained artifacts are assembled.
      security:
        - bearerAuth: []
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "202":
          description: Partition retry dispatch accepted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminPartitionRetryResponse"
        default:
          $ref: "#/components/responses/Error"
  /admin/operations/status:
    get:
      tags: [Admin]
      operationId: getAdminOperationsStatus
      summary: Read admin-only operational status for retained cohort generation.
      description: Aggregates durable job-ledger health with sanitized queue and dead-letter metrics when the production runtime exposes them.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Current operations health.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminOperationsStatus"
        default:
          $ref: "#/components/responses/Error"
  /admin/audit/api-key-requests:
    get:
      tags: [Admin]
      operationId: listAdminApiKeyRequestAudit
      summary: Search and export recent API-key request audit events.
      description: Returns flattened tenant-scoped API-key request audit rows across customers for operator review. Use `format=csv` for a CSV export.
      security:
        - bearerAuth: []
      parameters:
        - name: tenantId
          in: query
          required: false
          schema:
            type: string
        - name: outcome
          in: query
          required: false
          schema:
            type: string
            enum: [allowed, denied]
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: format
          in: query
          required: false
          schema:
            type: string
            enum: [json, csv]
            default: json
      responses:
        "200":
          description: API-key request audit rows.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminAPIKeyRequestAudit"
            text/csv:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
  /admin/audit/status-incidents:
    get:
      tags: [Admin]
      operationId: listAdminStatusIncidentAudit
      summary: Search and export status incident audit events.
      description: Returns lifecycle rows for status incident publication, updates, and resolution. Use `format=csv` for a CSV export.
      security:
        - bearerAuth: []
      parameters:
        - name: incidentId
          in: query
          required: false
          schema:
            type: string
        - name: status
          in: query
          required: false
          schema:
            type: string
            enum: [investigating, identified, monitoring, degraded, resolved]
        - name: action
          in: query
          required: false
          schema:
            type: string
            enum: [status_incident.created, status_incident.updated, status_incident.resolved]
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: format
          in: query
          required: false
          schema:
            type: string
            enum: [json, csv]
            default: json
      responses:
        "200":
          description: Status incident audit rows.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminStatusIncidentAudit"
            text/csv:
              schema:
                type: string
        default:
          $ref: "#/components/responses/Error"
  /admin/operations/dlq/messages:
    get:
      tags: [Admin]
      operationId: listAdminOperationsDlqMessages
      summary: Inspect sanitized dead-letter message metadata.
      description: Returns redrive-safe metadata for visible cohort worker DLQ messages without exposing raw queue message bodies.
      security:
        - bearerAuth: []
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 10
            default: 5
      responses:
        "200":
          description: Sanitized DLQ message inspection response.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminDLQMessages"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/members:
    get:
      tags: [Workspace Members]
      operationId: listWorkspaceMembers
      summary: List workspace members and their RBAC roles.
      description: >
        Returns the workspace membership roster. Workspace roles follow the
        hierarchy Owner > Admin > Member > Viewer.
      x-required-role: member
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Workspace members.
          content:
            application/json:
              schema:
                type: object
                required: [members]
                properties:
                  members:
                    type: array
                    items:
                      $ref: "#/components/schemas/WorkspaceMember"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Workspace Members]
      operationId: upsertWorkspaceMember
      summary: Assign or update a workspace member role.
      description: >
        Grants or updates a member role. Admins may manage Member and Viewer
        roles for non-owner accounts; only an Owner may grant or modify the Owner
        role. Demoting the final Owner is rejected.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpsertWorkspaceMemberRequest"
      responses:
        "200":
          description: Member role assigned.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceMember"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/members/me:
    get:
      tags: [Workspace Members]
      operationId: getWorkspaceMemberSelf
      summary: Read the calling account's workspace role.
      description: Returns the effective workspace role for the authenticated caller so the console can gate controls.
      x-required-role: viewer
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Caller workspace role.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceMember"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/members/{email}:
    delete:
      tags: [Workspace Members]
      operationId: removeWorkspaceMember
      summary: Remove a workspace member.
      description: >
        Removes a member from the workspace. Admins may remove non-owner members;
        only an Owner may remove another Owner. Removing the final Owner is rejected.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - name: email
          in: path
          required: true
          description: Email address of the member to remove.
          schema:
            type: string
            format: email
      responses:
        "204":
          description: Member removed.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/invitations:
    get:
      tags: [Workspace Members]
      operationId: listWorkspaceInvitations
      summary: List pending workspace invitations.
      description: >
        Returns the workspace's outstanding self-serve invitations with their
        target role and expiry. Secret accept tokens are never returned here.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Pending invitations.
          content:
            application/json:
              schema:
                type: object
                required: [invitations]
                properties:
                  invitations:
                    type: array
                    items:
                      $ref: "#/components/schemas/WorkspaceInvitation"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Workspace Members]
      operationId: createWorkspaceInvitation
      summary: Invite a teammate to the workspace.
      description: >
        Creates a tokenized, expiring invitation at the chosen role. Admins may
        invite Member and Viewer roles; only an Owner may invite an Owner. The
        one-time accept token is returned exactly once, in this response, so it
        can be shared with the invitee.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWorkspaceInvitationRequest"
      responses:
        "201":
          description: Invitation created.
          content:
            application/json:
              schema:
                type: object
                required: [invitation, token]
                properties:
                  invitation:
                    $ref: "#/components/schemas/WorkspaceInvitation"
                  token:
                    type: string
                    description: One-time accept token. Share with the invitee; never logged or re-shown.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/invitations/{invitationID}:
    delete:
      tags: [Workspace Members]
      operationId: revokeWorkspaceInvitation
      summary: Revoke a pending workspace invitation.
      description: Invalidates a pending invitation so its accept token can no longer be used.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - name: invitationID
          in: path
          required: true
          description: Identifier of the invitation to revoke.
          schema:
            type: string
      responses:
        "204":
          description: Invitation revoked.
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/invitations/{token}/accept:
    post:
      tags: [Workspace Members]
      operationId: acceptWorkspaceInvitation
      summary: Accept a workspace invitation.
      description: >
        Consumes an invitation token and provisions the caller's membership at the
        invited role. The authenticated caller's verified email must match the
        invited address, so a leaked token alone cannot grant access.
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - name: token
          in: path
          required: true
          description: The invitation's one-time accept token.
          schema:
            type: string
      responses:
        "200":
          description: Membership provisioned.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceMember"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/settings:
    put:
      tags: [Workspace Members]
      operationId: updateWorkspaceSettings
      summary: Rename a workspace.
      description: >
        Updates the workspace's display name. Session-only (API keys are
        rejected) and restricted to Owner and Admin. The name is validated with
        the same rules applied at workspace creation (1-120 printable characters,
        no control characters) and the change is written to the tamper-evident
        audit log. Returns the refreshed workspace/tenant summary.
      x-required-role: admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateWorkspaceSettingsRequest"
      responses:
        "200":
          description: Workspace renamed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantSummary"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/connectors:
    get:
      tags: [Connectors]
      operationId: listWorkspaceConnectors
      summary: List export delivery connectors for a workspace.
      description: |
        Returns the tenant's configured export delivery connectors. Connectors push generated
        cohort artifacts to object storage buckets, SFTP landing zones, or a FHIR server via the
        `$import` operation when a cohort job completes.
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Tenant connectors.
          content:
            application/json:
              schema:
                type: object
                required: [connectors]
                properties:
                  connectors:
                    type: array
                    items:
                      $ref: "#/components/schemas/Connector"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Connectors]
      operationId: createWorkspaceConnector
      summary: Create an export delivery connector.
      description: |
        Creates a per-workspace export delivery connector. Cloud credentials are never accepted in
        the request body; connectors reference an out-of-band secret via `credentialRef` that the
        delivery transport resolves at runtime. Requires the workspace_admin role.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectorInput"
      responses:
        "201":
          description: Connector created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Connector"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/connectors/{connectorID}:
    get:
      tags: [Connectors]
      operationId: getWorkspaceConnector
      summary: Read one export delivery connector.
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ConnectorID"
      responses:
        "200":
          description: Connector.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Connector"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Connectors]
      operationId: updateWorkspaceConnector
      summary: Update an export delivery connector.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ConnectorID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectorInput"
      responses:
        "200":
          description: Updated connector.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Connector"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Connectors]
      operationId: deleteWorkspaceConnector
      summary: Delete an export delivery connector.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ConnectorID"
      responses:
        "204":
          description: Connector deleted.
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/connectors/{connectorID}/metrics:
    get:
      tags: [Connectors]
      operationId: getWorkspaceConnectorMetrics
      summary: Read delivery metrics for one connector.
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/ConnectorID"
      responses:
        "200":
          description: Connector delivery metrics.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConnectorMetrics"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/webhooks:
    get:
      tags: [Webhooks]
      operationId: listWorkspaceWebhooks
      summary: List outbound webhooks for a workspace.
      description: Signing secrets are redacted on list and read responses; the plaintext secret is only returned on create and rotate-secret.
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
      responses:
        "200":
          description: Tenant webhooks.
          content:
            application/json:
              schema:
                type: object
                required: [webhooks]
                properties:
                  webhooks:
                    type: array
                    items:
                      $ref: "#/components/schemas/Webhook"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    post:
      tags: [Webhooks]
      operationId: createWorkspaceWebhook
      summary: Create a signed outbound webhook.
      description: |
        Creates a per-workspace webhook that fires on cohort-job lifecycle events. Deliveries are
        signed with HMAC-SHA256 over `<timestamp>.<body>` (see the `X-MediSynth-Signature` header),
        retried with exponential backoff, and carry a deterministic `X-MediSynth-Delivery` id so
        receivers can dedupe. The plaintext signing secret is returned exactly once in this response.
        Requires the workspace_admin role.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookInput"
      responses:
        "201":
          description: Webhook created. Includes the one-time plaintext signing secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/webhooks/{webhookID}:
    get:
      tags: [Webhooks]
      operationId: getWorkspaceWebhook
      summary: Read one outbound webhook (secret redacted).
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/WebhookID"
      responses:
        "200":
          description: Webhook.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    put:
      tags: [Webhooks]
      operationId: updateWorkspaceWebhook
      summary: Update an outbound webhook.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/WebhookID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookInput"
      responses:
        "200":
          description: Updated webhook (secret redacted).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags: [Webhooks]
      operationId: deleteWorkspaceWebhook
      summary: Delete an outbound webhook.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/WebhookID"
      responses:
        "204":
          description: Webhook deleted.
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/webhooks/{webhookID}/rotate-secret:
    post:
      tags: [Webhooks]
      operationId: rotateWorkspaceWebhookSecret
      summary: Rotate a webhook signing secret.
      description: Mints a fresh HMAC signing secret and returns it once in plaintext. Previously issued signatures become invalid immediately.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/WebhookID"
      responses:
        "200":
          description: Webhook with the newly minted plaintext signing secret.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/webhooks/{webhookID}/test:
    post:
      tags: [Webhooks]
      operationId: testWorkspaceWebhook
      summary: Send a signed test ping to a webhook.
      description: Delivers a `webhook.ping` event to the configured URL and returns the delivery record so operators can verify connectivity and signature handling.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/WebhookID"
      responses:
        "200":
          description: Test delivery succeeded.
          content:
            application/json:
              schema:
                type: object
                required: [delivery]
                properties:
                  delivery:
                    $ref: "#/components/schemas/DeliveryRecord"
        "502":
          description: The webhook endpoint rejected the test delivery.
          content:
            application/json:
              schema:
                type: object
                required: [delivery]
                properties:
                  delivery:
                    $ref: "#/components/schemas/DeliveryRecord"
        "402":
          $ref: "#/components/responses/PaymentRequired"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/deliveries:
    get:
      tags: [Connectors]
      operationId: listWorkspaceCohortJobDeliveries
      summary: List connector and webhook delivery records for a cohort job.
      x-required-role: workspace_member
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Delivery records, newest first.
          content:
            application/json:
              schema:
                type: object
                required: [deliveries]
                properties:
                  deliveries:
                    type: array
                    items:
                      $ref: "#/components/schemas/DeliveryRecord"
        default:
          $ref: "#/components/responses/Error"
  /v1/workspace/tenants/{tenantID}/cohort-jobs/{jobID}/redeliver:
    post:
      tags: [Connectors]
      operationId: redeliverWorkspaceCohortJob
      summary: Re-run connector and webhook delivery for an available cohort job.
      description: |
        Deterministically rebuilds the job's artifacts from its retained spec and re-runs delivery to
        every enabled connector and webhook. Because delivery ids are deterministic, receivers can
        dedupe replayed webhooks. Requires the workspace_admin role.
      x-required-role: workspace_admin
      parameters:
        - $ref: "#/components/parameters/TenantID"
        - $ref: "#/components/parameters/JobID"
      responses:
        "200":
          description: Delivery dispatch summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeliveryDispatchSummary"
        "422":
          $ref: "#/components/responses/RedeliveryRegenerationMemoryExceeded"
        default:
          $ref: "#/components/responses/Error"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Cognito JWT
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    scimBearerAuth:
      type: http
      scheme: bearer
      bearerFormat: opaque workspace SCIM token
  parameters:
    CohortJob:
      name: cohortJob
      in: query
      schema: { type: string }
      description: Retained cohort job id to read/search; defaults to the tenant's latest available job.
    ConnectorID:
      name: connectorID
      in: path
      required: true
      schema:
        type: string
      example: conn-000001
    WebhookID:
      name: webhookID
      in: path
      required: true
      schema:
        type: string
      example: whk-000001
    TenantID:
      name: tenantID
      in: path
      required: true
      schema:
        type: string
      example: tenant-000001
    JobID:
      name: jobID
      in: path
      required: true
      schema:
        type: string
      example: job-000001
    ScheduledJobID:
      name: jobID
      in: path
      required: true
      schema:
        type: string
      example: scheduled-job-000001
    RecipeID:
      name: recipeID
      in: path
      required: true
      schema:
        type: string
      example: recipe-000001
    ScenarioName:
      name: scenarioName
      in: path
      required: true
      schema:
        type: string
      example: diabetes-type-2-focused
    FileName:
      name: fileName
      in: path
      required: true
      schema:
        type: string
      example: patients.json
    APIKeyPrefix:
      name: prefix
      in: path
      required: true
      schema:
        type: string
      example: ms_000001_01
    AlertID:
      name: alertID
      in: path
      required: true
      schema:
        type: string
      example: usage-alert-000001
    PreserveHIE:
      name: preserve
      in: query
      required: false
      schema:
        type: string
        enum: [hie]
      description: When set to `hie`, run the conversion through the HIE preservation pipeline to retain document attribution, delivery-route provenance, and registry/repository metadata.
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
      description: Stable retry key. Reusing a key with a different payload returns a conflict.
  requestBodies:
    CohortSpec:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CohortSpec"
    CohortScenarioRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CohortScenarioRequest"
    CohortScenarioCustomizeRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CohortScenarioCustomizeRequest"
    CohortScenarioCustomizedJobRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CohortScenarioCustomizedJobRequest"
    TopologyValidateRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/TopologyValidateRequest"
    TopologyPreviewRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/TopologyPreviewRequest"
    CreateScheduledCohortJobRequest:
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CreateScheduledCohortJobRequest"
  responses:
    Error:
      description: Error response.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    RateLimitExceeded:
      description: Tenant rate limit exceeded. Retry after the window resets.
      headers:
        Retry-After:
          description: Seconds until the current rate-limit window resets (always >= 1).
          schema:
            type: integer
            minimum: 1
        X-RateLimit-Limit:
          description: The plan-derived request budget per fixed window (requests per minute).
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: Requests remaining in the current window. Omitted when the limiter failed open on a store outage and the window state is unknown.
          schema:
            type: integer
        X-RateLimit-Reset:
          description: Seconds until the current window resets. Omitted when the limiter failed open on a store outage and the window state is unknown.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ConcurrentGenerationLimit:
      description: >-
        Too many concurrent generation jobs for the workspace, or job creation
        is momentarily busy. `code` is `concurrent_generation_limit` or
        `concurrent_partitioned_generation_limit` when the plan's concurrent-job
        budget is exhausted, or `job_admission_contended` when another job for
        the workspace is mid-creation. All are retryable; honor `Retry-After`.
      headers:
        Retry-After:
          description: Seconds to wait before retrying (always >= 1).
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    PaymentRequired:
      description: The tenant's plan does not include the entitlement required for this feature. Upgrade to unlock it.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    InlineGenerationMemoryExceeded:
      description: Synchronous generation was rejected before allocation. The stable error code is `inline_generation_memory_exceeded`; use an asynchronous workspace cohort job.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error: Estimated synchronous generation memory exceeds the API limit
            type: https://api.medisynth.io/errors/inline_generation_memory_exceeded
            title: Inline generation memory exceeded
            status: 422
            code: inline_generation_memory_exceeded
            detail: Estimated synchronous generation memory exceeds the 768 MiB API limit; use the asynchronous workspace cohort-job path
            requestId: api/req-000001
            retryable: false
    InlineGenerationRejected:
      description: Synchronous generation was rejected before allocation. The stable error code is `inline_generation_population_exceeded` when the population exceeds 5,000, or `inline_generation_memory_exceeded` when estimated retained memory exceeds the API envelope. Use an asynchronous workspace cohort job.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            populationExceeded:
              summary: Population exceeds the synchronous inline limit
              value:
                error: Population exceeds the synchronous inline generation limit
                type: https://api.medisynth.io/errors/inline_generation_population_exceeded
                title: Inline generation population exceeded
                status: 422
                code: inline_generation_population_exceeded
                detail: population exceeds the synchronous inline generation limit; use the asynchronous workspace cohort-job path
                requestId: api/req-000001
                retryable: false
            memoryExceeded:
              summary: Estimated retained memory exceeds the synchronous API envelope
              value:
                error: Estimated synchronous generation memory exceeds the API limit
                type: https://api.medisynth.io/errors/inline_generation_memory_exceeded
                title: Inline generation memory exceeded
                status: 422
                code: inline_generation_memory_exceeded
                detail: Estimated synchronous generation memory exceeds the 768 MiB API limit; use the asynchronous workspace cohort-job path
                requestId: api/req-000001
                retryable: false
    RedeliveryRegenerationMemoryExceeded:
      description: Artifact regeneration was rejected before allocation. The stable error code is `redelivery_regeneration_memory_exceeded`.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error: Estimated synchronous generation memory exceeds the API limit
            type: https://api.medisynth.io/errors/redelivery_regeneration_memory_exceeded
            title: Cohort job is too large for synchronous redelivery
            status: 422
            code: redelivery_regeneration_memory_exceeded
            detail: Estimated synchronous generation memory exceeds the API limit; artifact regeneration was not attempted
            requestId: api/req-000001
            retryable: false
    NotFound:
      description: The requested resource was not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
  schemas:
    WorkspaceSSOConfig:
      type: object
      required: [issuer, clientId, domain]
      properties:
        tenantId: { type: string, readOnly: true }
        providerName: { type: string, readOnly: true }
        issuer: { type: string, format: uri }
        clientId: { type: string }
        clientSecret: { type: string, writeOnly: true }
        domain: { type: string }
        enforceSso: { type: boolean, default: false }
        discoveryUrl: { type: string, format: uri, readOnly: true }
    CohortDesignerRequest:
      type: object
      required: [prompt]
      properties:
        prompt:
          type: string
          minLength: 1
          maxLength: 2000
          example: Create 500 patients in the Northeast with diabetes and hypertension for an MPI test.
    CohortDesignerResponse:
      type: object
      required: [spec, explanation, warnings]
      properties:
        spec:
          $ref: "#/components/schemas/CohortSpec"
        explanation:
          type: string
        warnings:
          type: array
          items:
            type: string
    ReferenceVendor:
      type: object
      required: [name, documentCount]
      properties:
        name:
          type: string
          description: Vendor directory name in the corpus.
        documentCount:
          type: integer
    FHIRBundle:
      type: object
      description: FHIR Bundle (searchset over retained-cohort Patients).
      required: [resourceType, type]
      properties:
        resourceType:
          type: string
          enum: [Bundle]
        type:
          type: string
          enum: [searchset]
        total:
          type: integer
        link:
          type: array
          items:
            type: object
            properties:
              relation: { type: string }
              url: { type: string }
        entry:
          type: array
          items:
            type: object
            properties:
              fullUrl: { type: string }
              resource: { type: object }

    FHIRCapabilityStatement:
      type: object
      description: FHIR R4 CapabilityStatement describing the retained-cohort read/search surface.
      required: [resourceType, status, date, kind, fhirVersion, format, rest]
      properties:
        resourceType:
          type: string
          enum: [CapabilityStatement]
        status:
          type: string
        date:
          type: string
        kind:
          type: string
        fhirVersion:
          type: string
          enum: ["4.0.1"]
        format:
          type: array
          items:
            type: string
        software:
          type: object
        implementation:
          type: object
        rest:
          type: array
          items:
            type: object
            required: [mode]
            properties:
              mode:
                type: string
                enum: [server]
              resource:
                type: array
              documentation:
                type: string

    ReferenceVendorList:
      type: object
      required: [vendors, totalVendors, totalDocuments, totalBytes]
      properties:
        vendors:
          type: array
          items:
            $ref: "#/components/schemas/ReferenceVendor"
        totalVendors:
          type: integer
        totalDocuments:
          type: integer
        totalBytes:
          type: integer
    ReferenceSection:
      type: object
      required: [title]
      properties:
        code:
          type: string
          description: Section code (typically LOINC).
        title:
          type: string
        templateId:
          type: string
          description: First section-level templateId root.
    ReferenceDocument:
      type: object
      required: [id, vendor, fileName, path, sizeBytes, contentType, templateIds, sections]
      properties:
        id:
          type: string
          description: Stable URL-safe identifier for the document.
        vendor:
          type: string
        fileName:
          type: string
        path:
          type: string
          description: Path of the document within the corpus.
        sizeBytes:
          type: integer
        contentType:
          type: string
        title:
          type: string
        documentType:
          type: string
          description: Document code displayName (e.g. Summarization of Episode Note).
        documentTypeCode:
          type: string
          description: Document LOINC code.
        patientName:
          type: string
          description: Fictional patient name recorded in the document.
        effectiveTime:
          type: string
        templateIds:
          type: array
          items:
            type: string
        sections:
          type: array
          items:
            $ref: "#/components/schemas/ReferenceSection"
    ReferenceDocumentList:
      type: object
      required: [documents, total]
      properties:
        documents:
          type: array
          items:
            $ref: "#/components/schemas/ReferenceDocument"
        total:
          type: integer
        vendor:
          type: string
          description: Vendor filter applied to the listing, if any.
    ReferenceGeneratedProfile:
      type: object
      required: [templateIds, sections]
      properties:
        documentType:
          type: string
        documentTypeCode:
          type: string
        title:
          type: string
        templateIds:
          type: array
          items:
            type: string
        sections:
          type: array
          items:
            $ref: "#/components/schemas/ReferenceSection"
    WorkspaceRole:
      type: string
      description: >
        Workspace RBAC role. Hierarchy Owner > Admin > Member > Viewer. Owner
        manages billing, workspace destruction, and all members; Admin manages
        API keys, cohorts, exports, non-owner members, and views billing; Member
        creates/runs cohorts, exports, and manages own API keys; Viewer is
        read-only.
      enum: [owner, admin, member, viewer]
    WorkspaceMember:
      type: object
      required: [email, role]
      properties:
        email:
          type: string
          format: email
        role:
          $ref: "#/components/schemas/WorkspaceRole"
    UpsertWorkspaceMemberRequest:
      type: object
      required: [email, role]
      properties:
        email:
          type: string
          format: email
        role:
          $ref: "#/components/schemas/WorkspaceRole"
    WorkspaceInvitation:
      type: object
      required: [id, tenantId, email, role, status, createdAt, expiresAt]
      properties:
        id:
          type: string
        tenantId:
          type: string
        email:
          type: string
          format: email
        role:
          $ref: "#/components/schemas/WorkspaceRole"
        status:
          type: string
          enum: [pending, expired, accepted]
        invitedBy:
          type: string
          format: email
        createdAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time
    CreateWorkspaceInvitationRequest:
      type: object
      required: [email, role]
      properties:
        email:
          type: string
          format: email
        role:
          $ref: "#/components/schemas/WorkspaceRole"
    UpdateWorkspaceSettingsRequest:
      type: object
      required: [name]
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 120
          description: New workspace display name. 1-120 printable characters, no control characters.
          example: Acme Health Data Lab
    ConnectorInput:
      type: object
      required: [kind, name]
      description: |
        Export delivery connector configuration. Cloud credentials are never accepted here; supply
        `credentialRef` to point the transport at an out-of-band secret. When `artifacts` is empty
        every generated artifact is delivered; when `events` is empty the connector fires on
        `cohort.job.completed`.
      properties:
        kind:
          type: string
          enum: [s3, gcs, sftp, fhir_import]
          description: Destination transport. Object stores use bucket/prefix; sftp uses host/directory; fhir_import posts the FHIR bundle to `<endpoint>/$import`.
        name:
          type: string
          example: warehouse-landing
        enabled:
          type: boolean
          default: true
        bucket:
          type: string
          description: Object-store bucket (s3, gcs).
        prefix:
          type: string
          description: Object-store key prefix (s3, gcs).
        region:
          type: string
        host:
          type: string
          description: SFTP host.
        port:
          type: integer
          description: SFTP port (defaults to 22).
        directory:
          type: string
          description: SFTP landing directory.
        username:
          type: string
        endpoint:
          type: string
          format: uri
          description: FHIR base URL for fhir_import connectors.
        credentialRef:
          type: string
          description: Reference (secret-manager ARN or environment key) the transport resolves for authentication.
        artifacts:
          type: array
          items:
            type: string
          description: Optional artifact-name allow-list. Empty delivers all artifacts.
        events:
          type: array
          items:
            type: string
            enum: [cohort.job.completed, cohort.job.failed]
    Connector:
      allOf:
        - $ref: "#/components/schemas/ConnectorInput"
        - type: object
          required: [id, kind, name, enabled, createdAt, updatedAt]
          properties:
            id:
              type: string
              example: conn-000001
            createdAt:
              type: string
              format: date-time
            updatedAt:
              type: string
              format: date-time
    WebhookInput:
      type: object
      required: [url]
      description: |
        Outbound webhook subscription. Supplying no `events` subscribes to every event. A signing
        secret is minted automatically when omitted on create.
      properties:
        url:
          type: string
          format: uri
          example: https://example.com/hooks/medisynth
        enabled:
          type: boolean
          default: true
        description:
          type: string
        events:
          type: array
          items:
            type: string
            enum: [cohort.job.completed, cohort.job.failed, usage.alert.triggered, webhook.ping]
    Webhook:
      allOf:
        - $ref: "#/components/schemas/WebhookInput"
        - type: object
          required: [id, url, enabled, createdAt, updatedAt]
          properties:
            id:
              type: string
              example: whk-000001
            secret:
              type: string
              description: HMAC signing secret. Returned in plaintext only on create and rotate-secret; redacted elsewhere.
              example: whsec_redacted
            createdAt:
              type: string
              format: date-time
            updatedAt:
              type: string
              format: date-time
    DeliveryRecord:
      type: object
      required: [id, tenantId, channel, targetId, event, status, attempts, createdAt]
      description: Durable audit record for one connector or webhook delivery attempt-group.
      properties:
        id:
          type: string
          description: Deterministic delivery id; stable across retries and redeliveries for idempotent dedupe.
          example: dl_9f2c1a0b
        tenantId:
          type: string
        jobId:
          type: string
        channel:
          type: string
          enum: [connector, webhook]
        targetId:
          type: string
          description: Connector or webhook id.
        targetKind:
          type: string
          example: s3
        event:
          type: string
          example: cohort.job.completed
        status:
          type: string
          enum: [delivered, failed, skipped]
        attempts:
          type: integer
        statusCode:
          type: integer
          description: Final HTTP status for webhook deliveries.
        detail:
          type: string
        artifacts:
          type: array
          items:
            type: string
          description: Delivered target locations (object URIs, sftp paths, or FHIR status URLs).
        createdAt:
          type: string
          format: date-time
    DeliveryDispatchSummary:
      type: object
      required: [event, jobId, records]
      properties:
        event:
          type: string
          example: cohort.job.completed
        jobId:
          type: string
        records:
          type: array
          items:
            $ref: "#/components/schemas/DeliveryRecord"
    Error:
      type: object
      required: [error, type, title, status, code, detail, retryable]
      properties:
        error:
          type: string
          example: invalid cohort spec
          description: Legacy-compatible human-readable error detail.
        type:
          type: string
          format: uri
          example: https://api.medisynth.io/errors/validation_failed
        title:
          type: string
          example: Cohort validation failed
        status:
          type: integer
          example: 400
        code:
          type: string
          example: validation_failed
        detail:
          type: string
          example: cohort validation failed
        requestId:
          type: string
          example: api/req-000001
        retryable:
          type: boolean
          example: false
        retryAfterSeconds:
          type: integer
          example: 60
        fields:
          type: array
          items:
            type: object
            required: [field, message]
            properties:
              field:
                type: string
              message:
                type: string
        errors:
          type: array
          description: Compatibility alias for validation field errors.
          items:
            type: object
            required: [field, message]
            properties:
              field:
                type: string
              message:
                type: string
        valid:
          type: boolean
          description: Compatibility field returned on cohort validation errors.
        jobId:
          type: string
          description: Retained job ID when the error relates to a specific job.
        jobStatus:
          type: string
          description: Retained job status when the error relates to a specific cohort job lifecycle state.
          example: running
        expiresAt:
          type: string
          format: date-time
          description: Retention expiry timestamp when the error relates to expired artifacts.
        quota:
          $ref: "#/components/schemas/GenerationQuotaErrorMetadata"
      additionalProperties: true
    GenerationQuotaErrorMetadata:
      type: object
      description: Plan, usage, and retained-artifact forecast metadata returned on generation quota and limit failures.
      properties:
        planId:
          type: string
          example: free
        requestedPatients:
          type: integer
          example: 1001
        patientsGeneratedThisMonth:
          type: integer
          example: 0
        monthlyPatientQuota:
          type: integer
          example: 1000
        includedPatientQuotaRemaining:
          type: integer
          example: 1000
        creditBalanceCents:
          type: integer
          example: 0
        creditBackedPatientsAvailable:
          type: integer
          example: 0
        effectivePatientCapacity:
          type: integer
          example: 1000
        requestedGenerationJobs:
          type: integer
          example: 1
        generationJobsUsedThisMonth:
          type: integer
          example: 0
        monthlyGenerationJobQuota:
          type: integer
          example: 10
        generationJobsRemaining:
          type: integer
          example: 10
        maxJobPopulation:
          type: integer
          example: 1000
        maxSourceSystems:
          type: integer
          example: 4
        maxDocumentFormats:
          type: integer
          example: 3
        maxExportFormats:
          type: integer
          example: 3
        maxConcurrentJobs:
          type: integer
          example: 1
        currentConcurrentJobs:
          type: integer
          example: 1
        maxConcurrentPartitionedJobs:
          type: integer
          description: Maximum active large partitioned parent jobs allowed for the tenant plan.
          example: 1
        currentConcurrentPartitionedJobs:
          type: integer
          description: Current active queued or in-flight large partitioned parent jobs for the tenant.
          example: 1
        estimatedRetainedArtifactBytes:
          type: integer
          example: 33804096
        artifactRetentionDays:
          type: integer
          example: 30
        hieProviderInvocationsUsed:
          type: integer
          example: 0
        hieProviderInvocationsQuota:
          type: integer
          example: 100
        hieProviderInvocationsRemaining:
          type: integer
          example: 100
        percentOfHieProviderInvocationsQuota:
          type: number
          example: 0
        conversionsCcdaToFhirUsed:
          type: integer
          example: 0
        conversionsCcdaToFhirQuota:
          type: integer
          example: 100
        conversionsCcdaToFhirRemaining:
          type: integer
          example: 100
        percentOfConversionsCcdaToFhirQuota:
          type: number
          example: 0
        conversionsFhirToCcdaUsed:
          type: integer
          example: 0
        conversionsFhirToCcdaQuota:
          type: integer
          example: 100
        conversionsFhirToCcdaRemaining:
          type: integer
          example: 100
        percentOfConversionsFhirToCcdaQuota:
          type: number
          example: 0
        topologyEdgesUsed:
          type: integer
          example: 0
        topologyEdgesQuota:
          type: integer
          example: 100
        topologyEdgesRemaining:
          type: integer
          example: 100
        percentOfTopologyEdgesQuota:
          type: number
          example: 0
        webhookDeliveriesUsed:
          type: integer
          example: 0
        webhookDeliveriesQuota:
          type: integer
          example: 100
        webhookDeliveriesRemaining:
          type: integer
          example: 100
        percentOfWebhookDeliveriesQuota:
          type: number
          example: 0
        simulatorRunsByHieUsed:
          type: integer
          example: 0
        simulatorRunsByHieQuota:
          type: integer
          example: 100
        simulatorRunsByHieRemaining:
          type: integer
          example: 100
        percentOfSimulatorRunsByHieQuota:
          type: number
          example: 0
    Heartbeat:
      type: object
      required: [status]
      properties:
        status:
          type: string
          example: ok
    StatusResponse:
      type: object
      required: [status, summary, generatedAt, uptimeWindow, components, checks, incidents, metrics]
      properties:
        status:
          type: string
          example: operational
        summary:
          type: string
        generatedAt:
          type: string
          format: date-time
        uptimeWindow:
          type: string
        components:
          type: array
          items:
            $ref: "#/components/schemas/StatusComponent"
        checks:
          type: array
          items:
            $ref: "#/components/schemas/StatusCheck"
        incidents:
          type: array
          items:
            $ref: "#/components/schemas/StatusIncident"
        metrics:
          $ref: "#/components/schemas/StatusMetrics"
    StatusComponent:
      type: object
      required: [name, status]
      properties:
        name:
          type: string
          example: Public uptime monitor
        status:
          type: string
          enum: [operational, degraded, unavailable, unknown]
          example: operational
    StatusCheck:
      type: object
      required: [name, status, detail, checkedAt]
      properties:
        name:
          type: string
          example: Public uptime monitor
        status:
          type: string
          enum: [operational, degraded, unavailable, unknown]
          example: operational
        detail:
          type: string
          example: Public uptime checks are validating customer-facing endpoints.
        latencyMs:
          type: integer
          minimum: 0
        checkedAt:
          type: string
          format: date-time
    StatusIncident:
      type: object
      required: [id, status, title, createdAt, updatedAt]
      properties:
        id:
          type: string
          example: inc-public-001
        status:
          type: string
          example: investigating
        severity:
          type: string
          enum: [major, critical]
          example: major
        title:
          type: string
          example: Cohort downloads are delayed
        summary:
          type: string
          example: Some customer requests may take longer than expected while we investigate.
        startedAt:
          type: string
          format: date-time
        resolvedAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    StatusMetrics:
      type: object
      required: [uptimeTarget, artifactRetentionDays, generationMode, protectedApiRoutes, publicUptimeMonitorActive]
      properties:
        uptimeTarget:
          type: string
          example: 99.99%
        observedUptimePercent:
          type: integer
          minimum: 0
          maximum: 100
          description: Rolling 30-day success percentage from the public uptime canary when configured.
        lastProbeSuccessPercent:
          type: integer
          minimum: 0
          maximum: 100
          description: Most recent public uptime canary success percentage when configured.
        artifactRetentionDays:
          type: integer
          example: 30
        generationMode:
          type: string
          example: native synthetic cohort engine
        protectedApiRoutes:
          type: boolean
        publicUptimeMonitorActive:
          type: boolean
    GeneratePatientsRequest:
      type: object
      properties:
        population:
          type: integer
          minimum: 1
        state:
          type: string
        city:
          type: string
        gender:
          type: string
        ageMin:
          type: integer
        ageMax:
          type: integer
        seed:
          type: integer
          format: int64
    CohortScenarioRequest:
      type: object
      required: [scenario, population]
      properties:
        scenario:
          type: string
          description: Built-in cohort scenario preset identifier.
          enum:
            - ccda-lab-transform-network
            - copd-tobacco-adult
            - diabetes-ckd-ed
            - diabetes-type-2-focused
            - geriatric-multimorbidity
            - heart-failure-cardiac
            - high-acuity-hie
            - hypertension-focused
            - infectious-disease-harm-reduction
            - maternal-health
            - medicaid-postpartum-infant
            - mental-health-adult
            - mpi-hard-matches
            - pediatric-asthma-hie
            - referral-authorization-gaps
            - rural-sdoh-high
            - safety-net-cardiometabolic-hie
            - smoking-cessation-medication-safety
            - suburban-senior-sdoh
            - urban-pediatric-diverse
          example: diabetes-type-2-focused
        population:
          type: integer
          minimum: 1
          example: 1000
        seed:
          type: integer
          format: int64
          description: Optional deterministic seed for reproducible generation.
          example: 4107
    CohortScenarioOverrides:
      type: object
      description: Optional overrides applied to a built-in scenario preset while preserving its template metadata.
      properties:
        population:
          type: integer
          minimum: 1
          example: 1000
        seed:
          type: integer
          format: int64
          example: 4107
        geography:
          type: object
          properties:
            state:
              type: string
              example: New York
            city:
              type: string
              example: Buffalo
            county:
              type: string
              example: Erie
            postalCodes:
              type: object
              additionalProperties:
                type: number
        demographics:
          type: object
          properties:
            ageBands:
              type: array
              items:
                type: object
                required: [label, min, max, weight]
                properties:
                  label:
                    type: string
                  min:
                    type: integer
                  max:
                    type: integer
                  weight:
                    type: number
            sexAtBirth:
              type: object
              additionalProperties:
                type: number
            payerMix:
              type: object
              additionalProperties:
                type: number
            language:
              type: object
              additionalProperties:
                type: number
            race:
              type: object
              additionalProperties:
                type: number
            ethnicity:
              type: object
              additionalProperties:
                type: number
        conditions:
          type: array
          items:
            $ref: "#/components/schemas/ConditionRule"
        socialNeeds:
          $ref: "#/components/schemas/SocialNeedProfile"
        hie:
          type: object
          properties:
            sourceSystems:
              type: array
              items:
                type: string
            duplicateRate:
              type: number
              minimum: 0
              maximum: 1
            addressDriftRate:
              type: number
              minimum: 0
              maximum: 1
            missingPhoneRate:
              type: number
              minimum: 0
              maximum: 1
            nameDriftRate:
              type: number
              minimum: 0
              maximum: 1
            birthDateDriftRate:
              type: number
              minimum: 0
              maximum: 1
            staleRecordRate:
              type: number
              minimum: 0
              maximum: 1
            documentGapRate:
              type: number
              minimum: 0
              maximum: 1
            memberIdDriftRate:
              type: number
              minimum: 0
              maximum: 1
            coverageGapRate:
              type: number
              minimum: 0
              maximum: 1
            deniedClaimRate:
              type: number
              minimum: 0
              maximum: 1
            priorAuthRate:
              type: number
              minimum: 0
              maximum: 1
            consentRestrictionRate:
              type: number
              minimum: 0
              maximum: 1
            providerMismatchRate:
              type: number
              minimum: 0
              maximum: 1
            documentFormats:
              type: array
              items:
                type: string
                enum: [ccda, hl7v2, plain-text, pdf, docx, lab-summary]
            qualityTargets:
              $ref: "#/components/schemas/QualityTargets"
        exports:
          $ref: "#/components/schemas/ExportProfile"
        clinicalRealismProfile:
          type: string
          enum: [configured-targets, population-benchmark, high-acuity-hie, safety-net-cardiometabolic-hie, pediatric-asthma-hie]
    ConditionCorrelation:
      type: object
      description: A research-backed conditional probability linking a target condition to one or more prerequisite conditions.
      required: [given, conditionalRate]
      properties:
        given:
          type: array
          description: Names of conditions that must all be present.
          items:
            type: string
        conditionalRate:
          type: number
          minimum: 0
          maximum: 1
        reverseCeiling:
          type: number
          minimum: 0
          maximum: 1
          description: Optional cap on the reverse conditional probability.
        benchmarkRate:
          type: number
          minimum: 0
          maximum: 1
          description: Optional population benchmark rate for calibration assertions.
        source:
          type: string
          description: Citation or source for the rate.
    ConditionRule:
      type: object
      required: [name, prevalence]
      properties:
        name:
          type: string
          example: hypertension
        prevalence:
          type: number
          minimum: 0
          maximum: 1
        correlatedWith:
          type: array
          description: Backwards-compatible list of condition names to correlate with.
          items:
            type: string
        correlations:
          type: array
          description: Structured conditional-rate correlations for calibrated comorbidity generation.
          items:
            $ref: "#/components/schemas/ConditionCorrelation"
    CohortScenarioCustomizeRequest:
      type: object
      properties:
        population:
          type: integer
          minimum: 1
          description: Optional population override applied before scenario-specific clamping.
          example: 1000
        seed:
          type: integer
          format: int64
          description: Optional deterministic seed for reproducible generation.
          example: 4107
        overrides:
          $ref: "#/components/schemas/CohortScenarioOverrides"
    CohortScenarioCustomizedJobRequest:
      type: object
      required: [scenario]
      properties:
        scenario:
          type: string
          description: Built-in cohort scenario preset identifier.
          example: diabetes-type-2-focused
        population:
          type: integer
          minimum: 1
          description: Optional population override applied before scenario-specific clamping.
          example: 1000
        seed:
          type: integer
          format: int64
          description: Optional deterministic seed for reproducible generation.
          example: 4107
        overrides:
          $ref: "#/components/schemas/CohortScenarioOverrides"
    CohortSpec:
      type: object
      required: [name, population]
      properties:
        name:
          type: string
          example: enterprise-mpi-evaluation
        population:
          type: integer
          minimum: 1
          example: 1000
        seed:
          type: integer
          format: int64
          example: 4107
        hieProvider:
          type: string
          description: Optional built-in HIE provider profile ID to apply vendor-specific source systems and noise rates.
          example: epic
        regionPreset:
          type: string
          description: Optional built-in geographic region preset ID to apply realistic geography and demographics.
          example: northeast
        template:
          $ref: "#/components/schemas/TemplateProfile"
        geography:
          type: object
          properties:
            state:
              type: string
              example: Washington
            city:
              type: string
              example: Vancouver
        demographics:
          type: object
          properties:
            ageBands:
              type: array
              items:
                type: object
                required: [label, min, max, weight]
                properties:
                  label:
                    type: string
                  min:
                    type: integer
                  max:
                    type: integer
                  weight:
                    type: number
            sexAtBirth:
              type: object
              additionalProperties:
                type: number
            payerMix:
              type: object
              additionalProperties:
                type: number
            language:
              type: object
              additionalProperties:
                type: number
        conditions:
          type: array
          items:
            $ref: "#/components/schemas/ConditionRule"
        socialNeeds:
          $ref: "#/components/schemas/SocialNeedProfile"
        hie:
          type: object
          properties:
            sourceSystems:
              type: array
              items:
                type: string
            duplicateRate:
              type: number
              minimum: 0
              maximum: 1
            addressDriftRate:
              type: number
              minimum: 0
              maximum: 1
            missingPhoneRate:
              type: number
              minimum: 0
              maximum: 1
            documentFormats:
              type: array
              items:
                type: string
                enum: [ccda, hl7v2, plain-text, pdf, docx]
            gateways:
              type: array
              items:
                $ref: "#/components/schemas/HIEGateway"
            topology:
              type: array
              items:
                $ref: "#/components/schemas/HIETopologyEdge"
        exports:
          $ref: "#/components/schemas/ExportProfile"
      additionalProperties: true
    SocialNeedProfile:
      type: object
      description: Optional target rates for generated social determinants of health screening signals. Rates are rounded to deterministic cohort counts during preview and generation.
      properties:
        foodInsecurityRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.25
        transportationInsecurityRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.10
        medicationAffordabilityRate:
          type: number
          minimum: 0
          maximum: 1
          description: Applied to patients with chronic-condition evidence.
          example: 0.16
        housingInstabilityRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.18
        utilityRiskRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.14
        transportationBarrierRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.16
        socialIsolationRate:
          type: number
          minimum: 0
          maximum: 1
          example: 0.12
      additionalProperties: false
    ExportProfile:
      type: object
      description: Export format and FHIR bundle type preferences for a cohort.
      properties:
        formats:
          type: array
          description: "Optional export families to add. The base evidence set (manifest, patients, bundle, quality report, source CSVs, NDJSON, attestation) is always retained regardless of this list; these flags gate the optional families (x12-837/x12-835, documents/documents-archive, omop, omop-parquet, bulk-fhir). OMOP formats produce OMOP CDM 5.4 tabular tables (CSV / Parquet) for OHDSI/analytics."
          items:
            type: string
            enum: [json, ndjson, csv, manifest, bulk-fhir, x12-837, x12-835, documents, documents-archive, omop, omop-parquet]
        bundleType:
          type: string
          description: FHIR Bundle type to produce when exporting FHIR artifacts.
          enum: [collection, document, transaction, batch]
          default: collection
        transactionMethod:
          type: string
          description: HTTP method used for transaction or batch bundle entries.
          enum: [PUT, POST, conditional]
          default: PUT
        strictValidation:
          type: boolean
          default: false
          description: When true, run the generated bundle through MediSynth's structural US Core 6.1.0 validator and return the conformance report in the export response. This is not full HL7 IG package validation.
      additionalProperties: false
    QualityTarget:
      type: string
      description: Target quality level for an HIE simulation dimension. An empty value leaves the dimension unset.
      enum: ["", low, medium, high]
    QualityTargets:
      type: object
      description: Target quality levels for HIE simulation dimensions.
      properties:
        mpi:
          $ref: "#/components/schemas/QualityTarget"
        documentIngestion:
          $ref: "#/components/schemas/QualityTarget"
        payerReconciliation:
          $ref: "#/components/schemas/QualityTarget"
        labNormalization:
          $ref: "#/components/schemas/QualityTarget"
        providerRouting:
          $ref: "#/components/schemas/QualityTarget"
        privacy:
          $ref: "#/components/schemas/QualityTarget"
        replayExplainability:
          $ref: "#/components/schemas/QualityTarget"
      additionalProperties: false
    HIEProvider:
      type: object
      description: A realistic Health Information Exchange vendor profile with source systems, document formats, noise rates, and quality targets.
      required: [id, vendor, name]
      properties:
        id:
          type: string
          example: epic
        vendor:
          type: string
          example: Epic
        name:
          type: string
          example: Epic Care Everywhere
        description:
          type: string
        sourceSystems:
          type: array
          items:
            type: string
        documentFormats:
          type: array
          items:
            type: string
            enum: [ccda, hl7v2, plain-text, pdf, docx]
        duplicateRate:
          type: number
          minimum: 0
          maximum: 1
        addressDriftRate:
          type: number
          minimum: 0
          maximum: 1
        missingPhoneRate:
          type: number
          minimum: 0
          maximum: 1
        nameDriftRate:
          type: number
          minimum: 0
          maximum: 1
        birthDateDriftRate:
          type: number
          minimum: 0
          maximum: 1
        staleRecordRate:
          type: number
          minimum: 0
          maximum: 1
        documentGapRate:
          type: number
          minimum: 0
          maximum: 1
        memberIdDriftRate:
          type: number
          minimum: 0
          maximum: 1
        coverageGapRate:
          type: number
          minimum: 0
          maximum: 1
        deniedClaimRate:
          type: number
          minimum: 0
          maximum: 1
        priorAuthRate:
          type: number
          minimum: 0
          maximum: 1
        consentRestrictionRate:
          type: number
          minimum: 0
          maximum: 1
        providerMismatchRate:
          type: number
          minimum: 0
          maximum: 1
        qualityTargets:
          $ref: "#/components/schemas/QualityTargets"
    RegionPreset:
      type: object
      description: A geographic region preset that expands into realistic geography and demographic distributions.
      required: [id, name, geography, demographics]
      properties:
        id:
          type: string
          example: northeast
        name:
          type: string
          example: Northeast Corridor
        description:
          type: string
        geography:
          type: object
          properties:
            state:
              type: string
            city:
              type: string
            postalCodes:
              type: object
              additionalProperties:
                type: number
        demographics:
          type: object
          properties:
            ageBands:
              type: array
              items:
                type: object
                required: [label, min, max, weight]
                properties:
                  label:
                    type: string
                  min:
                    type: integer
                  max:
                    type: integer
                  weight:
                    type: number
            sexAtBirth:
              type: object
              additionalProperties:
                type: number
            payerMix:
              type: object
              additionalProperties:
                type: number
            language:
              type: object
              additionalProperties:
                type: number
            race:
              type: object
              additionalProperties:
                type: number
            ethnicity:
              type: object
              additionalProperties:
                type: number
    HIEGateway:
      type: object
      description: A node in the HIE exchange network that documents may pass through.
      required: [id]
      properties:
        id:
          type: string
          example: regional-hie-1
        name:
          type: string
          example: Regional HIE
        role:
          type: string
          example: regional
        homeCommunityId:
          type: string
          example: urn:oid:1.2.840.114350.1.13.11511.3.7.1
        repositoryUniqueId:
          type: string
          example: 1.3.6.1.4.1.311.12345.1
        endpoint:
          type: string
          format: uri
          example: https://regional-hie.example.org/xca
        protocol:
          type: string
          example: xca
        trustBundleId:
          type: string
          example: tb-regional-hie
        organizationId:
          type: string
          example: org-regional-hie
        region:
          type: string
          example: us-east-1
        isCentral:
          type: boolean
          default: false
    HIETopologyEdge:
      type: object
      description: A directed edge between two HIE gateways describing how documents flow.
      required: [from, to]
      properties:
        from:
          type: string
          example: hospital-a
        to:
          type: string
          example: regional-hie
        fromGatewayId:
          type: string
          example: hospital-a
        toGatewayId:
          type: string
          example: regional-hie
        protocol:
          type: string
          example: xcpd
        transform:
          type: boolean
          default: false
        latencyMs:
          type: integer
          example: 80
        reliability:
          type: number
          minimum: 0
          maximum: 1
          example: 0.995
        trustLevel:
          type: string
          example: production
    HIETopology:
      type: object
      description: A user-defined HIE network graph.
      properties:
        gateways:
          type: array
          items:
            $ref: "#/components/schemas/HIEGateway"
        edges:
          type: array
          items:
            $ref: "#/components/schemas/HIETopologyEdge"
    TopologyValidateRequest:
      type: object
      description: Validate either a full cohort spec or a standalone HIE topology.
      properties:
        spec:
          $ref: "#/components/schemas/CohortSpec"
        topology:
          $ref: "#/components/schemas/HIETopology"
    TopologyValidationResponse:
      type: object
      required: [valid]
      properties:
        valid:
          type: boolean
        errors:
          type: array
          items:
            type: object
            required: [field, message]
            properties:
              field:
                type: string
              message:
                type: string
        warnings:
          type: array
          items:
            type: string
    TopologyPreviewRequest:
      type: object
      required: [sourceSystems]
      properties:
        sourceSystems:
          type: array
          items:
            type: string
          example: [hospital-a, hospital-b]
        topology:
          $ref: "#/components/schemas/HIETopology"
    TopologyPreviewResponse:
      type: object
      required: [sourceSystems, routes]
      properties:
        sourceSystems:
          type: array
          items:
            type: string
        routes:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: "#/components/schemas/DocumentHop"
    DocumentHop:
      type: object
      required: [index, nodeId, nodeRole, status]
      properties:
        index:
          type: integer
        nodeId:
          type: string
        nodeName:
          type: string
        nodeRole:
          type: string
        status:
          type: string
        deliveredAt:
          type: string
          format: date-time
        ackId:
          type: string
        messageControlId:
          type: string
        transformApplied:
          type: string
        fromGatewayId:
          type: string
        toGatewayId:
          type: string
        homeCommunityId:
          type: string
        repositoryUniqueId:
          type: string
    TopologyPreset:
      type: object
      required: [id, name, topology]
      properties:
        id:
          type: string
          example: regional-hub
        name:
          type: string
          example: Regional hub
        description:
          type: string
        topology:
          $ref: "#/components/schemas/HIETopology"
    TemplateProfile:
      type: object
      description: Product metadata attached to built-in cohort templates so customers can choose the right test population before running it.
      properties:
        category:
          type: string
          example: Identity
        useCase:
          type: string
          example: Stress-test MPI matching with duplicate identities, address drift, sparse phones, source-specific MRNs, and conflicting provider feeds.
        expectedArtifacts:
          type: array
          description: Representative retained files expected from a completed job.
          items:
            type: string
          example: [patients.json, Patient.ndjson, Provenance.ndjson, manifest.json, quality-report.json, source-responses.ndjson]
        failureModes:
          type: array
          description: Realistic data-quality or integration issues intentionally modeled by the template.
          items:
            type: string
          example: [duplicate identities across HIE feeds, address and phone drift]
        recommendedPopulation:
          $ref: "#/components/schemas/RecommendedPopulation"
        estimatedCostCents:
          type: integer
          minimum: 0
          description: Estimated usage cost in cents before account-specific credits or included quota are applied.
          example: 0
      additionalProperties: false
    RecommendedPopulation:
      type: object
      properties:
        min:
          type: integer
          minimum: 1
          example: 100
        max:
          type: integer
          minimum: 1
          example: 50000
      additionalProperties: false
    ValidationReport:
      type: object
      required: [valid]
      properties:
        valid:
          type: boolean
        errors:
          type: array
          items:
            $ref: "#/components/schemas/ValidationError"
        warnings:
          type: array
          items:
            type: string
      additionalProperties: true
    ValidationError:
      type: object
      required: [field, message]
      properties:
        field:
          type: string
        message:
          type: string
      additionalProperties: false
    CohortPreview:
      type: object
      properties:
        name:
          type: string
        population:
          type: integer
        sourceSystems:
          type: integer
        duplicateIdentities:
          type: integer
        estimatedSourceRecords:
          type: integer
        estimatedFHIRResources:
          type: integer
        socialNeeds:
          $ref: "#/components/schemas/SocialNeedPreview"
        executionPlan:
          $ref: "#/components/schemas/CohortExecutionPlan"
      additionalProperties: true
    SocialNeedPreview:
      type: object
      description: Estimated social-need screening counts for configured cohort targets.
      properties:
        foodInsecurityCount:
          type: integer
          minimum: 0
        transportationInsecurityCount:
          type: integer
          minimum: 0
        medicationAffordabilityCount:
          type: integer
          minimum: 0
        housingInstabilityCount:
          type: integer
          minimum: 0
        utilityRiskCount:
          type: integer
          minimum: 0
        transportationBarrierCount:
          type: integer
          minimum: 0
        socialIsolationCount:
          type: integer
          minimum: 0
        totalCount:
          type: integer
          minimum: 0
      additionalProperties: false
    GeneratedDataset:
      type: object
      description: Native generated dataset envelope. Patient socialNeeds entries include coding, screeningInstrument, riskLevel, areaDeprivationIndex, and communityResourceUrn fields for SDOH routing tests.
      properties:
        patients:
          type: array
          items:
            type: object
            additionalProperties: true
        manifest:
          type: object
          additionalProperties: true
      additionalProperties: true
    FhirExport:
      type: object
      required: [bundle, ndjson]
      description: FHIR R4-style export envelope. NDJSON keys use FHIR resource file names such as Patient.ndjson, Observation.ndjson, DiagnosticReport.ndjson, DocumentReference.ndjson, and Provenance.ndjson. Observation.ndjson includes clinical measurements and categorical SDOH screening observations.
      properties:
        bundle:
          type: object
          additionalProperties: true
        ndjson:
          type: object
          description: Map of FHIR resource NDJSON file names to newline-delimited JSON payloads.
          example:
            Patient.ndjson: '{"resourceType":"Patient","id":"regional-hie-person-000001"}'
            Observation.ndjson: '{"resourceType":"Observation","id":"regional-hie-person-000001-observation-a1c"}'
            DiagnosticReport.ndjson: '{"resourceType":"DiagnosticReport","id":"regional-hie-person-000001-diagnostic-report-panel-000001"}'
            DocumentReference.ndjson: '{"resourceType":"DocumentReference","id":"regional-hie-person-000001-ccda-continuity"}'
          additionalProperties:
            type: string
        conformance:
          $ref: "#/components/schemas/FHIRProfileComplianceReport"
          description: Present only when exports.strictValidation is true.
    UpstreamRetrieveRequest:
      type: object
      required: [spec]
      properties:
        personId:
          type: string
          example: person-000001
        sourceSystems:
          type: array
          items:
            type: string
        includeDeprecated:
          type: boolean
          default: false
          description: When true, XCA query/retrieve responses include documents whose availabilityStatus is Deprecated. Defaults to false.
        storedQueryId:
          type: string
          description: IHE ITI-18/38 stored-query UUID for the XCA query endpoint. Omit for the backward-compatible rich response.
          enum:
            - urn:uuid:14d4debf-8f97-4251-9a74-a90016b0af0d
            - urn:uuid:958f3006-baad-4929-a4de-ff1114824431
            - urn:uuid:10b545ea-725c-446d-9b95-8aeb444eddf3
            - urn:uuid:5c4f972b-d56b-40ac-a5fc-c8ca9b40b9d4
            - urn:uuid:a7ae438b-4bc2-4642-93e9-be891f7bb155
            - urn:uuid:bab9529a-4a10-40b3-a01f-f68a615d247a
            - urn:uuid:51224314-5390-4169-9b91-b1980040715a
            - urn:uuid:d90e5407-b356-4d91-a89f-873917b4b0e6
          example: urn:uuid:5c4f972b-d56b-40ac-a5fc-c8ca9b40b9d4
        documentEntryUuids:
          type: array
          minItems: 1
          description: XDSDocumentEntry entryUUID selectors for GetDocuments, GetDocumentsAndAssociations, or GetRelatedDocuments. Mutually exclusive with documentUniqueIds.
          items:
            type: string
            minLength: 1
        documentUniqueIds:
          type: array
          minItems: 1
          description: XDSDocumentEntry uniqueId selectors for GetDocuments, GetDocumentsAndAssociations, or GetRelatedDocuments. Mutually exclusive with documentEntryUuids.
          items:
            type: string
            minLength: 1
        objectUuids:
          type: array
          minItems: 1
          description: Values for the ITI-18 $uuid parameter used by GetAssociations and GetSubmissionSets.
          items:
            type: string
            minLength: 1
        associationTypes:
          type: array
          minItems: 1
          description: Required relationship types for GetRelatedDocuments, such as RPLC, APND, or XFRM (short codes or full IHE association URNs).
          items:
            type: string
            minLength: 1
        spec:
          $ref: "#/components/schemas/CohortSpec"
    XCPDDiscoveryRequest:
      type: object
      required: [spec, queries]
      properties:
        spec:
          $ref: "#/components/schemas/CohortSpec"
        queries:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/XCPDDiscoveryQuery"
        trustMode:
          type: boolean
          default: false
          description: When true, exclude patient records exposed by quarantined community endpoints, consistent with XCA trust-mode behavior.
        requesterId:
          type: string
    XCPDDiscoveryQuery:
      type: object
      properties:
        requestId:
          type: string
        givenName:
          type: string
        familyName:
          type: string
        birthDate:
          type: string
          format: date
        gender:
          type: string
        identifiers:
          type: array
          items:
            $ref: "#/components/schemas/XCPDPatientIdentifier"
    XCPDPatientIdentifier:
      type: object
      required: [value]
      properties:
        value:
          type: string
        type:
          type: string
          example: MR
        assigningAuthority:
          type: string
          example: urn:oid:2.16.840.1.113883.19.5
        xdsValue:
          type: string
          example: regional-hie-person-000001^^^&urn:oid:2.16.840.1.113883.19.5&ISO
    XCPDDiscoveryResponse:
      type: object
      required: [cohortName, seed, results]
      properties:
        cohortName:
          type: string
        seed:
          type: integer
          format: int64
        results:
          type: array
          items:
            type: object
            required: [status, ambiguous, matches]
            properties:
              requestId:
                type: string
              status:
                type: string
                enum: [matched, ambiguous, no-match]
              ambiguous:
                type: boolean
              matches:
                type: array
                items:
                  $ref: "#/components/schemas/XCPDDiscoveryMatch"
    XCPDDiscoveryMatch:
      type: object
      required: [personId, patientRecordId, sourceSystem, homeCommunityId, patientIdentifiers, demographics, matchConfidence, matchGrade, matchReasons, ambiguous, xcaQuery]
      properties:
        personId:
          type: string
        patientRecordId:
          type: string
        sourceSystem:
          type: string
        homeCommunityId:
          type: string
        patientIdentifiers:
          type: array
          items:
            $ref: "#/components/schemas/XCPDPatientIdentifier"
        demographics:
          $ref: "#/components/schemas/XCPDDiscoveryQuery"
        matchConfidence:
          type: number
          minimum: 0
          maximum: 1
        matchGrade:
          type: string
          enum: [exact, probable, possible]
        matchReasons:
          type: array
          items:
            type: string
        duplicateOf:
          type: string
        ambiguous:
          type: boolean
        xcaQuery:
          type: object
          required: [personId, sourceSystems, homeCommunityId]
          properties:
            personId:
              type: string
            sourceSystems:
              type: array
              items:
                type: string
            homeCommunityId:
              type: string
    UpstreamRetrieveResponse:
      type: object
      required: [cohortName, seed, personId, sources]
      properties:
        cohortName:
          type: string
        seed:
          type: integer
          format: int64
        personId:
          type: string
        sources:
          type: array
          items:
            type: object
            required: [sourceSystem, status, latencyMs, documents]
            properties:
              sourceSystem:
                type: string
              status:
                type: string
                enum: [available, partial, missing]
              latencyMs:
                type: integer
              availabilityReason:
                type: string
              endpoint:
                type: object
                properties:
                  hostName:
                    type: string
                    example: regional-hie.sandbox-hie.example.org
                  baseUrl:
                    type: string
                    example: https://regional-hie.sandbox-hie.example.org
                  simulatedCname:
                    type: string
                    example: regional-hie.customer-upstream.example.org
                  ipAddress:
                    type: string
                    example: 198.51.100.42
                  ipAllowlistRequired:
                    type: boolean
                    example: true
                  authMode:
                    type: string
                    example: mtls-oauth2
                  tlsProfile:
                    type: string
                    example: tls-1.2-mtls
                  mtlsRequired:
                    type: boolean
                    example: true
                  organizationUrn:
                    type: string
                    example: urn:oid:2.16.840.1.113883.19.1042
                  rateLimitPerMinute:
                    type: integer
                    example: 60
                  requestTimeoutMillis:
                    type: integer
                    example: 5000
                  connectionReuseRequired:
                    type: boolean
                    example: true
              retrievalMode:
                type: string
                example: document-query
              cacheTtlSeconds:
                type: integer
              retryAfterMs:
                type: integer
              patient:
                type: object
                additionalProperties: true
              documents:
                type: array
                items:
                  type: object
                  additionalProperties: true
              documentManifest:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    type:
                      type: string
                    format:
                      type: string
                    contentType:
                      type: string
                    byteSize:
                      type: integer
                    hash:
                      type: string
                    present:
                      type: boolean
              transformationHints:
                type: array
                items:
                  type: string
              completeness:
                type: array
                items:
                  type: object
                  properties:
                    domain:
                      type: string
                    status:
                      type: string
                      enum: [available, missing]
                    detail:
                      type: string
    TrustStatusResponse:
      type: object
      required: [trustBundles, endpoints, driftSummary]
      properties:
        trustBundles:
          type: array
          items:
            type: object
            required: [id, name, anchorThumbprints]
            properties:
              id:
                type: string
              name:
                type: string
              anchorThumbprints:
                type: array
                items:
                  type: string
        endpoints:
          type: array
          items:
            type: object
            required: [endpointId, url, thumbprint, trustBundleId, status]
            properties:
              endpointId:
                type: string
              url:
                type: string
              thumbprint:
                type: string
              trustBundleId:
                type: string
              status:
                type: string
                enum: [active, suspended]
        driftSummary:
          type: object
          additionalProperties:
            type: integer
          example:
            totalDrifts: 4
            quarantine: 2
            retryAfterRotation: 2
            trustBundleMismatch: 1
            directoryEndpointUrlMismatch: 1
            staleCertificateThumbprint: 1
            tlsStatusDegraded: 0
    TrustAuditBundle:
      type: object
      required: [resourceType, type, id, entry]
      properties:
        resourceType:
          type: string
          example: Bundle
        type:
          type: string
          example: collection
        id:
          type: string
        entry:
          type: array
          items:
            type: object
            properties:
              resource:
                type: object
                additionalProperties: true
    TrustAuditResult:
      type: object
      required: [resourceType, id, endpoints, consentDecisions, driftSummary, warnings, bundle]
      properties:
        resourceType:
          type: string
          enum: [TrustAuditResult]
        id:
          type: string
        endpoints:
          type: array
          items:
            type: object
            required: [endpointId, url, status, trustBundleId, bundleValid, certificate, decision, warnings]
            properties:
              endpointId: { type: string }
              url: { type: string }
              status: { type: string, enum: [active, suspended] }
              trustBundleId: { type: string }
              bundleValid: { type: boolean }
              decision: { type: string }
              warnings:
                type: array
                items: { type: string }
              certificate:
                type: object
                required: [thumbprint, expired, revoked]
                properties:
                  thumbprint: { type: string }
                  validFrom: { type: string, format: date-time }
                  validUntil: { type: string, format: date-time }
                  expired: { type: boolean }
                  revoked: { type: boolean }
        consentDecisions:
          type: array
          items:
            type: object
            required: [id, documentId, decision, breakGlassRequired, breakGlassInvoked]
            properties:
              id: { type: string }
              documentId: { type: string }
              decision: { type: string }
              purposeOfUse: { type: string }
              consentId: { type: string }
              breakGlassRequired: { type: boolean }
              breakGlassInvoked: { type: boolean }
              reason: { type: string }
        driftSummary:
          type: object
          additionalProperties: { type: integer }
        warnings:
          type: array
          items: { type: string }
        bundle:
          $ref: "#/components/schemas/TrustAuditBundle"
    CommunicationSubscriptionRequest:
      type: object
      required: [email, topics]
      properties:
        email:
          type: string
          format: email
          example: ops@example.test
        topics:
          type: array
          minItems: 1
          items:
            type: string
            enum: [product-updates, incident-updates]
        source:
          type: string
          example: public-status
    CommunicationUnsubscribeRequest:
      type: object
      required: [token]
      properties:
        token:
          type: string
          minLength: 1
          example: email-footer-token
    CommunicationSubscription:
      type: object
      required: [email, topics, status, createdAt, updatedAt]
      properties:
        email:
          type: string
          format: email
        topics:
          type: array
          items:
            type: string
            enum: [product-updates, incident-updates]
        status:
          type: string
          enum: [active, inactive]
          example: inactive
        source:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        unsubscribedAt:
          type: string
          format: date-time
    BillingPlan:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        monthlyPatientQuota:
          type: integer
        includedCreditsCents:
          type: integer
        overageCentsPerPatient:
          type: integer
        apiKeyLimit:
          type: integer
        maxPopulationPerJob:
          type: integer
        maxSourceSystemsPerJob:
          type: integer
        maxConcurrentJobs:
          type: integer
        maxConcurrentPartitionedJobs:
          type: integer
        maxMonthlyGenerationJobs:
          type: integer
        maxHieProviderInvocationsPerMonth:
          type: integer
        maxConversionsCcdaToFhirPerMonth:
          type: integer
        maxConversionsFhirToCcdaPerMonth:
          type: integer
        maxTopologyEdgesPerMonth:
          type: integer
        maxWebhookDeliveriesPerMonth:
          type: integer
        maxSimulatorRunsByHiePerMonth:
          type: integer
        maxTrustAuditCallsPerMonth:
          type: integer
        entitlements:
          type: array
          items:
            type: string
      additionalProperties: true
    PricingPlan:
      allOf:
        - $ref: "#/components/schemas/BillingPlan"
        - type: object
          properties:
            highlighted:
              type: boolean
    PricingTier:
      type: object
      properties:
        plan:
          $ref: "#/components/schemas/PricingPlan"
        highlights:
          type: array
          items:
            type: string
        tagline:
          type: string
    PricingTrial:
      type: object
      properties:
        planId:
          type: string
        trialCreditCents:
          type: integer
        includedPatients:
          type: integer
    PricingEnterprise:
      type: object
      properties:
        planId:
          type: string
    PricingPayAsYouGo:
      type: object
      properties:
        centsPer1000Patients:
          type: integer
    PricingModel:
      type: object
      properties:
        tiers:
          type: array
          items:
            $ref: "#/components/schemas/PricingTier"
        freeTrial:
          $ref: "#/components/schemas/PricingTrial"
        enterprise:
          $ref: "#/components/schemas/PricingEnterprise"
        payAsYouGo:
          $ref: "#/components/schemas/PricingPayAsYouGo"
    Invoice:
      type: object
      required: [id, tenantId, status, amountCents, lineItems, periodStart, periodEnd, createdAt]
      properties:
        id:
          type: string
        tenantId:
          type: string
        status:
          type: string
          enum: [draft, open, paid, void, uncollectible]
        amountCents:
          type: integer
        lineItems:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceLineItem"
        periodStart:
          type: string
          format: date-time
        periodEnd:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        finalizedAt:
          type: string
          format: date-time
    InvoiceLineItem:
      type: object
      required: [id, type, description, quantity, unitAmountCents, amountCents]
      properties:
        id:
          type: string
        type:
          type: string
          enum: [overage_patients, overage_hie_dimension, plan_proration]
        description:
          type: string
        quantity:
          type: integer
        unitAmountCents:
          type: integer
        amountCents:
          type: integer
    InvoiceListResponse:
      type: object
      required: [invoices]
      properties:
        invoices:
          type: array
          items:
            $ref: "#/components/schemas/Invoice"
        nextCursor: { type: string }
    PendingPlanChange:
      type: object
      required: [id, tenantId, requestedPlanId, status, effectiveAt, createdAt]
      properties:
        id:
          type: string
        tenantId:
          type: string
        requestedPlanId:
          type: string
        status:
          type: string
          enum: [pending, applied, canceled]
        effectiveAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
    PlanChangeRequest:
      type: object
      required: [planId]
      properties:
        planId:
          type: string
          example: team
        effectiveAt:
          type: string
          format: date-time
    PlanPreviewRequest:
      type: object
      required: [planId]
      properties:
        planId:
          type: string
          example: team
    PlanPreviewResponse:
      type: object
      required: [currentPlan, requestedPlan, prorationCents, immediateChargeCents, nextBillingPeriodStart, nextBillingPeriodEnd]
      properties:
        currentPlan:
          $ref: "#/components/schemas/BillingPlan"
        requestedPlan:
          $ref: "#/components/schemas/BillingPlan"
        prorationCents:
          type: integer
        immediateChargeCents:
          type: integer
        nextBillingPeriodStart:
          type: string
          format: date-time
        nextBillingPeriodEnd:
          type: string
          format: date-time
    CreateTenantRequest:
      type: object
      required: [name, email, plan]
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        plan:
          type: string
          example: developer
    Tenant:
      type: object
      required: [id, name, email, plan]
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        plan:
          type: string
        pastDue:
          type: boolean
          description: True while a Stripe subscription invoice payment has failed and not yet recovered. The paid plan is retained while Stripe retries payment.
        pastDueSince:
          type: string
          description: RFC 3339 timestamp of when the account entered the past-due state.
        pastDueInvoiceId:
          type: string
          description: Stripe invoice ID of the most recent failed subscription payment.
    TenantSummary:
      type: object
      properties:
        tenant:
          $ref: "#/components/schemas/Tenant"
        plan:
          $ref: "#/components/schemas/BillingPlan"
        usage:
          $ref: "#/components/schemas/UsageSummary"
        periodUsage:
          $ref: "#/components/schemas/UsageEvent"
        periodUsageSummary:
          $ref: "#/components/schemas/UsageSummary"
        apiKeys:
          type: array
          items:
            $ref: "#/components/schemas/APIKey"
        usageLedger:
          type: array
          items:
            $ref: "#/components/schemas/UsageLedgerEntry"
        artifactAccessLedger:
          type: array
          items:
            type: object
            additionalProperties: true
        accountActivity:
          type: array
          items:
            type: object
            additionalProperties: true
        apiKeyAudit:
          type: array
          items:
            type: object
            additionalProperties: true
        apiKeyRequestAudit:
          type: array
          items:
            $ref: "#/components/schemas/APIKeyRequestAuditEntry"
        recipes:
          type: array
          items:
            $ref: "#/components/schemas/TenantRecipe"
      additionalProperties: true
    SaveTenantRecipeRequest:
      type: object
      required: [name, spec]
      properties:
        id:
          type: string
          description: Existing recipe ID when updating a saved recipe.
          example: recipe-000001
        name:
          type: string
          example: Cardiology QA
        sourceTemplate:
          type: string
          description: Optional built-in template slug used as the starting point.
          example: mpi-hard-matches
        spec:
          $ref: "#/components/schemas/CohortSpec"
    TenantRecipe:
      type: object
      required: [id, tenantId, name, spec, createdAt, updatedAt]
      properties:
        id:
          type: string
          example: recipe-000001
        tenantId:
          type: string
          example: tenant-000001
        name:
          type: string
          example: Cardiology QA
        sourceTemplate:
          type: string
          example: mpi-hard-matches
        spec:
          $ref: "#/components/schemas/CohortSpec"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    APIKeyRequestAuditEntry:
      type: object
      properties:
        id:
          type: string
        tenantId:
          type: string
        apiKeyPrefix:
          type: string
          example: ms_000001_01
        method:
          type: string
          example: POST
        path:
          type: string
          example: /workspace/tenants/tenant-000001/cohort-jobs
        outcome:
          type: string
          enum: [allowed, denied]
          example: allowed
        failureCode:
          type: string
          example: invalid_api_key
        requestId:
          type: string
        userAgent:
          type: string
        remoteAddr:
          type: string
        createdAt:
          type: string
          format: date-time
    AdminAPIKeyRequestAudit:
      type: object
      required: [generatedAt, events]
      properties:
        generatedAt:
          type: string
          format: date-time
        events:
          type: array
          items:
            $ref: "#/components/schemas/AdminAPIKeyRequestAuditEntry"
    AdminAPIKeyRequestAuditEntry:
      allOf:
        - $ref: "#/components/schemas/APIKeyRequestAuditEntry"
        - type: object
          properties:
            tenantName:
              type: string
            tenantEmail:
              type: string
              format: email
    AdminStatusIncidentAudit:
      type: object
      required: [generatedAt, events]
      properties:
        generatedAt:
          type: string
          format: date-time
        events:
          type: array
          items:
            $ref: "#/components/schemas/AdminStatusIncidentAuditEntry"
    AdminStatusIncidentAuditEntry:
      type: object
      required: [id, incidentId, status, title, action, createdAt]
      properties:
        id:
          type: string
          example: status-incident-audit-000002
        incidentId:
          type: string
          example: inc-public-001
        status:
          type: string
          enum: [investigating, identified, monitoring, degraded, resolved]
          example: resolved
        title:
          type: string
          example: Cohort downloads recovered
        action:
          type: string
          enum: [status_incident.created, status_incident.updated, status_incident.resolved]
          example: status_incident.resolved
        actorType:
          type: string
          example: admin_session
        actorId:
          type: string
          example: ops@example.com
        createdAt:
          type: string
          format: date-time
    AdminOverview:
      type: object
      required: [session, totals, tenants, jobs, coupons, admins]
      properties:
        session:
          $ref: "#/components/schemas/AdminSession"
        totals:
          $ref: "#/components/schemas/AdminOverviewTotals"
        tenants:
          type: array
          items:
            $ref: "#/components/schemas/TenantSummary"
        jobs:
          type: array
          items:
            $ref: "#/components/schemas/CohortJob"
        coupons:
          type: array
          items:
            $ref: "#/components/schemas/Coupon"
        admins:
          type: array
          items:
            $ref: "#/components/schemas/AdminAccount"
    AdminSession:
      type: object
      required: [email, role, isAdmin, isSuperAdmin]
      properties:
        email:
          type: string
          format: email
        role:
          type: string
          enum: [superadmin, admin]
        isAdmin:
          type: boolean
        isSuperAdmin:
          type: boolean
    AdminOverviewTotals:
      type: object
      required: [tenantCount, savedCohortCount, patientsGenerated, sourceRecords, fhirResources, artifactBytes, generationJobCount, workerInvocations, activeCouponCount, creditBalanceCents, freeTriggerBalance]
      properties:
        tenantCount:
          type: integer
        savedCohortCount:
          type: integer
        patientsGenerated:
          type: integer
        sourceRecords:
          type: integer
        fhirResources:
          type: integer
        artifactBytes:
          type: integer
          description: Total retained artifact bytes represented by metered tenant usage.
        generationJobCount:
          type: integer
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
        activeCouponCount:
          type: integer
        creditBalanceCents:
          type: integer
        freeTriggerBalance:
          type: integer
    AdminAccount:
      type: object
      required: [email, role]
      properties:
        email:
          type: string
          format: email
        role:
          type: string
          enum: [superadmin, admin]
    Coupon:
      type: object
      required: [code, triggerAllowance, maxRedemptions, redemptionCount, createdByEmail, createdAt]
      properties:
        code:
          type: string
          example: GREG-50K
        triggerAllowance:
          type: integer
        maxRedemptions:
          type: integer
        redemptionCount:
          type: integer
        createdByEmail:
          type: string
          format: email
        note:
          type: string
        createdAt:
          type: string
          format: date-time
    APIKeyNameRequest:
      type: object
      required: [name]
      properties:
        name:
          type: string
          maxLength: 64
          example: browser-console
        expiresAt:
          type: string
          format: date-time
          description: Optional future UTC expiry. The key stops authenticating at this instant.
        scopes:
          type: array
          description: Optional least-privilege capabilities. Omit or send an empty array for unrestricted legacy access.
          uniqueItems: true
          items:
            type: string
            enum: [data:read, data:generate, data:export, connectors:manage, usage:write]
        allowedCidrs:
          type: array
          description: Optional IPv4 or IPv6 CIDR allowlist. Omit for access from any network.
          uniqueItems: true
          items:
            type: string
            example: 203.0.113.24/32
    APIKey:
      type: object
      properties:
        prefix:
          type: string
          example: ms_000001_01
        name:
          type: string
        status:
          type: string
          enum: [active, revoked]
        secret:
          type: string
          description: One-time secret returned only at creation or rotation.
        createdAt:
          type: string
          format: date-time
        revokedAt:
          type: string
          format: date-time
        lastUsedAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time
        scopes:
          type: array
          items:
            type: string
            enum: [data:read, data:generate, data:export, connectors:manage, usage:write]
        allowedCidrs:
          type: array
          items:
            type: string
        rotatedFrom:
          type: string
      additionalProperties: true
    UsageRecordRequest:
      type: object
      description: Usage dimensions accepted by the record-usage endpoint. Egress is accrued from artifact-access records and cannot be supplied here.
      properties:
        eventId:
          type: string
        jobId:
          type: string
        apiKeyPrefix:
          type: string
        patientsGenerated:
          type: integer
        sourceRecords:
          type: integer
        fhirResources:
          type: integer
        artifactBytes:
          type: integer
          description: Retained export artifact bytes associated with the usage event.
        artifactRetentionDays:
          type: integer
          description: Retention window used to derive storage byte-days for this event.
        storageByteDays:
          type: integer
          description: Precomputed retained bytes integrated over the configured retention window.
        generationJobCount:
          type: integer
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
        hieProviderInvocations:
          type: integer
        conversionsCcdaToFhir:
          type: integer
        conversionsFhirToCcda:
          type: integer
        topologyEdges:
          type: integer
        webhookDeliveries:
          type: integer
        simulatorRunsByHie:
          type: integer
        trustAuditCalls:
          type: integer
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
        hieProviderId:
          type: string
    UsageEvent:
      type: object
      description: Accumulated usage returned for a tenant or billing period.
      properties:
        eventId:
          type: string
        jobId:
          type: string
        apiKeyPrefix:
          type: string
        patientsGenerated:
          type: integer
        sourceRecords:
          type: integer
        fhirResources:
          type: integer
        artifactBytes:
          type: integer
          description: Retained export artifact bytes associated with the usage event.
        artifactRetentionDays:
          type: integer
          description: Retention window used to derive storage byte-days for this event.
        storageByteDays:
          type: integer
          description: Retained bytes integrated over the configured retention window.
        egressBytes:
          type: integer
          description: Artifact-download bytes accrued for the usage period.
        generationJobCount:
          type: integer
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
        hieProviderInvocations:
          type: integer
        conversionsCcdaToFhir:
          type: integer
        conversionsFhirToCcda:
          type: integer
        topologyEdges:
          type: integer
        webhookDeliveries:
          type: integer
        simulatorRunsByHie:
          type: integer
        trustAuditCalls:
          type: integer
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
        hieProviderId:
          type: string
    UsageSummary:
      type: object
      properties:
        patientsGenerated: { type: integer }
        sourceRecords: { type: integer }
        fhirResources: { type: integer }
        artifactBytes: { type: integer }
        storageByteDays: { type: integer }
        egressBytes: { type: integer }
        generationJobCount: { type: integer }
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
        hieProviderInvocations: { type: integer }
        conversionsCcdaToFhir: { type: integer }
        conversionsFhirToCcda: { type: integer }
        topologyEdges: { type: integer }
        webhookDeliveries: { type: integer }
        simulatorRunsByHie: { type: integer }
        trustAuditCalls: { type: integer }
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
        freeTriggersApplied: { type: integer }
        billableGenerationJobCount: { type: integer }
        patientQuotaRemaining: { type: integer }
        percentOfPatientQuota: { type: number, format: double }
        hieProviderInvocationsRemaining: { type: integer }
        percentOfHieProviderInvocationsQuota: { type: number, format: double }
        conversionsCcdaToFhirRemaining: { type: integer }
        percentOfConversionsCcdaToFhirQuota: { type: number, format: double }
        conversionsFhirToCcdaRemaining: { type: integer }
        percentOfConversionsFhirToCcdaQuota: { type: number, format: double }
        topologyEdgesRemaining: { type: integer }
        percentOfTopologyEdgesQuota: { type: number, format: double }
        webhookDeliveriesRemaining: { type: integer }
        percentOfWebhookDeliveriesQuota: { type: number, format: double }
        simulatorRunsByHieRemaining: { type: integer }
        percentOfSimulatorRunsByHieQuota: { type: number, format: double }
        trustAuditCallsRemaining: { type: integer }
        percentOfTrustAuditCallsQuota: { type: number, format: double }
        storageByteDaysRemaining: { type: integer }
        percentOfStorageByteDaysQuota: { type: number, format: double }
        egressBytesRemaining: { type: integer }
        percentOfEgressBytesQuota: { type: number, format: double }
    UsageLedgerEntry:
      type: object
      required: [id, tenantId, patientsGenerated, sourceRecords, fhirResources, artifactBytes, generationJobCount, workerInvocations, hieProviderInvocations, conversionsCcdaToFhir, conversionsFhirToCcda, topologyEdges, webhookDeliveries, simulatorRunsByHie, freeTriggersApplied, billableGenerationJobCount, createdAt]
      properties:
        id:
          type: string
          example: usage-event-4107
        tenantId:
          type: string
          example: tenant-000001
        jobId:
          type: string
        apiKeyPrefix:
          type: string
          example: ms_000001_01
        patientsGenerated:
          type: integer
          example: 250
        sourceRecords:
          type: integer
          example: 1038
        fhirResources:
          type: integer
          example: 5770
        artifactBytes:
          type: integer
          example: 8192
        storageByteDays:
          type: integer
          description: Retained bytes integrated over the event's configured retention window.
          example: 245760
        generationJobCount:
          type: integer
          example: 1
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
          example: 1
        hieProviderInvocations:
          type: integer
          example: 0
        conversionsCcdaToFhir:
          type: integer
          example: 0
        conversionsFhirToCcda:
          type: integer
          example: 0
        topologyEdges:
          type: integer
          example: 0
        webhookDeliveries:
          type: integer
          example: 0
        simulatorRunsByHie:
          type: integer
          example: 0
        trustAuditCalls:
          type: integer
          example: 0
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
          example: 0
        hieProviderId:
          type: string
        freeTriggersApplied:
          type: integer
          example: 0
        billableGenerationJobCount:
          type: integer
          example: 1
        createdAt:
          type: string
          format: date-time
    UsageExportTotals:
      type: object
      required: [patientsGenerated, sourceRecords, fhirResources, artifactBytes, generationJobCount, workerInvocations, hieProviderInvocations, conversionsCcdaToFhir, conversionsFhirToCcda, topologyEdges, webhookDeliveries, simulatorRunsByHie, freeTriggersApplied, billableGenerationJobCount]
      properties:
        patientsGenerated:
          type: integer
        sourceRecords:
          type: integer
        fhirResources:
          type: integer
        artifactBytes:
          type: integer
        generationJobCount:
          type: integer
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
        hieProviderInvocations:
          type: integer
        conversionsCcdaToFhir:
          type: integer
        conversionsFhirToCcda:
          type: integer
        topologyEdges:
          type: integer
        webhookDeliveries:
          type: integer
        simulatorRunsByHie:
          type: integer
        aiDesignInvocations:
          type: integer
        freeTriggersApplied:
          type: integer
        billableGenerationJobCount:
          type: integer
    UsageExport:
      type: object
      required: [tenantId, format, rows, totals]
      properties:
        tenantId:
          type: string
        from:
          type: string
        to:
          type: string
        format:
          type: string
          enum: [json]
        rows:
          type: array
          items:
            $ref: "#/components/schemas/UsageLedgerEntry"
        totals:
          $ref: "#/components/schemas/UsageExportTotals"
    CheckoutSessionRequest:
      type: object
      required: [successUrl, cancelUrl]
      properties:
        purpose:
          type: string
          enum: [api_credits, subscription]
          default: api_credits
        planId:
          type: string
          enum: [developer, team]
          description: Required when purpose is subscription.
        amountCents:
          type: integer
          minimum: 1
          description: Required when purpose is api_credits.
        successUrl:
          type: string
          format: uri
        cancelUrl:
          type: string
          format: uri
    CheckoutSession:
      type: object
      required: [id, url]
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
        status:
          type: string
      additionalProperties: true
    BillingPortalSessionRequest:
      type: object
      required: [returnUrl]
      properties:
        returnUrl:
          type: string
          format: uri
    BillingPortalSession:
      type: object
      required: [id, url]
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
    RedeemCouponRequest:
      type: object
      required: [code]
      properties:
        code:
          type: string
          example: GREG-50K
    WorkspaceCohortJobResponse:
      type: object
      required: [job, statusUrl, artifactsUrl]
      properties:
        job:
          $ref: "#/components/schemas/CohortJob"
        statusUrl:
          type: string
          description: Relative URL for polling retained cohort job status.
          example: /v1/workspace/me/cohort-jobs/job-000001
        artifactsUrl:
          type: string
          description: Relative URL for listing retained artifact inventory once the job is available.
          example: /v1/workspace/me/cohort-jobs/job-000001/artifacts
    AdminPartitionRetryResponse:
      type: object
      required: [job, mode, dispatchedCount, dispatchedChunks, finalizerRequested]
      properties:
        job:
          $ref: "#/components/schemas/CohortJob"
        mode:
          type: string
          enum: [failed_partitions, finalizer]
          description: Whether failed child partitions were requeued or the retained-artifact finalizer was re-dispatched.
        dispatchedCount:
          type: integer
          minimum: 0
          example: 2
        dispatchedChunks:
          type: array
          items:
            type: integer
          example: [1, 3]
        finalizerRequested:
          type: boolean
          description: True when the retry requested final assembly instead of a child partition rerun.
    CohortJob:
      type: object
      required: [id, tenantId, status, spec, createdAt, retentionDays]
      properties:
        id:
          type: string
          example: job-000001
        tenantId:
          type: string
        status:
          type: string
          enum: [queued, running, processing, generating, in_progress, available, failed, expired, canceled, stale]
        spec:
          $ref: "#/components/schemas/CohortSpec"
        manifest:
          type: object
          additionalProperties: true
        artifacts:
          type: object
          additionalProperties: true
        error:
          type: string
          description: Human-readable terminal failure or cancellation message.
        errorCode:
          type: string
          description: Stable machine-readable terminal failure code.
          enum: [job_canceled, dispatch_failed, generation_failed, export_failed, artifact_write_failed, job_failed]
        errorRequestId:
          type: string
          description: Request ID that produced the terminal failure when available.
        errorRetryable:
          type: boolean
          description: Whether the terminal failure can be retried by creating a linked replacement job.
        phase:
          type: string
          description: Current retained-job processing phase for queued or running jobs.
          example: writing-artifacts
        progressMessage:
          type: string
          description: Short customer-safe progress message for the current processing phase.
          example: Saving retained cohort artifacts.
        lastHeartbeatAt:
          type: string
          format: date-time
          description: Last time the worker recorded progress for the job.
        retriedFromJob:
          type: string
        executionPlan:
          $ref: "#/components/schemas/CohortExecutionPlan"
        executionSummary:
          $ref: "#/components/schemas/CohortJobExecutionSummary"
        partitions:
          type: array
          description: Deterministic partition descriptors for large retained cohort jobs. Present when the job is planned for partitioned execution.
          items:
            $ref: "#/components/schemas/CohortPartitionPlan"
        createdAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time
        retentionDays:
          type: integer
          example: 30
      additionalProperties: true
    CohortJobExecutionSummary:
      type: object
      description: Runtime timing evidence recorded by retained cohort workers for dashboard progress and operational tuning.
      properties:
        startedAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
        runtimeMs:
          type: integer
          format: int64
          minimum: 0
          example: 312000
        workerMemoryMb:
          type: integer
          description: Planned worker memory for the selected execution path.
          example: 10240
        phases:
          type: array
          items:
            $ref: "#/components/schemas/CohortJobPhaseTiming"
      additionalProperties: false
    CohortJobPhaseTiming:
      type: object
      required: [phase, startedAt, lastSeenAt, durationMs, heartbeatCount]
      properties:
        phase:
          type: string
          example: assembling-partitions
        startedAt:
          type: string
          format: date-time
        lastSeenAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
        durationMs:
          type: integer
          format: int64
          minimum: 0
          example: 84000
        heartbeatCount:
          type: integer
          minimum: 0
          example: 4
      additionalProperties: false
    CohortExecutionPlan:
      type: object
      required: [class, estimatedRecords, workerMemoryMb, requiresFanout, estimatedWorkerInvocations, estimatedParallelWorkers, maxPatientsPerWorker]
      properties:
        class:
          type: string
          enum: [standard, heavy, partitioned]
        estimatedRecords:
          type: integer
          example: 41100
        chunkSize:
          type: integer
          example: 1000
        chunkCount:
          type: integer
          example: 10
        workerMemoryMb:
          type: integer
          example: 10240
        requiresFanout:
          type: boolean
        maxConcurrentPartitions:
          type: integer
          description: Maximum partition child jobs that should be queued or running at once for this retained cohort job.
          example: 10
        estimatedWorkerInvocations:
          type: integer
          description: Expected bounded execution passes for the run, including coordination and retained artifact assembly when partitioning is required.
          example: 12
        estimatedParallelWorkers:
          type: integer
          description: Expected maximum number of generation partitions that can be active at the same time for this run.
          example: 10
        maxPatientsPerWorker:
          type: integer
          description: Maximum patient count targeted for a single bounded generation pass.
          example: 1000
        recommendedReason:
          type: string
      additionalProperties: false
    CohortPartitionPlan:
      type: object
      required: [parentJobId, chunkIndex, chunkCount, populationOffset, populationSize, executionClass, status]
      properties:
        parentJobId:
          type: string
          example: job-000001
        chunkIndex:
          type: integer
          example: 0
        chunkCount:
          type: integer
          example: 10
        populationOffset:
          type: integer
          example: 0
        populationSize:
          type: integer
          example: 1000
        executionClass:
          type: string
          example: partitioned
        status:
          type: string
          enum: [queued, processing, running, available, failed, canceled, stale]
      additionalProperties: false
    AdminOperationsStatus:
      type: object
      required: [generatedAt, summary, jobs, queue]
      properties:
        generatedAt:
          type: string
          format: date-time
        summary:
          type: object
          required: [status, message, actionNeeded, failureCount, backlogCount, redriveCount, retainedCount]
          properties:
            status:
              type: string
              enum: [operational, attention]
            message:
              type: string
            actionNeeded:
              type: boolean
            failureCount:
              type: integer
            backlogCount:
              type: integer
            redriveCount:
              type: integer
            retainedCount:
              type: integer
        jobs:
          type: object
          required: [total, queued, running, available, failed, expired, canceled, retryable, staleRunning, oldestQueuedAgeSeconds, oldestRunningAgeSeconds, recentFailures]
          properties:
            total:
              type: integer
            queued:
              type: integer
            running:
              type: integer
            available:
              type: integer
            failed:
              type: integer
            expired:
              type: integer
            canceled:
              type: integer
            retryable:
              type: integer
            staleRunning:
              type: integer
            oldestQueuedAgeSeconds:
              type: integer
            oldestRunningAgeSeconds:
              type: integer
            recentFailures:
              type: array
              items:
                type: string
        queue:
          type: object
          required: [configured, status, visibleMessages, inFlightMessages, delayedMessages, oldestMessageAgeSeconds, deadLetterVisibleMessages, deadLetterOldestAgeSeconds]
          properties:
            configured:
              type: boolean
            status:
              type: string
              enum: [operational, attention, unavailable, not_configured]
            visibleMessages:
              type: integer
            inFlightMessages:
              type: integer
            delayedMessages:
              type: integer
            oldestMessageAgeSeconds:
              type: integer
            deadLetterVisibleMessages:
              type: integer
            deadLetterOldestAgeSeconds:
              type: integer
            message:
              type: string
        warnings:
          type: array
          items:
            type: string
    AdminDLQMessages:
      type: object
      required: [configured, generatedAt, messages]
      properties:
        configured:
          type: boolean
        generatedAt:
          type: string
          format: date-time
        message:
          type: string
        warnings:
          type: array
          items:
            type: string
        messages:
          type: array
          items:
            $ref: "#/components/schemas/AdminDLQMessage"
    AdminDLQMessage:
      type: object
      required: [messageId, approximateAgeSeconds, approximateReceiveCount, bodyType, redriveable, summary]
      properties:
        messageId:
          type: string
        tenantId:
          type: string
        jobId:
          type: string
        sentAt:
          type: string
          format: date-time
        firstReceivedAt:
          type: string
          format: date-time
        approximateAgeSeconds:
          type: integer
        approximateReceiveCount:
          type: integer
        bodyType:
          type: string
          enum: [workspace_cohort_job, unknown]
        redriveable:
          type: boolean
        summary:
          type: string
    ArtifactInventory:
      type: object
      required: [jobId, tenantId, status, retentionDays, artifacts]
      properties:
        jobId:
          type: string
        tenantId:
          type: string
        status:
          type: string
        expiresAt:
          type: string
          format: date-time
        retentionDays:
          type: integer
        artifacts:
          type: array
          items:
            $ref: "#/components/schemas/ArtifactDescriptor"
    QualityReport:
      type: object
      required: [manifest, quality, exportValidation]
      properties:
        manifest:
          type: object
          additionalProperties: true
        quality:
          type: object
          additionalProperties: true
        exportValidation:
          $ref: "#/components/schemas/ExportValidationReport"
    ExportValidationReport:
      type: object
      required: [valid, fhir, ndjson, documents, x12]
      properties:
        valid:
          type: boolean
        fhir:
          $ref: "#/components/schemas/FHIRExportValidation"
        ndjson:
          type: array
          items:
            $ref: "#/components/schemas/NDJSONExportValidation"
        documents:
          $ref: "#/components/schemas/DocumentExportValidation"
        x12:
          $ref: "#/components/schemas/X12ExportValidation"
        issues:
          type: array
          items:
            type: string
    FHIRExportValidation:
      type: object
      required: [resourceCount, resourceTypes, referenceCount]
      properties:
        resourceCount:
          type: integer
        resourceTypes:
          type: object
          additionalProperties:
            type: integer
        referenceCount:
          type: integer
        unresolvedReferences:
          type: array
          items:
            type: string
        duplicateResourceIds:
          type: array
          items:
            type: string
        missingResourceIds:
          type: integer
    NDJSONExportValidation:
      type: object
      required: [name, resourceType, rowCount, valid]
      properties:
        name:
          type: string
          example: Patient.ndjson
        resourceType:
          type: string
          example: Patient
        rowCount:
          type: integer
        valid:
          type: boolean
        error:
          type: string
    DocumentExportValidation:
      type: object
      required: [totalDocuments, formats, parseableCcda, validHl7v2Messages, plainTextDocuments]
      properties:
        totalDocuments:
          type: integer
        formats:
          type: object
          additionalProperties:
            type: integer
        parseableCcda:
          type: integer
        validHl7v2Messages:
          type: integer
        plainTextDocuments:
          type: integer
    X12ExportValidation:
      type: object
      required:
        - totalInterchanges
        - conformantInterchanges
        - claim837Interchanges
        - remittance835Interchanges
      properties:
        totalInterchanges:
          type: integer
          minimum: 0
        conformantInterchanges:
          type: integer
          minimum: 0
        claim837Interchanges:
          type: integer
          minimum: 0
        remittance835Interchanges:
          type: integer
          minimum: 0
    ArtifactDescriptor:
      type: object
      required: [name, objectKey, contentType, sizeBytes, downloadPath, downloadUrlPath]
      properties:
        name:
          type: string
          example: attestation.json
        objectKey:
          type: string
        contentType:
          type: string
        sizeBytes:
          type: integer
        checksumSha256:
          type: string
        rowCount:
          type: integer
        downloadPath:
          type: string
          example: /workspace/me/cohort-jobs/job-000001/artifacts/patients.json
        downloadUrlPath:
          type: string
          example: /workspace/me/cohort-jobs/job-000001/artifacts/patients.json/download-url
    ArtifactDownloadURL:
      type: object
      required: [name, contentType, url, expiresAt, expiresInSeconds]
      properties:
        name:
          type: string
        contentType:
          type: string
        url:
          type: string
          format: uri
        expiresAt:
          type: string
          format: date-time
        expiresInSeconds:
          type: integer
    ScheduledCohortJob:
      type: object
      required: [id, tenantId, name, scheduleType, timezone, enabled, spec, nextRunAt, createdAt, updatedAt]
      properties:
        id:
          type: string
          example: scheduled-job-000001
        tenantId:
          type: string
        name:
          type: string
        scheduleType:
          type: string
          enum: [daily, weekly, monthly, cron]
        cronExpression:
          type: string
          description: Required when scheduleType is cron. Five-field cron expression (minute hour day-of-month month day-of-week).
          example: 0 9 * * 1
        hour:
          type: integer
          description: Hour for daily, weekly, and monthly schedules.
          minimum: 0
          maximum: 23
        minute:
          type: integer
          description: Minute for daily, weekly, and monthly schedules.
          minimum: 0
          maximum: 59
        dayOfWeek:
          type: integer
          description: Day of week for weekly schedules (0=Sunday).
          minimum: 0
          maximum: 6
        dayOfMonth:
          type: integer
          description: Day of month for monthly schedules.
          minimum: 1
          maximum: 31
        timezone:
          type: string
          example: America/New_York
        enabled:
          type: boolean
        spec:
          $ref: "#/components/schemas/CohortSpec"
        nextRunAt:
          type: string
          format: date-time
        lastRunAt:
          type: string
          format: date-time
        lastDispatchedAt:
          type: string
          format: date-time
          description: Wall-clock time of the most recent successful dispatch.
        lastRunStatus:
          type: string
          enum: [advanced, dispatched, rejected]
          description: Outcome of the most recently processed scheduled occurrence.
        lastRunError:
          type: string
          description: Tenant-visible reason when the most recent scheduled occurrence was permanently rejected.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    CreateScheduledCohortJobRequest:
      type: object
      required: [name, scheduleType, timezone, enabled, spec]
      properties:
        name:
          type: string
        scheduleType:
          type: string
          enum: [daily, weekly, monthly, cron]
        cronExpression:
          type: string
        hour:
          type: integer
        minute:
          type: integer
        dayOfWeek:
          type: integer
        dayOfMonth:
          type: integer
        timezone:
          type: string
        enabled:
          type: boolean
        spec:
          $ref: "#/components/schemas/CohortSpec"
    ScheduledCohortJobList:
      type: object
      required: [scheduledJobs]
      properties:
        scheduledJobs:
          type: array
          items:
            $ref: "#/components/schemas/ScheduledCohortJob"
    FHIRBulkExportStatus:
      type: object
      required: [transactionTime, request, requiresAccessToken, error]
      properties:
        transactionTime:
          type: string
          format: date-time
          description: Time the export transaction completed or was initiated.
        request:
          type: string
          description: URL of the original kickoff request.
        requiresAccessToken:
          type: boolean
          description: Always false for these public API-key-scoped exports.
        status:
          type: string
          description: Underlying cohort job status when still in progress.
        progress:
          type: integer
          description: Export progress percentage; always 0 until completion.
        output:
          type: array
          description: FHIR Bulk Data manifest output array, present when complete.
          items:
            $ref: "#/components/schemas/FHIRBulkExportOutput"
        error:
          type: array
          description: Empty array when the export succeeds.
          items:
            type: object
    FHIRBulkExportOutput:
      type: object
      required: [type, url, count]
      properties:
        type:
          type: string
          description: FHIR resource type contained in the file.
          example: Patient
        url:
          type: string
          description: Absolute download URL for the NDJSON file.
        count:
          type: integer
          description: Number of FHIR resources (rows) in the file.
    UsageAlert:
      type: object
      required: [id, tenantId, name, thresholdType, thresholdValue, status, createdAt, updatedAt]
      properties:
        id:
          type: string
          example: usage-alert-000001
        tenantId:
          type: string
          example: tenant-000001
        name:
          type: string
          example: High patient volume
        thresholdType:
          type: string
          enum: [patients, cost_cents, hie_provider_invocations, conversions_ccda_to_fhir, conversions_fhir_to_ccda, topology_edges, webhook_deliveries, simulator_runs_by_hie, trust_audit_calls, storage_byte_days, egress_bytes, credit_balance]
          example: patients
        thresholdValue:
          type: integer
          example: 100000
        thresholdPercent:
          type: integer
          minimum: 1
          maximum: 100
          description: Percentage of the plan quota that triggers the alert. Mutually exclusive with thresholdValue and unavailable for cost_cents.
        status:
          type: string
          enum: [ok, alert]
          example: alert
        triggeredAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    UsageAlertList:
      type: object
      required: [alerts]
      properties:
        alerts:
          type: array
          items:
            $ref: "#/components/schemas/UsageAlert"
    CreateUsageAlertRequest:
      type: object
      required: [name, thresholdType]
      oneOf:
        - required: [thresholdValue]
        - required: [thresholdPercent]
      properties:
        name:
          type: string
          example: High patient volume
        thresholdType:
          type: string
          enum: [patients, cost_cents, hie_provider_invocations, conversions_ccda_to_fhir, conversions_fhir_to_ccda, topology_edges, webhook_deliveries, simulator_runs_by_hie, trust_audit_calls, storage_byte_days, egress_bytes, credit_balance]
          example: patients
        thresholdValue:
          type: integer
          example: 100000
        thresholdPercent:
          type: integer
          minimum: 1
          maximum: 100
    UpdateUsageAlertRequest:
      type: object
      properties:
        name:
          type: string
        thresholdType:
          type: string
          enum: [patients, cost_cents, hie_provider_invocations, conversions_ccda_to_fhir, conversions_fhir_to_ccda, topology_edges, webhook_deliveries, simulator_runs_by_hie, trust_audit_calls, storage_byte_days, egress_bytes, credit_balance]
        thresholdValue:
          type: integer
        thresholdPercent:
          type: integer
          minimum: 1
          maximum: 100
    ConnectorMetrics:
      type: object
      required: [connectorId, totalDeliveries, successfulDeliveries, failedDeliveries, replayedDeliveries]
      properties:
        connectorId:
          type: string
          example: conn-000001
        totalDeliveries:
          type: integer
          example: 42
        successfulDeliveries:
          type: integer
          example: 38
        failedDeliveries:
          type: integer
          example: 4
        replayedDeliveries:
          type: integer
          example: 2
        lastDeliveredAt:
          type: string
          format: date-time
        lastFailureAt:
          type: string
          format: date-time
    FHIRValidationReport:
      type: object
      required: [valid, resourceCount, errorCount, warningCount, infoCount]
      properties:
        valid:
          type: boolean
          example: true
        resourceCount:
          type: integer
          example: 273
        ndjsonFileCount:
          type: integer
          example: 0
        ndjsonResourceCount:
          type: integer
          example: 0
        requiredReferenceCount:
          type: integer
          example: 412
        brokenReferenceCount:
          type: integer
          example: 0
        syntheticExtensionCount:
          type: integer
          example: 1
        syntheticLocalCodingCount:
          type: integer
          example: 1
        errorCount:
          type: integer
          example: 0
        warningCount:
          type: integer
          example: 1
        infoCount:
          type: integer
          example: 1
        findings:
          type: array
          items:
            $ref: "#/components/schemas/FHIRValidationFinding"
    FHIRProfileComplianceReport:
      type: object
      required: [profile, compliant, errorCount, warningCount]
      properties:
        profile:
          type: string
          example: us-core
        compliant:
          type: boolean
        errorCount:
          type: integer
          minimum: 0
        warningCount:
          type: integer
          minimum: 0
        findings:
          type: array
          items:
            $ref: "#/components/schemas/FHIRValidationFinding"
    FHIRValidationFinding:
      type: object
      required: [severity, code, message]
      properties:
        severity:
          type: string
          enum: [error, warning, info]
          example: warning
        code:
          type: string
          example: synthetic-local-coding
        resourceType:
          type: string
          example: Bundle
        resourceId:
          type: string
          example: bundle-000001
        field:
          type: string
          example: coding.system
        message:
          type: string
          example: Synthetic local code systems intentionally model source-specific terminology drift.
    CCDAConformanceReport:
      type: object
      required: [valid, referenceChecks, entryCount]
      properties:
        valid:
          type: boolean
          example: true
        documentTemplateIds:
          type: array
          items:
            type: string
          example: ["2.16.840.1.113883.10.20.22.1.2"]
        sections:
          type: array
          items:
            type: string
          example: ["Allergies and Intolerances", "Medications", "Problem List"]
        referenceChecks:
          type: integer
          example: 24
        entryCount:
          type: integer
          example: 18
        findings:
          type: array
          items:
            $ref: "#/components/schemas/CCDAConformanceFinding"
    CCDAConformanceFinding:
      type: object
      required: [rule, severity, message]
      properties:
        rule:
          type: string
          example: required-section
        severity:
          type: string
          enum: [error, warning]
          example: error
        message:
          type: string
          example: Required section is missing or unrecognized.
        path:
          type: string
          example: section
    X12ConformanceReport:
      type: object
      required:
        - valid
        - interchangeCount
        - functionalGroupCount
        - transactionSetCount
        - claim837Count
        - remittance835Count
        - serviceLineCount
        - diagnosisCount
      properties:
        valid:
          type: boolean
          example: true
        interchangeCount:
          type: integer
          minimum: 0
          example: 2
        functionalGroupCount:
          type: integer
          minimum: 0
          example: 2
        transactionSetCount:
          type: integer
          minimum: 0
          example: 2
        claim837Count:
          type: integer
          minimum: 0
          example: 1
        remittance835Count:
          type: integer
          minimum: 0
          example: 1
        serviceLineCount:
          type: integer
          minimum: 0
          example: 2
        diagnosisCount:
          type: integer
          minimum: 0
          example: 1
        findings:
          type: array
          items:
            $ref: "#/components/schemas/X12ConformanceFinding"
    X12ConformanceFinding:
      type: object
      required: [rule, severity, message]
      properties:
        rule:
          type: string
          example: transaction-control
        severity:
          type: string
          enum: [error, warning]
          example: error
        message:
          type: string
          example: SE02 does not match ST02.
        interchange:
          type: integer
          minimum: 0
          example: 1
        segment:
          type: integer
          minimum: 0
          example: 19
    ConversionCapabilityReport:
      type: object
      required: [enabled]
      properties:
        enabled:
          type: boolean
          example: true
    ConversionHealthReport:
      type: object
      required: [ok]
      properties:
        ok:
          type: boolean
          example: true
    FHIRToCorpusResponse:
      type: object
      required: [ccdaXML, patientCount, documentCount, resourceCounts]
      properties:
        ccdaXML:
          type: string
          format: xml
          example: '<?xml version="1.0"?><ClinicalDocument xmlns="urn:hl7-org:v3"/>'
        patientCount:
          type: integer
          example: 1
        documentCount:
          type: integer
          example: 1
        resourceCounts:
          type: object
          additionalProperties:
            type: integer
          example:
            Patient: 1
            Condition: 2
    ConverterFidelityReport:
      type: object
      required: [enabled, status, overall]
      properties:
        enabled:
          type: boolean
          example: true
        status:
          type: string
          example: ok
        overall:
          type: number
          format: double
          example: 0.92
        preservationOverall:
          type: number
          format: double
          example: 0.85
        documentScores:
          type: array
          items:
            $ref: "#/components/schemas/ConverterFidelityScore"
        error:
          type: string
          example: converter returned an empty bundle
    ConverterFidelityScore:
      type: object
      required: [documentId, status, resourceCountScore, attributionScore, identifierScore, sectionScore, clinicalContentScore, terminologyWeight, terminologyScore, terminologyExpected, terminologyMatched, temporalWeight, temporalScore, temporalExpected, temporalMatched, quantityWeight, quantityScore, quantityExpected, quantityMatched, overall]
      properties:
        documentId:
          type: string
          example: doc-000001
        sourceSystem:
          type: string
          example: regional-hie
        status:
          type: string
          example: ok
        resourceCountScore:
          type: number
          format: double
          example: 0.95
        attributionScore:
          type: number
          format: double
          example: 0.9
        identifierScore:
          type: number
          format: double
          example: 0.88
        sectionScore:
          type: number
          format: double
          example: 0.91
        clinicalContentScore:
          type: number
          format: double
          example: 0.93
        terminologyWeight:
          type: number
          format: double
          description: Effective weight applied to terminologyScore for this document; zero when terminology is not applicable.
          example: 0.13
        terminologyScore:
          type: number
          format: double
          description: Fraction of native SNOMED CT, LOINC, RxNorm, and ICD-10 codings preserved with the same system and code.
          example: 0.96
        terminologyExpected:
          type: integer
          description: Number of eligible terminology codings in the native bundle.
          example: 25
        terminologyMatched:
          type: integer
          description: Number of native terminology codings preserved by the conversion.
          example: 24
        temporalWeight:
          type: number
          format: double
          description: Effective weight applied to temporalScore for this document; zero when temporal fidelity is not applicable.
          example: 0.08
        temporalScore:
          type: number
          format: double
          description: Fraction of native effectiveDateTime, onsetDateTime, and issued values preserved.
          example: 0.95
        temporalExpected:
          type: integer
          description: Number of eligible clinical timestamps in the native bundle.
          example: 20
        temporalMatched:
          type: integer
          description: Number of native clinical timestamps preserved by the conversion.
          example: 19
        quantityWeight:
          type: number
          format: double
          description: Effective weight applied to quantityScore for this document; zero when quantity fidelity is not applicable.
          example: 0.08
        quantityScore:
          type: number
          format: double
          description: Fraction of native Observation valueQuantity values and UCUM units preserved.
          example: 0.9
        quantityExpected:
          type: integer
          description: Number of eligible UCUM Observation quantities in the native bundle.
          example: 10
        quantityMatched:
          type: integer
          description: Number of native UCUM Observation quantities preserved by the conversion.
          example: 9
        overall:
          type: number
          format: double
          example: 0.92
        preservation:
          $ref: "#/components/schemas/ConverterFidelityPreservationScore"
        notes:
          type: array
          items:
            type: string
          example: ["author extension missing"]
    ConverterFidelityPreservationScore:
      type: object
      required: [documentId, overall, authorSurvived, custodianSurvived, legalAttesterSurvived, documentIdSurvived, deliveryHopsSurvived, registryRepositorySurvived]
      properties:
        documentId:
          type: string
          example: doc-000001
        sourceSystem:
          type: string
          example: regional-hie
        overall:
          type: number
          format: double
          example: 0.85
        authorSurvived:
          type: boolean
          example: true
        custodianSurvived:
          type: boolean
          example: true
        legalAttesterSurvived:
          type: boolean
          example: false
        documentIdSurvived:
          type: boolean
          example: true
        deliveryHopsSurvived:
          type: boolean
          example: false
        registryRepositorySurvived:
          type: boolean
          example: true
        notes:
          type: array
          items:
            type: string
          example: ["legal attester stripped by converter"]
    WorkspaceListEntry:
      type: object
      required: [id, name, plan, role, isDefault]
      properties:
        id:
          type: string
          example: tenant-000001
        name:
          type: string
          example: greg@darknex.us workspace
        plan:
          type: string
          description: The workspace plan identifier.
          example: developer
        role:
          $ref: "#/components/schemas/WorkspaceRole"
        isDefault:
          type: boolean
          description: True for the user's default (email-owned) workspace.
          example: true
    WorkspaceList:
      type: object
      required: [workspaces, defaultWorkspaceId]
      properties:
        workspaces:
          type: array
          items:
            $ref: "#/components/schemas/WorkspaceListEntry"
        defaultWorkspaceId:
          type: string
          description: Tenant ID of the user's default (email-owned) workspace.
          example: tenant-000001
    WorkspaceQuota:
      type: object
      required: [tenantId, planId, planName, monthlyPatientQuota, patientsGenerated, patientQuotaRemaining, monthlyGenerationJobQuota, generationJobCount, workerInvocations, generationJobQuotaRemaining, monthlyHieProviderInvocationsQuota, hieProviderInvocations, hieProviderInvocationsRemaining, monthlyConversionsCcdaToFhirQuota, conversionsCcdaToFhir, conversionsCcdaToFhirRemaining, monthlyConversionsFhirToCcdaQuota, conversionsFhirToCcda, conversionsFhirToCcdaRemaining, monthlyTopologyEdgesQuota, topologyEdges, topologyEdgesRemaining, monthlyWebhookDeliveriesQuota, webhookDeliveries, webhookDeliveriesRemaining, monthlySimulatorRunsByHieQuota, simulatorRunsByHie, simulatorRunsByHieRemaining, monthlyStorageByteDaysQuota, storageByteDays, storageByteDaysRemaining, monthlyEgressBytesQuota, egressBytes, egressBytesRemaining, creditBalanceCents, freeTriggerBalance, estimatedOverageCents]
      properties:
        tenantId:
          type: string
          example: tenant-000001
        planId:
          type: string
          example: developer
        planName:
          type: string
          example: Developer
        monthlyPatientQuota:
          type: integer
          example: 125000
        patientsGenerated:
          type: integer
          example: 42
        patientQuotaRemaining:
          type: integer
          example: 124958
        percentOfPatientQuota:
          type: number
          format: double
          example: 0.0336
        monthlyGenerationJobQuota:
          type: integer
          example: 600
        generationJobCount:
          type: integer
          example: 3
        workerInvocations:
          type: integer
          description: Execution telemetry count. This dimension is not priced or quota-enforced.
          example: 3
        aiDesignInvocations:
          type: integer
          description: Bedrock Converse calls made by the AI cohort designer. Metering-only; no quota or price is enforced.
          example: 0
        generationJobQuotaRemaining:
          type: integer
          example: 597
        monthlyHieProviderInvocationsQuota:
          type: integer
          example: 1000
        hieProviderInvocations:
          type: integer
          example: 0
        hieProviderInvocationsRemaining:
          type: integer
          example: 1000
        percentOfHieProviderInvocationsQuota:
          type: number
          format: double
          example: 0.0
        monthlyConversionsCcdaToFhirQuota:
          type: integer
          example: 500
        conversionsCcdaToFhir:
          type: integer
          example: 0
        conversionsCcdaToFhirRemaining:
          type: integer
          example: 500
        percentOfConversionsCcdaToFhirQuota:
          type: number
          format: double
          example: 0.0
        monthlyConversionsFhirToCcdaQuota:
          type: integer
          example: 500
        conversionsFhirToCcda:
          type: integer
          example: 0
        conversionsFhirToCcdaRemaining:
          type: integer
          example: 500
        percentOfConversionsFhirToCcdaQuota:
          type: number
          format: double
          example: 0.0
        monthlyTopologyEdgesQuota:
          type: integer
          example: 1000
        topologyEdges:
          type: integer
          example: 0
        topologyEdgesRemaining:
          type: integer
          example: 1000
        percentOfTopologyEdgesQuota:
          type: number
          format: double
          example: 0.0
        monthlyWebhookDeliveriesQuota:
          type: integer
          example: 1000
        webhookDeliveries:
          type: integer
          example: 0
        webhookDeliveriesRemaining:
          type: integer
          example: 1000
        percentOfWebhookDeliveriesQuota:
          type: number
          format: double
          example: 0.0
        monthlySimulatorRunsByHieQuota:
          type: integer
          example: 500
        simulatorRunsByHie:
          type: integer
          example: 0
        simulatorRunsByHieRemaining:
          type: integer
          example: 500
        percentOfSimulatorRunsByHieQuota:
          type: number
          format: double
          example: 0.0
        monthlyTrustAuditCallsQuota:
          type: integer
          example: 0
        trustAuditCalls:
          type: integer
          example: 0
        trustAuditCallsRemaining:
          type: integer
          example: 0
        percentOfTrustAuditCallsQuota:
          type: number
          format: double
          example: 0.0
        monthlyStorageByteDaysQuota:
          type: integer
          example: 0
        storageByteDays:
          type: integer
          example: 0
        storageByteDaysRemaining:
          type: integer
          example: 0
        percentOfStorageByteDaysQuota:
          type: number
          format: double
          example: 0.0
        monthlyEgressBytesQuota:
          type: integer
          example: 0
        egressBytes:
          type: integer
          example: 0
        egressBytesRemaining:
          type: integer
          example: 0
        percentOfEgressBytesQuota:
          type: number
          format: double
          example: 0.0
        creditBalanceCents:
          type: integer
          example: 0
        freeTriggerBalance:
          type: integer
          example: 0
        estimatedOverageCents:
          type: integer
          example: 0
    DirectoryEndpoint:
      type: object
      required: [resourceType, id, status, connectionType, name, address]
      properties:
        resourceType:
          type: string
          example: Endpoint
        id:
          type: string
          example: regional-hie-endpoint
        status:
          type: string
          example: active
        connectionType:
          type: object
          properties:
            system:
              type: string
            code:
              type: string
            display:
              type: string
        name:
          type: string
          example: regional-hie Endpoint
        managingOrganization:
          type: object
          properties:
            reference:
              type: string
            display:
              type: string
        address:
          type: string
          example: https://regional-hie.sandbox-hie.example.org
        payloadType:
          type: array
          items:
            type: object
    DirectoryAffiliation:
      type: object
      required: [resourceType, id, active, organization, participatingOrganization, network]
      properties:
        resourceType:
          type: string
          example: OrganizationAffiliation
        id:
          type: string
          example: regional-hie-affiliation
        active:
          type: boolean
        organization:
          type: object
          properties:
            reference:
              type: string
            display:
              type: string
        participatingOrganization:
          type: object
          properties:
            reference:
              type: string
            display:
              type: string
        network:
          type: array
          items:
            type: object
            properties:
              reference:
                type: string
              display:
                type: string
        endpoint:
          type: array
          items:
            type: object
    DirectoryEndpointBundle:
      type: object
      required: [resourceType, type, total, entry]
      properties:
        resourceType:
          type: string
          example: Bundle
        type:
          type: string
          example: searchset
        total:
          type: integer
        entry:
          type: array
          items:
            type: object
            properties:
              resource:
                $ref: "#/components/schemas/DirectoryEndpoint"
    DirectoryAffiliationBundle:
      type: object
      required: [resourceType, type, total, entry]
      properties:
        resourceType:
          type: string
          example: Bundle
        type:
          type: string
          example: searchset
        total:
          type: integer
        entry:
          type: array
          items:
            type: object
            properties:
              resource:
                $ref: "#/components/schemas/DirectoryAffiliation"
    ConformancePackSummary:
      type: object
      required: [id, name, category, description, scenarioName, population]
      properties:
        id:
          type: string
          example: break-glass-denial
        name:
          type: string
          example: Break-glass denial
        category:
          type: string
          example: release-routing
        description:
          type: string
        scenarioName:
          type: string
          example: pediatric-asthma-hie
        population:
          type: integer
          example: 64
    ConformancePackListResponse:
      type: object
      required: [packs]
      properties:
        packs:
          type: array
          items:
            $ref: "#/components/schemas/ConformancePackSummary"
    ConformanceAssertionResult:
      type: object
      required: [name, passed, durationMs]
      properties:
        name:
          type: string
          example: break_glass_required_exists
        passed:
          type: boolean
        detail:
          type: string
        count:
          type: integer
        durationMs:
          type: number
          format: double
          description: Assertion execution duration in milliseconds.
    ConformancePackResult:
      type: object
      required: [packId, packName, passed, generatedAt, scenario, assertions, durationMs]
      properties:
        packId:
          type: string
        packName:
          type: string
        passed:
          type: boolean
        generatedAt:
          type: string
          format: date-time
        scenario:
          $ref: "#/components/schemas/CohortSpec"
        assertions:
          type: array
          items:
            $ref: "#/components/schemas/ConformanceAssertionResult"
        durationMs:
          type: number
          format: double
          description: Total pack execution duration in milliseconds.
