openapi: 3.0.3
info:
  title: AutoData API
  version: 2.0.0
  description: >-
    Programmatic access to the AutoData ML data-preparation pipeline.
    Every endpoint below is authenticated with an API key issued from
    the dashboard, sent as `Authorization: Bearer dtpk_...`.
    This file is GENERATED from the server url_map by
    scripts/generate_openapi.py — do not hand-edit; regenerate.
servers:
  - url: https://autodata.datatoolpack.com
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Account
  - name: Assess
  - name: Automation
  - name: Connectors
  - name: Enterprise
  - name: Inference & Retraining
  - name: Other
  - name: Pipeline
  - name: Preferences
  - name: Sessions
  - name: Sharing
  - name: Streaming
  - name: Templates
  - name: Utilities
paths:
  /api/v1/account/contracts:
    get:
      tags: [Account]
      operationId: v1_account_contracts_get
      summary: >-
        The signed-in customer's own contracts, with usage against allowance.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/account/profile:
    get:
      tags: [Account]
      operationId: api_v1_account_profile
      summary: Credit balance, role and API limits for the authenticated account.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/account/trial-status:
    get:
      tags: [Account]
      operationId: v1_auth_trial_status_get
      summary: Get trial user status (uploads remaining)
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/account/usage:
    get:
      tags: [Account]
      operationId: api_v1_account_usage
      summary: Account-wide usage (all keys + dashboard), broken down by tool.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/assess/from-source:
    post:
      tags: [Assess]
      operationId: assess_from_source
      summary: >-
        Profile a previous run's input (session_id) or a connector sample for an assessment.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/assess/jobs:
    get:
      tags: [Assess]
      operationId: assess_list_jobs
      summary: Your recent assessments.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/assess/upload:
    post:
      tags: [Assess]
      operationId: assess_upload
      summary: >-
        Upload a dataset (multipart "file") and profile it for an assessment.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                config:
                  type: string
                  description: "JSON run configuration."
                outputPreferences:
                  type: string
                  description: >-
                    JSON object of output preferences. `output_format`
                    is one of: csv, parquet, xlsx, json, jsonl, ndjson, feather, orc.
                    An output that cannot be written in the chosen
                    format falls back to csv and the run reports it.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/assess/{job_id}:
    delete:
      tags: [Assess]
      operationId: assess_delete_job
      summary: Delete an assessment and its stored dataset.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Assess]
      operationId: assess_get_job
      summary: >-
        One assessment: profile, intake answers, score, advisory and auto-configuration.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/advise:
    post:
      tags: [Assess]
      operationId: assess_advise
      summary: Plain-English advisory from the language model; never changes the score.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/assess:
    post:
      tags: [Assess]
      operationId: assess_run
      summary: Score readiness (0-100, grade, blockers, recommendations); model_family re-scores.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/file:
    get:
      tags: [Assess]
      operationId: assess_dataset_file
      summary: Download the dataset stored for this assessment.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/intake:
    post:
      tags: [Assess]
      operationId: assess_intake
      summary: >-
        Save the intake answers: goal, model family, targets, exclusions, compute, entity/time columns.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/pipeline-config:
    get:
      tags: [Assess]
      operationId: assess_pipeline_config
      summary: The auto-configuration as a Pipeline / LM Readiness form.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/assess/{job_id}/report:
    get:
      tags: [Assess]
      operationId: assess_report
      summary: The full assessment report as HTML.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/automation/{kind}/{item_id}/runs:
    get:
      tags: [Automation]
      operationId: automation_runs
      summary: >-
        Recent runs of a listener / scheduled run / trigger (``limit``, default 20).
      parameters:
        - name: item_id
          in: path
          required: true
          schema: {type: string}
        - name: kind
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/cancel/{session_id}:
    post:
      tags: [Pipeline]
      operationId: api_v1_cancel
      summary: Cancel a running session.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/connectors/{connector_type}/discover:
    post:
      tags: [Connectors]
      operationId: discover_connector
      summary: discover connector
      parameters:
        - name: connector_type
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/connectors/{connector_type}/preview:
    post:
      tags: [Connectors]
      operationId: preview_connector
      summary: preview connector
      parameters:
        - name: connector_type
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/connectors/{connector_type}/test:
    post:
      tags: [Connectors]
      operationId: test_connector
      summary: test connector
      parameters:
        - name: connector_type
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/credentials:
    get:
      tags: [Connectors]
      operationId: list_credentials
      summary: list credentials
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Connectors]
      operationId: create_credential
      summary: create credential
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/credentials/{credential_id}:
    delete:
      tags: [Connectors]
      operationId: delete_credential
      summary: delete credential
      parameters:
        - name: credential_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Connectors]
      operationId: update_credential
      summary: update credential
      parameters:
        - name: credential_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/dataset-metadata/catalog/import:
    post:
      tags: [Other]
      operationId: enterprise_catalog_import
      summary: >-
        Read a table's entry from a data catalog as dataset metadata.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/dataset-metadata/catalog/tables:
    post:
      tags: [Other]
      operationId: enterprise_catalog_tables
      summary: List the tables a data catalog import can pick from.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/dataset-metadata/catalog/test:
    post:
      tags: [Other]
      operationId: enterprise_catalog_test
      summary: Test a connection that exists only to read a data catalog.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/dataset-metadata/validate:
    post:
      tags: [Other]
      operationId: enterprise_dataset_metadata_validate
      summary: Read a data dictionary and return it normalized, with warnings.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/download-archive/{session_id}:
    get:
      tags: [Pipeline]
      operationId: api_v1_download_archive_get
      summary: Download all result files as a ZIP archive (no filter).
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    post:
      tags: [Pipeline]
      operationId: api_v1_download_archive
      summary: Download all result files as a ZIP archive.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/download/{session_id}/{filename}:
    get:
      tags: [Pipeline]
      operationId: api_v1_download_file
      summary: Download an individual result file via API key auth.
      parameters:
        - name: filename
          in: path
          required: true
          schema: {type: string}
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/audit-report/{session_id}:
    get:
      tags: [Enterprise]
      operationId: enterprise_audit_report
      summary: >-
        The downloadable audit trail. ?format=json|html (html by default).
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/docs:
    get:
      tags: [Enterprise]
      operationId: enterprise_internals_index
      summary: >-
        The "How it works" module guides available to this account.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/enterprise/docs/{module_id}:
    get:
      tags: [Enterprise]
      operationId: enterprise_internals_module
      summary: >-
        One module's "How it works" guide.
      parameters:
        - name: module_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/families:
    get:
      tags: [Enterprise]
      operationId: enterprise_families
      summary: The model families a run can be prepared for, and what each changes.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/enterprise/lineage/{session_id}:
    get:
      tags: [Enterprise]
      operationId: enterprise_lineage
      summary: >-
        Everything recorded about a run: stages, families, every decision.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/lineage/{session_id}/diff:
    get:
      tags: [Enterprise]
      operationId: enterprise_lineage_diff
      summary: >-
        What changed between this run's decisions and another run's.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/runs/{session_id}/columns:
    get:
      tags: [Enterprise]
      operationId: enterprise_columns
      summary: >-
        The per-column ledger: what every column got, and why.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/runs/{session_id}/dataset-metadata:
    get:
      tags: [Enterprise]
      operationId: enterprise_run_dataset_metadata
      summary: The metadata a run was given, and what it did to the data.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/enterprise/runs/{session_id}/leaderboard:
    get:
      tags: [Enterprise]
      operationId: enterprise_leaderboard_view
      summary: How the model families compared, and which one is recommended.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/estimate:
    post:
      tags: [Other]
      operationId: api_v1_estimate
      summary: >-
        Price a run before starting it. The reply also carries estimated_seconds
        (a heuristic running time, with its basis under estimated_seconds_basis;
        pass image_columns / audio_columns or media={...} so media is counted).
        A stated input_rows below 5 is refused with 400 TOO_FEW_ROWS.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '400': {description: Too few rows (TOO_FEW_ROWS) or a missing size}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/feature-engineering/columns:
    get:
      tags: [Other]
      operationId: feature_selection_columns
      summary: >-
        The columns a completed session's ranking can target, so the tab can offer them as buttons instead of asking for a comma-separated list.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/feature-engineering/recommend:
    post:
      tags: [Other]
      operationId: feature_selection_recommend
      summary: >-
        F4 — rank a completed session's columns WITHOUT re-running the pipeline.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/feature-selection/columns:
    get:
      tags: [Utilities]
      operationId: feature_selection_columns
      summary: >-
        The columns a completed session's ranking can target, so the tab can offer them as buttons instead of asking for a comma-separated list.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/feature-selection/recommend:
    post:
      tags: [Utilities]
      operationId: feature_selection_recommend
      summary: >-
        F4 — rank a completed session's columns WITHOUT re-running the pipeline.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/inference:
    post:
      tags: [Inference & Retraining]
      operationId: inference
      summary: Lightweight inference endpoint for scoring new data.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                config:
                  type: string
                  description: "JSON run configuration."
                outputPreferences:
                  type: string
                  description: >-
                    JSON object of output preferences. `output_format`
                    is one of: csv, parquet, xlsx, json, jsonl, ndjson, feather, orc.
                    An output that cannot be written in the chosen
                    format falls back to csv and the run reports it.
                quote_id:
                  type: string
                  description: >-
                    An exact quote from /api/v1/estimate with session_type
                    inference; the run is charged exactly that price. 409 when the
                    file or settings no longer match the quote.
      responses:
        '200': {description: Success}
        '409': {description: The confirmed quote no longer matches this file or these settings}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/inference-retraining:
    post:
      tags: [Inference & Retraining]
      operationId: inference_retraining
      summary: >-
        REMOVED: use /inference or /retraining instead.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/keys:
    get:
      tags: [Account]
      operationId: api_v1_list_keys
      summary: >-
        List the authenticated user's API keys (no secrets exposed).
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/listeners/folder:
    get:
      tags: [Automation]
      operationId: list_folder_listeners
      summary: list folder listeners
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Automation]
      operationId: create_folder_listener
      summary: create folder listener
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/listeners/folder/preview-source:
    post:
      tags: [Automation]
      operationId: preview_listener_source
      summary: >-
        What a listener would pick up now: newest files plus the head of one.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/listeners/folder/{listener_id}:
    delete:
      tags: [Automation]
      operationId: delete_folder_listener
      summary: delete folder listener
      parameters:
        - name: listener_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Automation]
      operationId: update_folder_listener
      summary: update folder listener
      parameters:
        - name: listener_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/mapping/apply:
    post:
      tags: [Utilities]
      operationId: apply_column_mapping
      summary: >-
        Apply column mapping to a session's data. Renames columns based on the mapping.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/mapping/suggest:
    post:
      tags: [Utilities]
      operationId: suggest_column_mapping
      summary: Auto-suggest column mappings between source columns and target schema.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/media/validate:
    post:
      tags: [Pipeline]
      operationId: v1_validate_media_files_post
      summary: >-
        Check a dataset's media references against the files you intend to upload, before uploading them.
      description: >-
        `valid` is true only when every uploaded name is referenced, every
        referenced name is uploaded, and the upload would not be refused
        (extension, file count, names that save to the same file, a trial
        account's size cap). URLs in the data are fetched at run time and are
        not checked here.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required: [csv, mediaType, uploadedFilenames]
              properties:
                csv:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                mediaType:
                  type: string
                  enum: [image, audio]
                uploadedFilenames:
                  type: array
                  items: {type: string}
                  description: "Names of the files you intend to upload (repeat the field)."
                uploadedSizes:
                  type: array
                  items: {type: integer}
                  description: "Optional byte sizes, in the same order, for the trial size check."
                imageColumns:
                  type: string
                  description: "JSON array of image columns; default image_file_name."
                audioColumns:
                  type: string
                  description: "JSON array of audio columns; default audio_file_name."
      responses:
        '200':
          description: >-
            Validation report: valid, column_found, references_without_file,
            references_without_file_count, uploaded_files_without_match,
            rejected_files, name_collisions, too_many_files, max_files,
            trial_media_cap, total_referenced, total_uploaded, total_matched,
            message.
        '400': {description: Missing parameters or unreadable data file}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '413': {description: More files than one request takes (TOO_MANY_FILES)}
  /api/v1/mode-preview:
    post:
      tags: [Pipeline]
      operationId: api_v1_mode_preview
      summary: What a speed mode would change about your parameters, without running.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/notification-preferences:
    get:
      tags: [Account]
      operationId: ux_get_notification_preferences
      summary: ux get notification preferences
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    put:
      tags: [Account]
      operationId: ux_put_notification_preferences
      summary: ux put notification preferences
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/pending-approvals:
    get:
      tags: [Automation]
      operationId: v1_list_pending_approvals_get
      summary: >-
        The caller's automated runs held because their price is above the limit.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/pending-approvals/{approval_id}/preview:
    get:
      tags: [Automation]
      operationId: preview_pending_approval
      summary: >-
        First rows of a held run's data, so it can be checked before approving.
      parameters:
        - name: approval_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/pending-approvals/{approval_id}/{action}:
    post:
      tags: [Automation]
      operationId: v1_decide_pending_approval_post
      summary: Approve (queue at the shown price, charged exactly) or discard a held run.
      parameters:
        - name: action
          in: path
          required: true
          schema: {type: string}
        - name: approval_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/pipeline-config/decide:
    post:
      tags: [Pipeline]
      operationId: ux_config_decide_v1
      summary: Settings the data and metadata support, for the configuration form.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/pipeline-templates:
    get:
      tags: [Templates]
      operationId: ux_list_pipeline_templates
      summary: ux list pipeline templates
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Templates]
      operationId: ux_create_pipeline_template
      summary: ux create pipeline template
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/pipeline-templates/{template_id}:
    delete:
      tags: [Templates]
      operationId: ux_delete_pipeline_template
      summary: ux delete pipeline template
      parameters:
        - name: template_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Templates]
      operationId: ux_update_pipeline_template
      summary: ux update pipeline template
      parameters:
        - name: template_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/pivot/suggest:
    post:
      tags: [Other]
      operationId: pivot_suggest
      summary: >-
        Rank the columns that could be the run's as-of time, and say why.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/advanced:
    get:
      tags: [Preferences]
      operationId: v1_get_advanced_parameters_get
      summary: >-
        Get user's advanced parameters
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Preferences]
      operationId: v1_set_advanced_parameters_post
      summary: >-
        Set user's advanced parameters
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/advanced/reset:
    post:
      tags: [Preferences]
      operationId: v1_reset_advanced_parameters_post
      summary: >-
        Reset user's advanced parameters to defaults
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/anomaly:
    get:
      tags: [Preferences]
      operationId: v1_get_anomaly_parameters_get
      summary: >-
        Get user's anomaly detection parameters
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Preferences]
      operationId: v1_set_anomaly_parameters_post
      summary: >-
        Set user's anomaly detection parameters
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/anomaly/reset:
    post:
      tags: [Preferences]
      operationId: v1_reset_anomaly_parameters_post
      summary: >-
        Reset user's anomaly detection parameters to defaults
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/api-anomaly:
    get:
      tags: [Preferences]
      operationId: v1_get_api_account_anomaly_parameters_get
      summary: >-
        Get user's API anomaly detection parameters
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Preferences]
      operationId: v1_set_api_account_anomaly_parameters_post
      summary: >-
        Set user's API anomaly detection parameters
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/api-anomaly/reset:
    post:
      tags: [Preferences]
      operationId: v1_reset_api_account_anomaly_parameters_post
      summary: >-
        Reset user's API anomaly detection parameters to defaults
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/completion:
    get:
      tags: [Preferences]
      operationId: v1_get_completion_parameters_get
      summary: >-
        Get user's dataset completion parameters
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Preferences]
      operationId: v1_set_completion_parameters_post
      summary: >-
        Set user's dataset completion parameters
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/completion/reset:
    post:
      tags: [Preferences]
      operationId: v1_reset_completion_parameters_post
      summary: >-
        Reset user's dataset completion parameters to defaults
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/outputs:
    get:
      tags: [Preferences]
      operationId: v1_get_output_preferences_get
      summary: >-
        Get user's output file preferences
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Preferences]
      operationId: v1_set_output_preferences_post
      summary: >-
        Set user's output file preferences
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preferences/outputs/reset:
    post:
      tags: [Preferences]
      operationId: v1_reset_output_preferences_post
      summary: >-
        Reset user's output preferences to default
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/preview-file:
    post:
      tags: [Pipeline]
      operationId: preview_uploaded_file
      summary: >-
        First rows of an uploaded data file (multipart ``file``, optional ``rows``).
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/pricing/profile/{profile_id}:
    get:
      tags: [Other]
      operationId: pricing_profile_status
      summary: Progress of an upload being measured for its exact price (owner only).
      parameters:
        - name: profile_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/process:
    post:
      tags: [Pipeline]
      operationId: api_v1_process
      summary: Start a pipeline job from an uploaded file (API key or passcode).
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                config:
                  type: string
                  description: >-
                    JSON run configuration. Optional lm_readiness selects LM Readiness.
                    Supports profile (tabular_transformer or event_sequence), roles
                    (entity, time, amount, category, counterparty), level (E1, E2, auto),
                    representation (typed or feature_tokens), and sequence_length (32).
                    action replay requires base_session_id inside lm_readiness.
                    validation_policy and dataset_metadata use the existing shared schemas.
                    Every pipeline setting the dashboard offers is accepted at the top
                    level or inside advanced_params, snake_case or camelCase: task_types,
                    anomaly_params, completion_params, output_preferences, model_ready_split,
                    session_name, webhook_ids, speed_mode and the explicit enable_* flags.
                    llm_enabled (boolean, default true) and strict_llm (boolean, default
                    false) are the per-run data-residency switches. slm_understanding
                    (boolean, default false, every plan) uses the on-box small language
                    model to recognise IDs, codes and times and to unify misspelt values
                    during cleaning; it runs locally and obeys llm_enabled.
                    An Idempotency-Key header makes a retried request return the first
                    session instead of starting a second run.
                history:
                  type: string
                  format: binary
                  description: Optional prior-event source for LM Readiness replay.
                outputPreferences:
                  type: string
                  description: >-
                    JSON object of output preferences. `output_format`
                    is one of: csv, parquet, xlsx, json, jsonl, ndjson, feather, orc.
                    An output that cannot be written in the chosen
                    format falls back to csv and the run reports it.
      responses:
        '200': {description: Success}
        '202': {description: LM Readiness job accepted; poll existing status and result endpoints.}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/process-connector:
    post:
      tags: [Pipeline]
      operationId: dashboard_run_connector
      summary: Start a pipeline run from a connector data source.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '202': {description: LM Readiness job accepted; poll existing status and result endpoints.}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/quality-alerts:
    get:
      tags: [Automation]
      operationId: list_quality_alerts
      summary: list quality alerts
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Automation]
      operationId: create_quality_alert
      summary: create quality alert
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/quality-alerts/events:
    get:
      tags: [Automation]
      operationId: list_quality_alert_events
      summary: list quality alert events
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/quality-alerts/{rule_id}:
    delete:
      tags: [Automation]
      operationId: delete_quality_alert
      summary: delete quality alert
      parameters:
        - name: rule_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Automation]
      operationId: update_quality_alert
      summary: update quality alert
      parameters:
        - name: rule_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/result/{session_id}:
    get:
      tags: [Pipeline]
      operationId: api_v1_result
      summary: Get final results and file download URLs for a completed session.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/retraining:
    post:
      tags: [Inference & Retraining]
      operationId: retraining
      summary: >-
        Retraining: inference's replay, plus outlier removal and synthetic generation.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                config:
                  type: string
                  description: "JSON run configuration."
                outputPreferences:
                  type: string
                  description: >-
                    JSON object of output preferences. `output_format`
                    is one of: csv, parquet, xlsx, json, jsonl, ndjson, feather, orc.
                    An output that cannot be written in the chosen
                    format falls back to csv and the run reports it.
                quote_id:
                  type: string
                  description: >-
                    An exact quote from /api/v1/estimate with session_type
                    retraining; the run is charged exactly that price. 409 when the
                    file or settings no longer match the quote.
      responses:
        '200': {description: Success}
        '400': {description: "Run refused: error_code MISSING_TARGET_COLUMNS or UNSEEN_TARGET_CLASSES; not charged"}
        '409': {description: The confirmed quote no longer matches this file or these settings}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/scheduled-runs:
    get:
      tags: [Automation]
      operationId: v1_list_scheduled_runs_get
      summary: list scheduled runs
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Automation]
      operationId: v1_create_scheduled_run_post
      summary: create scheduled run
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/scheduled-runs/{run_id}:
    delete:
      tags: [Automation]
      operationId: v1_delete_scheduled_run_delete
      summary: delete scheduled run
      parameters:
        - name: run_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Automation]
      operationId: v1_update_scheduled_run_put
      summary: update scheduled run
      parameters:
        - name: run_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/scheduled-runs/{run_id}/run-now:
    post:
      tags: [Automation]
      operationId: v1_run_scheduled_now_post
      summary: Trigger a scheduled run immediately.
      parameters:
        - name: run_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/scheduled-runs/{run_id}/toggle:
    post:
      tags: [Automation]
      operationId: v1_toggle_scheduled_run_post
      summary: toggle scheduled run
      parameters:
        - name: run_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions:
    get:
      tags: [Sessions]
      operationId: v1_get_user_history_api_get
      summary: Get processing history for the current user (API endpoint)
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/sessions/{session_id}:
    get:
      tags: [Sessions]
      operationId: v1_get_session_details_api_get
      summary: Get full session details including all processing parameters (API endpoint)
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/config:
    get:
      tags: [Sessions]
      operationId: ux_session_config
      summary:  config view
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/decode:
    post:
      tags: [Sessions]
      operationId: decode_session_output
      summary: >-
        Revert a frame's encoded non-numeric columns to their original types.
      description: >-
        Decodes one of the session's output files (JSON body, `output`) or an
        uploaded file shaped like it (multipart, field `file`, e.g. a model's
        scored copy). An inference session decodes with its training session's
        encoders. The report rates every source column `exact`, `approximate`,
        `skipped` or `failed`; scaled numeric features stay scaled (listed under
        `scaled_numeric`) unless `unscale` is true. With `media`, image/audio
        columns come back as files through a job (202 + `status_url`).
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                output: {type: string, description: "A listed output file name, `dsg_output` (default) or `model_ready`."}
                stage: {type: string, enum: [raw, encoded, final], description: "Default: from the file name (anomaly-fixed = raw, DTC/MDH = encoded, else final)."}
                unscale: {type: boolean, default: false, description: Return CDS-scaled numeric features in original units.}
                restore_missing: {type: boolean, default: false}
                format: {type: string, default: csv}
                media: {type: string, enum: ['off', reconstruct, generate], default: 'off'}
                variations: {type: integer}
                media_rows: {type: integer}
          multipart/form-data:
            schema:
              type: object
              properties:
                file: {type: string, format: binary}
      responses:
        '200': {description: Decoded file and report}
        '202': {description: Media decode job queued; poll status_url}
        '400': {description: Bad option or unreadable file}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
        '409': {description: No saved encoders for this session or its training session}
        '413': {description: Over the row or size limit for on-demand decoding}
        '422': {description: The frame could not be decoded}
  /api/v1/sessions/{session_id}/decode/{job_id}:
    delete:
      tags: [Sessions]
      operationId: decode_session_job_cancel
      summary: Cancel a media decode job that has not finished.
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Sessions]
      operationId: decode_session_job_status
      summary: Progress of a media decode job, then its files (decoded table, report, media).
      parameters:
        - name: job_id
          in: path
          required: true
          schema: {type: string}
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/download-all:
    get:
      tags: [Sessions]
      operationId: ux_session_download_all
      summary:  download all view
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/files:
    get:
      tags: [Sessions]
      operationId: v1_list_session_files_get
      summary: List all downloadable files for a completed session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/meta:
    get:
      tags: [Sessions]
      operationId: ux_session_meta_get
      summary: Read the caller's tags and note for a session ({tags, note}).
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Sessions]
      operationId: ux_session_meta
      summary:  meta view
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/name:
    put:
      tags: [Sessions]
      operationId: v1_update_session_name_put
      summary: Update the name/alias of a session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/outputs:
    delete:
      tags: [Sessions]
      operationId: v1_clear_session_memory_outputs_delete
      summary: Clear all memory outputs for a session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Sessions]
      operationId: v1_get_memory_outputs_list_get
      summary: Get list of available memory outputs for a session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/outputs/{output_name}:
    get:
      tags: [Sessions]
      operationId: v1_download_memory_output_get
      summary: Download a specific memory output as CSV
      parameters:
        - name: output_name
          in: path
          required: true
          schema: {type: string}
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/preview:
    get:
      tags: [Sessions]
      operationId: preview_session_file
      summary: >-
        First rows of a run's input (``file=__input__``) or one of its outputs.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/report:
    get:
      tags: [Sessions]
      operationId: ux_session_report
      summary: ux session report
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/result:
    get:
      tags: [Sessions]
      operationId: view_session_result
      summary: >-
        A past run's result payload, read-only (no billing or webhook side effects).
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/retraining:
    put:
      tags: [Sessions]
      operationId: v1_update_session_retraining_put
      summary: Toggle the retraining_enabled flag for a session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/retry:
    post:
      tags: [Sessions]
      operationId: retry_session
      summary: retry session
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sessions/{session_id}/write-output:
    post:
      tags: [Sessions]
      operationId: write_output_to_db
      summary: >-
        Write a completed session's output to a connector target.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sftp/credentials:
    get:
      tags: [Utilities]
      operationId: list_sftp_credentials
      summary: list sftp credentials
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Utilities]
      operationId: create_sftp_credential
      summary: create sftp credential
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/sftp/credentials/{cred_id}:
    delete:
      tags: [Utilities]
      operationId: delete_sftp_credential
      summary: delete sftp credential
      parameters:
        - name: cred_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sftp/credentials/{cred_id}/pipeline:
    put:
      tags: [Utilities]
      operationId: update_sftp_pipeline
      summary: >-
        Update pipeline config (y_columns, pipeline_config) for an SFTP credential's linked listener.
      parameters:
        - name: cred_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sftp/info:
    get:
      tags: [Utilities]
      operationId: sftp_info
      summary: Return SFTP connection details to a signed-in user.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/shared-sessions:
    get:
      tags: [Sharing]
      operationId: v1_list_shared_sessions_get
      summary: List sessions this user has shared outbound.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Sharing]
      operationId: v1_create_shared_session_post
      summary: Share a session with another user or generate a public link.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/shared-sessions/access/{token}:
    get:
      tags: [Sharing]
      operationId: access_shared_session
      summary: Public endpoint — access a shared session via its share_token (no login required).
      security: []
      parameters:
        - name: token
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/access/{token}/download/{filename}:
    get:
      tags: [Sharing]
      operationId: download_shared_session_file
      summary: Public endpoint — download one owner-selected file from a share token.
      security: []
      parameters:
        - name: filename
          in: path
          required: true
          schema: {type: string}
        - name: token
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/access/{token}/join:
    post:
      tags: [Sharing]
      operationId: join_shared_session_link
      summary: >-
        Attach a public link's grant to the signed-in caller's account.
      parameters:
        - name: token
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/access/{token}/preview:
    get:
      tags: [Sharing]
      operationId: preview_shared_session_file
      summary: >-
        Public endpoint — first rows of one owner-selected file (``file``, ``rows``).
      parameters:
        - name: token
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/by-session/{session_id}/comments:
    get:
      tags: [Sharing]
      operationId: shared_session_comments
      summary: >-
        Comment thread on a session: owner + every live share holder read it, 'comment' and 'edit' holders (and the owner) post to it.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    post:
      tags: [Sharing]
      operationId: shared_session_comments
      summary: >-
        Comment thread on a session: owner + every live share holder read it, 'comment' and 'edit' holders (and the owner) post to it.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/by-session/{session_id}/comments/{comment_id}:
    delete:
      tags: [Sharing]
      operationId: delete_shared_session_comment
      summary: delete shared session comment
      parameters:
        - name: comment_id
          in: path
          required: true
          schema: {type: string}
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/shared-sessions/received:
    get:
      tags: [Sharing]
      operationId: v1_list_received_shared_sessions_get
      summary: List sessions shared with this user.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/shared-sessions/{share_id}:
    delete:
      tags: [Sharing]
      operationId: v1_delete_shared_session_delete
      summary: delete shared session
      parameters:
        - name: share_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Sharing]
      operationId: update_shared_session
      summary: >-
        Owner edits an existing share's permission / expiry / files / note.
      parameters:
        - name: share_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/spark/read:
    post:
      tags: [Utilities]
      operationId: spark_read_file
      summary: Read a large file via Spark and return stats + sample rows.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/spark/status:
    get:
      tags: [Utilities]
      operationId: spark_status
      summary: Check Spark availability and session info.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/spark/transform:
    post:
      tags: [Utilities]
      operationId: spark_transform
      summary: Apply Spark transformations to a large file and save result.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/status/{session_id}:
    get:
      tags: [Pipeline]
      operationId: api_v1_status
      summary: Get processing progress for a session.
      parameters:
        - name: session_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/streams:
    get:
      tags: [Streaming]
      operationId: list_streams
      summary: list streams
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Streaming]
      operationId: create_stream
      summary: create stream
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/streams/preview:
    post:
      tags: [Streaming]
      operationId: stream_preview
      summary: >-
        Dry-run: sample the source, replay it in memory, show input and output.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/streams/test-connection:
    post:
      tags: [Streaming]
      operationId: stream_test_connection
      summary: stream test connection
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/streams/{stream_id}:
    delete:
      tags: [Streaming]
      operationId: delete_stream
      summary: delete stream
      parameters:
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Streaming]
      operationId: get_stream
      summary: get stream
      parameters:
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Streaming]
      operationId: update_stream
      summary: update stream
      parameters:
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/streams/{stream_id}/schema:
    get:
      tags: [Streaming]
      operationId: stream_schema
      summary: >-
        Column order of the positional output formats ('values', 'sparse').
      parameters:
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/streams/{stream_id}/status:
    get:
      tags: [Streaming]
      operationId: stream_status
      summary: stream status
      parameters:
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/streams/{stream_id}/{action}:
    post:
      tags: [Streaming]
      operationId: stream_action
      summary: stream action
      parameters:
        - name: action
          in: path
          required: true
          schema: {type: string}
        - name: stream_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/sync/watermarks:
    delete:
      tags: [Connectors]
      operationId: v1_delete_sync_watermark_delete
      summary: delete sync watermark
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    get:
      tags: [Connectors]
      operationId: v1_get_sync_watermark_get
      summary: get sync watermark
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Connectors]
      operationId: v1_create_sync_watermark_post
      summary: Create a manual watermark — useful for setting initial sync points.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    put:
      tags: [Connectors]
      operationId: v1_upsert_sync_watermark_put
      summary: upsert sync watermark
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/sync/watermarks/list:
    get:
      tags: [Connectors]
      operationId: list_sync_watermarks
      summary: List all watermarks for the current user.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/sync/watermarks/{watermark_id}/reset:
    post:
      tags: [Connectors]
      operationId: reset_sync_watermark_by_id
      summary: Reset a watermark by ID — clears watermark_value to force full re-read.
      parameters:
        - name: watermark_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/triggers:
    get:
      tags: [Automation]
      operationId: list_triggers
      summary: >-
        List the caller's triggers (webhook_secret never included).
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Automation]
      operationId: create_trigger
      summary: >-
        Create a trigger. For inbound_webhook, a webhook_secret is generated and returned ONCE in this response (never in subsequent GETs).
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/triggers/{trigger_id}:
    delete:
      tags: [Automation]
      operationId: delete_trigger
      summary: delete trigger
      parameters:
        - name: trigger_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Automation]
      operationId: get_trigger
      summary: get trigger
      parameters:
        - name: trigger_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Automation]
      operationId: update_trigger
      summary: >-
        Update name / enabled / config / target. webhook_secret is immutable and never returned here.
      parameters:
        - name: trigger_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/triggers/{trigger_id}/test:
    post:
      tags: [Automation]
      operationId: test_trigger
      summary: >-
        Dry-run: validate the trigger's config + target without firing the target pipeline. Reports what WOULD happen. Actual firing is Part 2/3.
      parameters:
        - name: trigger_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/usage:
    get:
      tags: [Account]
      operationId: api_v1_usage
      summary: Get credit usage stats for the current API key.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/users/search:
    get:
      tags: [Sharing]
      operationId: v1_search_users_get
      summary: Find a share recipient — never a directory search.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/validate:
    post:
      tags: [Pipeline]
      operationId: v1_validate_csv_post
      summary: validate csv
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: "Data file. Accepted: .csv, .feather, .json, .jsonl, .ndjson, .orc, .parquet, .xls, .xlsx"
                config:
                  type: string
                  description: "JSON run configuration."
                outputPreferences:
                  type: string
                  description: >-
                    JSON object of output preferences. `output_format`
                    is one of: csv, parquet, xlsx, json, jsonl, ndjson, feather, orc.
                    An output that cannot be written in the chosen
                    format falls back to csv and the run reports it.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/webhooks:
    get:
      tags: [Automation]
      operationId: v1_list_webhooks_get
      summary: List all webhooks for the current user.
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
    post:
      tags: [Automation]
      operationId: v1_create_webhook_post
      summary: Register a new webhook — persisted to DB, scoped to current user.
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
  /api/v1/webhooks/{webhook_id}:
    delete:
      tags: [Automation]
      operationId: v1_delete_webhook_delete
      summary: Delete a webhook (user-scoped). Delivery logs cascade-deleted.
      parameters:
        - name: webhook_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    get:
      tags: [Automation]
      operationId: v1_get_webhook_get
      summary: Get details of a specific webhook (user-scoped).
      parameters:
        - name: webhook_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
    put:
      tags: [Automation]
      operationId: v1_update_webhook_put
      summary: Update an existing webhook (user-scoped).
      parameters:
        - name: webhook_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/webhooks/{webhook_id}/deliveries:
    get:
      tags: [Automation]
      operationId: v1_list_webhook_deliveries_get
      summary: list webhook deliveries
      parameters:
        - name: webhook_id
          in: path
          required: true
          schema: {type: string}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/webhooks/{webhook_id}/test:
    post:
      tags: [Automation]
      operationId: v1_test_webhook_post
      summary: Test a webhook by sending a test notification (user-scoped).
      parameters:
        - name: webhook_id
          in: path
          required: true
          schema: {type: string}
      requestBody:
        content:
          application/json:
            schema: {type: object}
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
        '404': {$ref: '#/components/responses/NotFound'}
  /api/v1/workers/status:
    get:
      tags: [Utilities]
      operationId: get_worker_fleet_status
      summary: get worker fleet status
      responses:
        '200': {description: Success}
        '401': {$ref: '#/components/responses/Unauthorized'}
        '403': {$ref: '#/components/responses/Forbidden'}
components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: API key issued from the dashboard (prefix `dtpk_`).
  schemas:
    Error:
      type: object
      properties:
        error: {type: string}
  responses:
    Unauthorized:
      description: Missing or invalid credentials
      content:
        application/json:
          schema: {$ref: '#/components/schemas/Error'}
    Forbidden:
      description: Authenticated, but the resource belongs to someone else
      content:
        application/json:
          schema: {$ref: '#/components/schemas/Error'}
    NotFound:
      description: No such resource for this account
      content:
        application/json:
          schema: {$ref: '#/components/schemas/Error'}
