# Proposed contract, version 1: endpoints, errors, paging, idempotency, security and the capability of every
# operation. Resource schemas were initialized from the data model (docs/06-data) and are kept aligned with it; input
# schemas (*Input, *Request) and views are specific to this contract. Status: proposal for review, not confirmed design.
# Conventions: docs/05-interfaces/choosing-an-interface.md. Vendor extensions: x-moonitoring-audience (who calls),
# x-moonitoring-capability (the capability checked), x-moonitoring-entitlement (the entitlement feature checked),
# x-moonitoring-requirements (the requirements of 1.requisiti-raffinati.txt the operation serves).
openapi: 3.1.0
info:
  title: Farm Observations API
  version: 1.0.0
  description: Measured and computed values about animals, groups and farm products, with the catalogs that give
    them meaning (types, methods, contexts, body sites), the sessions and samples that group them, the selections
    among proved duplicates and the derivations of computed values. Readers see the current revision or the data
    as it was at a write number. Model predictions are requested here and recorded as computed observations.
servers:
- url: https://farm.moonitoring.com/observations/v1
  description: Prod
- url: https://stage-farm.moonitoring.com/observations/v1
  description: Stage, through IAP
security:
- bearer: []
tags:
- name: Observations
  description: Canonical observations
- name: Sessions
  description: Milkings, weighings, samplings
- name: Samples
  description: Physical specimens and product lots
- name: Predictions
  description: Model outputs for an Organization
- name: Catalogs
  description: Types, methods, contexts, body sites
paths:
  /organizations/{organization_id}/observations:
    get:
      summary: List observations
      operationId: listObservations
      description: Current revisions of the Organization's observations, or the revisions available at `as_of_seq`.
        Each record is authorized against its time and the caller's ownership or management episode.
      tags:
      - Observations
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this animal.
      - name: animal_group
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this group.
      - name: product_material
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this product lot.
      - name: observation_type
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this type.
      - name: session
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this session.
      - name: sample
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this sample.
      - name: origin
        in: query
        required: false
        schema:
          type: string
          enum:
          - sensor
          - operator
          - lab
          - computed
          - unknown
        description: Only values of this kind of origin.
      - name: include_cancelled
        in: query
        required: false
        schema:
          type: boolean
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/CanonicalObservation'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '27'
      - 27.*.1
      - 27.*.2
      - 27.*.3
      - '1002.11'
      - '1006.23'
    post:
      summary: Record an observation
      operationId: recordObservation
      tags:
      - Observations
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ObservationEntry'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CanonicalObservation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: organization
      x-moonitoring-capability: farm.animal_records.edit_own
      x-moonitoring-requirements:
      - '27'
      - 32.*.4
      - 19.*.2
      - '1002.20'
  /observations/{observation_id}:
    get:
      summary: Read an observation
      operationId: getObservation
      tags:
      - Observations
      parameters:
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CanonicalObservation'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '27'
  /observations/{observation_id}/revisions:
    get:
      summary: List an observation's revisions
      operationId: listObservationRevisions
      tags:
      - Observations
      parameters:
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/CanonicalObservation'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '27.14'
      - '1019'
  /observations/{observation_id}/lineage:
    get:
      summary: Read an observation's lineage
      operationId: getObservationLineage
      tags:
      - Observations
      parameters:
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationLineage'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '27.10'
      - '27.11'
      - '27.12'
      - '27.13'
      - '17'
      - '30'
      - '61'
  /observations/{observation_id}/selection:
    get:
      summary: Read the duplicate selection
      operationId: getObservationSelection
      description: The selection among proved copies of the same measurement this observation belongs to, when a
        farm reaches us through two channels.
      tags:
      - Observations
      parameters:
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationSelection'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '56'
  /observations/{observation_id}/correct:
    post:
      summary: Correct an observation
      operationId: correctObservation
      description: Only records that entered through the Organization's own feeds; data from labs, sensors, software
        and registries is corrected at the source.
      tags:
      - Observations
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CorrectionRequest'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CanonicalObservation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: organization
      x-moonitoring-capability: farm.animal_records.edit_own
      x-moonitoring-requirements:
      - '27.14'
      - '1002.20'
      - '61.3'
  /observations/{observation_id}/cancel:
    post:
      summary: Cancel an observation
      operationId: cancelObservation
      tags:
      - Observations
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: observation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancellationRequest'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CanonicalObservation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: organization
      x-moonitoring-capability: farm.animal_records.edit_own
      x-moonitoring-requirements:
      - '27.14'
      - '1002.20'
      - '61.3'
  /derivations/{derivation_id}:
    get:
      summary: Read a derivation
      operationId: getDerivation
      description: The transformation and the exact input revisions of a computed value.
      tags:
      - Observations
      parameters:
      - name: derivation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CanonicalDerivation'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '57'
  /organizations/{organization_id}/sessions:
    get:
      summary: List sessions
      operationId: listSessions
      tags:
      - Sessions
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this animal.
      - name: device
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this device.
      - name: session_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - milking
          - weighing
          - feeding
          - sampling
          - other
        description: Only this kind.
      - name: outcome
        in: query
        required: false
        schema:
          type: string
          enum:
          - success
          - refused
          - failed
          - incomplete
          - unknown
        description: Only this outcome.
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ObservationSession'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '38'
      - '1002.11'
  /sessions/{session_id}:
    get:
      summary: Read a session
      operationId: getSession
      tags:
      - Sessions
      parameters:
      - name: session_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationSession'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '38'
  /sessions/{session_id}/observations:
    get:
      summary: List a session's observations
      operationId: listSessionObservations
      tags:
      - Sessions
      parameters:
      - name: session_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/CanonicalObservation'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '38'
      - '27.8'
  /organizations/{organization_id}/samples:
    get:
      summary: List samples
      operationId: listSamples
      tags:
      - Samples
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this animal.
      - name: product_material
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this product lot.
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Sample'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '54'
      - '1002.11'
  /samples/{sample_id}:
    get:
      summary: Read a sample
      operationId: getSample
      tags:
      - Samples
      parameters:
      - name: sample_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Sample'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '54'
  /organizations/{organization_id}/product-materials:
    get:
      summary: List product lots
      operationId: listProductMaterials
      tags:
      - Samples
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: kind
        in: query
        required: false
        schema:
          type: string
          enum:
          - bulk_tank
          - shipment
          - pooled_sample
          - other_documented
          - unknown
        description: Only this kind of milk material.
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ProductMaterial'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '55'
      - 55.*.1
      - '1002.11'
  /product-materials/{material_id}:
    get:
      summary: Read a product lot
      operationId: getProductMaterial
      tags:
      - Samples
      parameters:
      - name: material_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductMaterial'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '55'
  /organizations/{organization_id}/models:
    get:
      summary: List the models an Organization may use
      operationId: listModels
      tags:
      - Predictions
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/AvailableModel'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: organization
      x-moonitoring-capability: farm.models.use
      x-moonitoring-requirements:
      - '1002.24'
      - '68'
      - '1006.25'
  /organizations/{organization_id}/predictions:
    post:
      summary: Request predictions
      operationId: requestPredictions
      description: 'Two gates: the caller''s role must hold `farm.models.use` and the Organization an active entitlement
        for the model''s feature.'
      tags:
      - Predictions
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PredictionRequest'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PredictionResult'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
        '429':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/TooManyRequests
      x-moonitoring-audience: organization
      x-moonitoring-capability: farm.models.use
      x-moonitoring-entitlement: farm.models.<model>
      x-moonitoring-requirements:
      - '1002.24'
      - '68'
      - '62'
      - 19.*.4
      - '57'
  /observation-types:
    get:
      summary: List observation types
      operationId: listObservationTypes
      tags:
      - Catalogs
      parameters:
      - name: profile_family
        in: query
        required: false
        schema:
          type: string
        description: Only this family, e.g. milk_scc.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - draft
          - active
          - retired
        description: Only this status.
      - name: applies_to
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only types for this species.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ObservationType'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '35'
      - '2000'
      - '2001'
    post:
      summary: Create an observation type version
      operationId: createObservationType
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ObservationTypeInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationType'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '35'
      - '35.14'
      - '35.19'
      - '1006.17'
  /observation-types/{type_id}:
    get:
      summary: Read an observation type
      operationId: getObservationType
      tags:
      - Catalogs
      parameters:
      - name: type_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationType'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '35'
  /observation-types/{type_id}/activate:
    post:
      summary: Activate an observation type
      operationId: activateObservationType
      description: Requires concrete constants, resolved units and closed schemas; published semantics are immutable
        from then on.
      tags:
      - Catalogs
      parameters:
      - name: type_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationType'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '35.19'
      - '1006.17'
  /observation-types/{type_id}/retire:
    post:
      summary: Retire an observation type
      operationId: retireObservationType
      description: Historical observations keep referring to it.
      tags:
      - Catalogs
      parameters:
      - name: type_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationType'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '35.19'
      - '1006.17'
  /observation-methods:
    get:
      summary: List observation methods
      operationId: listObservationMethods
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ObservationMethod'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '36'
    post:
      summary: Create an observation method version
      operationId: createObservationMethod
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ObservationMethodInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationMethod'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '36'
      - '1006.17'
  /observation-contexts:
    get:
      summary: List observation contexts
      operationId: listObservationContexts
      description: A small catalog readers keep in memory.
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ObservationContext'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '64'
    post:
      summary: Create an observation context
      operationId: createObservationContext
      description: 'Immutable: a different way of obtaining values is a new context.'
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ObservationContextInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObservationContext'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '64'
      - '1006.17'
  /body-sites:
    get:
      summary: List body sites
      operationId: listBodySites
      tags:
      - Catalogs
      parameters:
      - name: applies_to
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only sites of this species.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/BodySite'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '37'
    post:
      summary: Create a body site
      operationId: createBodySite
      tags:
      - Catalogs
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BodySiteInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BodySite'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: farm.reference_data.manage
      x-moonitoring-requirements:
      - '37'
      - '1006.17'
components:
  schemas:
    CanonicalObservation:
      description: 'One measured or computed value about an animal, a group or a product lot, in our standard form:
        what was observed (an observation type), when, how (an observation context), on which body site, and with
        which value. When a source corrects a value, a new revision is added instead of overwriting the old one.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        observation_type:
          type: string
          format: uuid
          description: ID of the ObservationType. Reference the exact registered profile version, never a family/template.
            Draft profiles are for design, not operational publication.
        body_site:
          type: string
          format: uuid
          description: ID of the BodySite. Empty does not assert whole udder/subject; see `anatomical_scope`.
        time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        value:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationValue
          description: Required for active numerical/category/flag results; absent only in a cancellation revision.
        session:
          type: string
          format: uuid
          description: ID of the ObservationSession. Only when the entire observation concerns that session; multiple
            contributing milkings belong to Sample.
        device:
          type: string
          format: uuid
          description: ID of the Device.
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity.
        raw_metadata:
          type: string
          format: uuid
          description: ID of the RawMetadata. Required unless derivation (`CanonicalObservation.derivation`) is
            set; see lineage.
        raw_locator:
          type: string
          description: Identifies the exact source record/field; detailed adapter inputs also live in its ParseJob
            audit.
        source_record_key:
          type: string
          description: Stable source record key; no export date, mutable value or lactation context in the key.
        status:
          type: string
          enum:
          - final
          - corrected
          - cancelled
          default: final
          description: A source correction/cancellation appends a revision; previous payloads and availability remain
            intact. Corrected may be exposed as a current-view projection, never by erasing the prior revision's
            status.
        recorded_at:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/EventTime
          description: When the source recorded or published this value (e.g. the date of the lab report, the time
            the robot stored the reading). Not our arrival time (`revision.available_in`). Empty when the source
            does not say; never filled with an assumed delay.
        coverage:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CoverageDetails
        source_feed:
          type: string
          format: uuid
          description: ID of the SourceFeed. Must match the producer's feed; stable across deliveries.
        content_hash:
          type: string
          description: Hash all semantic fields including subject, time, profile version, context, value and qualifiers;
            exclude delivery clocks.
        sample:
          type: string
          format: uuid
          description: ID of the Sample.
        property_qualifiers:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/PropertyQualifiers
          description: Typed fields allowed by `observation_type.qualifier_schema`; no unvalidated free JSON.
        anatomical_scope:
          type: string
          enum:
          - whole_subject
          - body_part
          - not_applicable
          - unknown
          description: '`body_part` requires `body_site`; other values have none. A known whole udder is a BodySite,
            not the whole animal.'
        aggregation_details:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/AggregationDetails
          description: Per-row part of an aggregate (e.g. how many readings it combined); its method is in the context.
        derivation:
          type: string
          format: uuid
          description: ID of the CanonicalDerivation.
        revision:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
        component_key:
          type: string
          description: Stable component of the source record, e.g. field/test/channel; distinguishes two assays
            or targets in the same record.
        context:
          type: string
          format: uuid
          description: 'ID of the ObservationContext. How the value was obtained: method, result basis, time basis,
            aggregation. Chosen by the parser mapping of the source field.'
        farm:
          type: string
          format: uuid
          description: ID of the Organization that is a Farm. The farm of the feed that delivered the record (=
            `source_feed.farm`), copied here as the key of partitioning, row-level access and erasure; it never
            changes on a revision. See STORAGE. For observations we compute, the farm of the inputs; a derivation
            never crosses farms.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        subject:
          type: string
          enum:
          - AnimalObservation
          - AnimalGroupObservation
          - ProductObservation
          description: Which kind of CanonicalObservation this is (enum, disjoint + complete).
      required:
      - id
      - observation_type
      - time
      - source_producer
      - source_record_key
      - status
      - source_feed
      - content_hash
      - property_qualifiers
      - anatomical_scope
      - revision
      - component_key
      - context
      - farm
      - created_at
      - updated_at
      - subject
    AnimalObservation:
      allOf:
      - $ref: '#/components/schemas/CanonicalObservation'
      - type: object
        properties:
          animal:
            type: string
            format: uuid
            description: ID of the Animal.
        required:
        - animal
      description: A CanonicalObservation whose subject is AnimalObservation.
    AnimalGroupObservation:
      allOf:
      - $ref: '#/components/schemas/CanonicalObservation'
      - type: object
        properties:
          animal_group:
            type: string
            format: uuid
            description: ID of the AnimalGroup.
        required:
        - animal_group
      description: A CanonicalObservation whose subject is AnimalGroupObservation.
    ProductObservation:
      allOf:
      - $ref: '#/components/schemas/CanonicalObservation'
      - type: object
        properties:
          product_material:
            type: string
            format: uuid
            description: ID of the ProductMaterial.
        required:
        - product_material
      description: A CanonicalObservation whose subject is ProductObservation.
    ObservationType:
      description: 'The versioned catalog entry that defines what an observation means: the property, material,
        result shape, canonical unit and validation. A new provider maps to an existing type whenever the meaning
        matches; the profile definitions live in the canonical type catalog.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        code:
          type: string
        name:
          type: string
        description:
          type: string
        value_type:
          type: string
          enum:
          - quantity
          - count
          - category
          - flag
        canonical_unit:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: One unit per published version; required for quantity/count, absent for category/flag. Prefer
            UCUM; non-UCUM assay scales require a separately versioned `moo.unit` definition, never invented UCUM
            symbols.
        categories:
          type: array
          items:
            type: string
          description: Required non-empty vocabulary for category, empty for other value types; milk detection profiles
            use detected/not_detected/inconclusive/invalid.
        valid_range:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/NumericBounds
          description: Hard mathematical/physical limits only, not normal clinical ranges; anomalies are flagged,
            not automatically deleted.
        comparability:
          type: string
          enum:
          - physical
          - method_specific
          - vendor_index
          description: Physical means a physical measurand, not guaranteed interchangeability across methods, matrices
            or bases. `vendor_index` only for a vendor scale whose definition is documented (scale, range, meaning);
            undocumented proprietary indices are not canonical (IngestionSkip reason `proprietary_index`).
        applies_to:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: ID of the AnimalType.
        allowed_body_sites:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the BodySite. Only applicable sites in this list are allowed; subject-specific constraints
            remain mandatory. Empty does not mean any site.
        allowed_subjects:
          type: array
          items:
            type: string
            enum:
            - animal
            - animal_group
            - product
          minItems: 1
        external_codes:
          type: array
          items:
            $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Crosswalks require matching semantics; an external metric code alone does not prove equivalent
            meaning.
        version:
          type: string
        profile_family:
          type: string
          description: Registered family, e.g. `milk_protein`, `milk_scc`, `milk_pathogen_test`; it selects the
            closed constants schema in the canonical type catalog. A family can define several concrete profiles;
            arbitrary strings do not create a new validated family.
        property_definition:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/PropertyDefinition
          description: 'Immutable typed constants: matrix, analyte/target, denominator, count basis or index definition,
            according to family.'
        qualifier_schema:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Selects a closed versioned PropertyQualifiers schema; empty schema allowed where no extra
            fields are needed.
        allowed_result_forms:
          type: array
          items:
            type: string
            enum:
            - point
            - interval
            - lower_bound
            - upper_bound
            - category
            - flag
          uniqueItems: true
          description: Non-empty subset of numeric forms for quantity/count; exactly {category} for category and
            {flag} for flag. Must match `value_type` and ObservationValue.result_form (ObservationValue); supplied
            by the profile, not guessed by the adapter.
        status:
          type: string
          enum:
          - draft
          - active
          - retired
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - code
      - name
      - description
      - value_type
      - comparability
      - applies_to
      - allowed_subjects
      - version
      - profile_family
      - property_definition
      - qualifier_schema
      - allowed_result_forms
      - status
      - created_at
      - updated_at
    ObservationMethod:
      description: A versioned analytical, measurement or computation protocol. It describes how a value was produced,
        not how it was transmitted or typed in.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        code:
          type: string
        name:
          type: string
        version:
          type: string
        definition:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
        family:
          type: string
          enum:
          - laboratory
          - sensor
          - direct_observation
          - computation
          - other_documented
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - code
      - name
      - version
      - definition
      - family
      - created_at
      - updated_at
    ObservationContext:
      description: 'How a value was obtained: method, result basis, time basis and aggregation. One context is shared
        by every observation produced the same way, so the same observation type can come from a lab test day, a
        robot milking or a daily sensor mean without multiplying codes.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        method:
          type: string
          format: uuid
          description: ID of the ObservationMethod. Protocol/version when known; manual transcription is not an
            analytical method.
        result_basis:
          type: string
          enum:
          - measurement
          - calibrated_estimate
          - aggregate
          - derived_value
          - derived_index
          - unknown
        time_basis:
          type: string
          enum:
          - sample_collection
          - phenomenon
          - test_day_reference
          - aggregation_window
          - unknown
          description: A test-day date is not automatically the physical sampling date.
        aggregation:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/AggregationEnum
          description: A measurement may cover a window with aggregation none; a mixed physical sample is not a
            statistical mean.
        aggregation_definition:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Custom formula/weights when known.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - result_basis
      - time_basis
      - aggregation
      - created_at
    BodySite:
      description: Catalog of the parts of a subject that a value can refer to, such as an udder quarter or a leg.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        code:
          type: string
          description: Unique. e.g. `udder_whole`, `udder_lf`, `udder_rf`, `udder_lr`, `udder_rr`, `leg_lf`, `leg_rf`,
            `leg_lr`, `leg_rr`.
        name:
          type: string
        applies_to:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: ID of the AnimalType.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - code
      - name
      - applies_to
      - created_at
      - updated_at
    ObservationSession:
      description: 'A bounded activity on a subject, optionally with a device: a milking, weighing, feeding or sampling.
        It groups the observations produced together and records whether the activity succeeded.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        session_type:
          type: string
          enum:
          - milking
          - weighing
          - feeding
          - sampling
          - other
          description: Sampling is the collection activity; Sample identifies the physical material and links its
            results.
        animal:
          type: string
          format: uuid
          description: ID of the Animal. Empty when the device could not identify the animal.
        device:
          type: string
          format: uuid
          description: ID of the Device.
        time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        outcome:
          type: string
          enum:
          - success
          - refused
          - failed
          - incomplete
          - unknown
          description: e.g. a robot refusal (too early) or a failed attachment.
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity.
        raw_metadata:
          type: string
          format: uuid
          description: ID of the RawMetadata. Required unless computed by us; see lineage.
        raw_locator:
          type: string
        source_record_key:
          type: string
          description: (`source_feed`, `source_record_key`) is the logical identity; uniqueness across history also
            includes revision number.
        source_feed:
          type: string
          format: uuid
          description: ID of the SourceFeed.
        content_hash:
          type: string
        status:
          type: string
          enum:
          - final
          - corrected
          - cancelled
          default: final
          description: Same rules as `CanonicalObservation.status`.
        revision:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
        product_material:
          type: string
          format: uuid
          description: 'ID of the ProductMaterial. For collective milk sampling: material rather than an individual
            animal. Unknown subject remains explicitly unresolved.'
        ordinal_in_day:
          type: integer
          description: Session number in the day, 1-based, when the source gives only a date; a source that counts
            from 0 (AfiMilk sessions 0, 1, 2) is shifted by the adapter.
        milk_destination:
          type: string
          enum:
          - tank
          - separated
          - calf_feed
          - discarded
          - unknown
          description: 'Only for `session_type` = milking: where the milk went. separated: kept apart from the tank
            (e.g. Lely M4Use, bucket); discarded: to the sewer. The quantity is the yield observation of the session.'
        milk_destination_reason:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: 'The source''s reason, with its code system (e.g. Lely LimMilkDestinationReasonType: MIS,
            MQC, Manual).'
        farm:
          type: string
          format: uuid
          description: ID of the Organization that is a Farm. The farm of the feed that delivered the record (=
            `source_feed.farm`), copied here as the key of partitioning, row-level access and erasure; it never
            changes on a revision. See STORAGE.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - session_type
      - time
      - outcome
      - source_producer
      - source_record_key
      - source_feed
      - content_hash
      - status
      - revision
      - farm
      - created_at
      - updated_at
    Sample:
      description: A physical specimen, such as a milk sample sent to a lab. It links several test results to the
        same material and records how and when it was collected.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity. The producer of the sample record itself; each result keeps
            its own producer on the observation.
        source_sample_reference:
          type: string
        matrix:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
        collected_time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        collection_kind:
          type: string
          enum:
          - single_collection
          - composite_collection
          - unknown
        animal:
          type: string
          format: uuid
          description: ID of the Animal.
        product_material:
          type: string
          format: uuid
          description: ID of the ProductMaterial.
        collection_session:
          type: string
          format: uuid
          description: ID of the ObservationSession.
        contributing_sessions:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the ObservationSession.
        body_site:
          type: string
          format: uuid
          description: ID of the BodySite.
        revision:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
        status:
          type: string
          enum:
          - active
          - cancelled
          default: active
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - source_producer
      - matrix
      - collected_time
      - collection_kind
      - revision
      - status
      - created_at
      - updated_at
    ProductMaterial:
      description: A physical lot of farm product, such as bulk-tank milk. It is the subject of product observations
        and samples when a value describes mixed product rather than one animal.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        organization:
          type: string
          format: uuid
          description: ID of the Organization.
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity. The producer of the material record itself; each result keeps
            its own producer on the observation.
        source_material_reference:
          type: string
        represented_time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        revision:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
        status:
          type: string
          enum:
          - active
          - cancelled
          default: active
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        product:
          type: string
          enum:
          - MilkMaterial
          - EggLot
          description: Which kind of ProductMaterial this is (enum, disjoint).
      required:
      - id
      - source_producer
      - represented_time
      - revision
      - status
      - created_at
      - updated_at
    MilkMaterial:
      allOf:
      - $ref: '#/components/schemas/ProductMaterial'
      - type: object
        properties:
          kind:
            type: string
            enum:
            - bulk_tank
            - shipment
            - pooled_sample
            - other_documented
            - unknown
        required:
        - kind
      description: A ProductMaterial whose product is MilkMaterial.
    EggLot:
      allOf:
      - $ref: '#/components/schemas/ProductMaterial'
      - type: object
        properties:
          batch:
            type: string
            format: uuid
            description: ID of the AnimalGroup that is a Batch. The flock that laid it, when known.
      description: Future work. A ProductMaterial whose product is EggLot.
    ObservationSelection:
      description: Chooses one preferred copy among observations that are proved to be copies of the same original
        measurement, for example a reading received both directly and through the management software. The source
        evidence is never changed.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        candidates:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: ID of the CanonicalObservation.
        preferred:
          type: string
          format: uuid
          description: ID of the CanonicalObservation.
        status:
          type: string
          enum:
          - selected
          - disputed
          - unresolved
          - cancelled
        identity_basis:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Versioned matching rule plus common upstream/sample/session evidence in the decision audit.
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        revision:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
        issues:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the DataIssue.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - candidates
      - status
      - identity_basis
      - rule_set
      - revision
      - created_at
    CanonicalDerivation:
      description: 'Records how we computed a value from other values: the calculation, its parameters and the exact
        versions of its inputs. It lets computed observations and periods be computed again identically.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        transformation:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
        inputs:
          type: array
          items:
            $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordReference
          minItems: 1
        parameters:
          description: A value typed by object of transformation definition.
        computed_at:
          type: string
          format: date-time
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity.
      required:
      - id
      - transformation
      - inputs
      - parameters
      - computed_at
      - source_producer
    ObservationLineage:
      type: object
      description: From a canonical record back to its raw data, its source and the write that made it available,
        with stored references only.
      properties:
        raw_metadata:
          type: string
          format: uuid
          description: ID of the RawMetadata (Files API).
        raw_locator:
          type: string
        source_record_key:
          type: string
        source_producer:
          type: string
          format: uuid
          description: ID of the SourceProducerEntity (Sources API, lineage).
        source_feed:
          type: string
          format: uuid
        device:
          type: string
          format: uuid
        available_in:
          type: integer
          description: The write number (WriteCommit.seq) of this revision.
        replaced_in:
          type: integer
        write_commit:
          type: object
          additionalProperties: true
          description: The WriteCommit, as in the Versioning API.
        derivation:
          type: string
          format: uuid
          description: ID of the CanonicalDerivation, for records we compute.
      required:
      - source_producer
      - source_feed
      - available_in
    ObservationEntry:
      type: object
      description: An observation typed in the app, for example a manual weight. It is stored as a raw file of the
        Organization's MoonitoringAppChannel feed and parsed into a CanonicalObservation with an operator origin;
        the response is the published revision.
      properties:
        animal:
          type: string
          format: uuid
        animal_group:
          type: string
          format: uuid
        product_material:
          type: string
          format: uuid
        observation_type:
          type: string
          format: uuid
        time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        value:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationValue
        body_site:
          type: string
          format: uuid
        anatomical_scope:
          type: string
          enum:
          - whole_subject
          - body_part
          - not_applicable
          - unknown
          description: '`body_part` requires `body_site`; other values have none. A known whole udder is a BodySite,
            not the whole animal.'
        context:
          type: string
          format: uuid
          description: ID of the ObservationContext; default the app's manual-entry context.
        property_qualifiers:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/PropertyQualifiers
        note:
          type: string
      required:
      - observation_type
      - time
      - value
    CorrectionRequest:
      type: object
      description: Appends a corrected revision to a record that entered through the Organization's own feeds. The
        previous revision stays.
      properties:
        value:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationValue
        time:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationTime
        reason:
          type: string
      required:
      - reason
    CancellationRequest:
      type: object
      description: Appends a cancellation revision.
      properties:
        reason:
          type: string
      required:
      - reason
    PredictionRequest:
      type: object
      description: Asks a model for predictions about animals of the Organization. `farm` calls the model API of
        `ai-model-platform`, records a ModelRun and stores each prediction as a computed observation or event with the
        model as origin.
      properties:
        model:
          type: string
          description: The model's name, as listed by `listModels`, e.g. mastitis-risk.
        animals:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          maxItems: 500
        as_of_seq:
          type: integer
          description: Read the inputs at this write number; default the watermark.
      required:
      - model
      - animals
    PredictionResult:
      type: object
      description: The predictions, with the run that produced them.
      properties:
        model_run:
          type: string
          format: uuid
        predictions:
          type: array
          items:
            type: object
            properties:
              animal:
                type: string
                format: uuid
              observation:
                type: string
                format: uuid
                description: ID of the CanonicalObservation written, when the output is a value.
              event:
                type: string
                format: uuid
                description: ID of the CanonicalEvent written, when the output is an alert.
              value:
                $ref: ../../../../common/v1/schemas.yaml#/components/schemas/ObservationValue
            required:
            - animal
      required:
      - model_run
      - predictions
    AvailableModel:
      type: object
      description: 'A model the Organization may use: its name, what it predicts and the entitlement feature it
        needs.'
      properties:
        name:
          type: string
        description:
          type: string
        feature:
          type: string
          description: e.g. farm.models.mastitis.
        entitled:
          type: boolean
          description: Whether the Organization holds the feature now.
        output_type:
          type: string
          format: uuid
          description: The ObservationType or event type it writes.
      required:
      - name
      - feature
      - entitled
    ObservationTypeInput:
      type: object
      description: A new profile version. It is created as draft and activated once constants, units and schemas
        are resolved.
      properties:
        code:
          type: string
        name:
          type: string
        description:
          type: string
        value_type:
          type: string
          enum:
          - quantity
          - count
          - category
          - flag
        canonical_unit:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: One unit per published version; required for quantity/count, absent for category/flag. Prefer
            UCUM; non-UCUM assay scales require a separately versioned `moo.unit` definition, never invented UCUM
            symbols.
        categories:
          type: array
          items:
            type: string
          description: Required non-empty vocabulary for category, empty for other value types; milk detection profiles
            use detected/not_detected/inconclusive/invalid.
        valid_range:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/NumericBounds
          description: Hard mathematical/physical limits only, not normal clinical ranges; anomalies are flagged,
            not automatically deleted.
        comparability:
          type: string
          enum:
          - physical
          - method_specific
          - vendor_index
          description: Physical means a physical measurand, not guaranteed interchangeability across methods, matrices
            or bases. `vendor_index` only for a vendor scale whose definition is documented (scale, range, meaning);
            undocumented proprietary indices are not canonical (IngestionSkip reason `proprietary_index`).
        applies_to:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: ID of the AnimalType.
        allowed_body_sites:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the BodySite. Only applicable sites in this list are allowed; subject-specific constraints
            remain mandatory. Empty does not mean any site.
        allowed_subjects:
          type: array
          items:
            type: string
            enum:
            - animal
            - animal_group
            - product
          minItems: 1
        external_codes:
          type: array
          items:
            $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Crosswalks require matching semantics; an external metric code alone does not prove equivalent
            meaning.
        version:
          type: string
        profile_family:
          type: string
          description: Registered family, e.g. `milk_protein`, `milk_scc`, `milk_pathogen_test`; it selects the
            closed constants schema in the canonical type catalog. A family can define several concrete profiles;
            arbitrary strings do not create a new validated family.
        property_definition:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/PropertyDefinition
          description: 'Immutable typed constants: matrix, analyte/target, denominator, count basis or index definition,
            according to family.'
        qualifier_schema:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Selects a closed versioned PropertyQualifiers schema; empty schema allowed where no extra
            fields are needed.
        allowed_result_forms:
          type: array
          items:
            type: string
            enum:
            - point
            - interval
            - lower_bound
            - upper_bound
            - category
            - flag
          uniqueItems: true
          description: Non-empty subset of numeric forms for quantity/count; exactly {category} for category and
            {flag} for flag. Must match `value_type` and ObservationValue.result_form (ObservationValue); supplied
            by the profile, not guessed by the adapter.
      required:
      - code
      - name
      - description
      - value_type
      - comparability
      - applies_to
      - allowed_subjects
      - version
      - profile_family
      - property_definition
      - qualifier_schema
      - allowed_result_forms
      additionalProperties: false
    ObservationMethodInput:
      type: object
      description: Input to create or change a ObservationMethod; server-managed fields are left out.
      properties:
        code:
          type: string
        name:
          type: string
        version:
          type: string
        definition:
          $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
        family:
          type: string
          enum:
          - laboratory
          - sensor
          - direct_observation
          - computation
          - other_documented
      required:
      - code
      - name
      - version
      - definition
      - family
      additionalProperties: false
    ObservationContextInput:
      type: object
      description: Input to create or change a ObservationContext; server-managed fields are left out.
      properties:
        method:
          type: string
          format: uuid
          description: ID of the ObservationMethod. Protocol/version when known; manual transcription is not an
            analytical method.
        result_basis:
          type: string
          enum:
          - measurement
          - calibrated_estimate
          - aggregate
          - derived_value
          - derived_index
          - unknown
        time_basis:
          type: string
          enum:
          - sample_collection
          - phenomenon
          - test_day_reference
          - aggregation_window
          - unknown
          description: A test-day date is not automatically the physical sampling date.
        aggregation:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/AggregationEnum
          description: A measurement may cover a window with aggregation none; a mixed physical sample is not a
            statistical mean.
        aggregation_definition:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/CodedValue
          description: Custom formula/weights when known.
      required:
      - result_basis
      - time_basis
      - aggregation
      additionalProperties: false
    BodySiteInput:
      type: object
      description: Input to create or change a BodySite; server-managed fields are left out.
      properties:
        code:
          type: string
          description: Unique. e.g. `udder_whole`, `udder_lf`, `udder_rf`, `udder_lr`, `udder_rr`, `leg_lf`, `leg_rf`,
            `leg_lr`, `leg_rr`.
        name:
          type: string
        applies_to:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: ID of the AnimalType.
      required:
      - code
      - name
      - applies_to
      additionalProperties: false
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The short-lived token signed by `access`: an Organization user token, a staff token or a client
        token, as the operation''s audience says.'
