openapi: 3.1.0
info:
  title: Cadenza Embedding API - Direct HTTP Endpoints
  summary: 'Direct HTTP access to disy Cadenza embedding targets for data export, object information, and spatial operations.'

  description: |
    This API provides direct HTTP endpoints to invoke a subset of the disy Cadenza Embedding API functionality without requiring the Cadenza JS client library.

    The use of this API is only intended for edge case scenarios, such as access from backend services, or simple `<iframe>` embeddings in non-JavaScript environments.
    For all other use cases, we generally recommend using the Cadenza Embedding API through the [Cadenza JS client library](https://disyinformationssysteme.github.io/cadenza.js/) for rich, interactive integration.

    For more than structural information, please use the Cadenza JS client documentation, which also uses these endpoints internally.

servers:
  - url: https://{hostname}/{base}/w
    variables:
      hostname:
        default: 'localhost:8000'

paths:
  /{embeddingTargetId}?dataType=json:
    get:
      operationId: fetchDataAsJson
      summary: Fetch table view or indicator view as json file
      description: |
        For further information see cadenza.js documentation for fetch data.

      x-codeSamples:
        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=json" 
                    download>Download JSON Data</a>
        - lang: 'HTML'
          label: 'Download Link with Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=json" 
                    download="my_file.json">Download JSON Data</a>

      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/parts'
        - $ref: '#/components/parameters/file_name'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Table'

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embeddingTargetId}?dataType=csv:
    get:
      operationId: fetchDataAsCsv
      summary: Fetch table view or indicator view as csv file
      description: |
        For further information see cadenza.js documentation for fetch data.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/parts'
        - $ref: '#/components/parameters/file_name'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      x-codeSamples:
        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=csv" 
                    download>Download CSV Data</a>
        - lang: 'HTML'
          label: 'Download Link with Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=csv" 
                    download="my_file.csv">Download CSV Data</a>
      responses:
        '200':
          description: successful operation
          content:
            text/csv:
              schema:
                type: string

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embeddingTargetId}?dataType=excel:
    get:
      operationId: fetchDataAsExcel
      summary: Fetch table view or indicator view as excel file
      description: |
        For further information see cadenza.js documentation for fetch data.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/parts'
        - $ref: '#/components/parameters/file_name'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      x-codeSamples:
        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=excel" 
                    download>Download XLSX Data</a>
        - lang: 'HTML'
          label: 'Download Link with Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=excel" 
                    download="my_file.xlsx">Download XLSX Data</a>

      responses:
        '200':
          description: successful operation
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embeddingTargetId}?dataType=ods:
    get:
      operationId: fetchDataAsOds
      summary: Fetch table view or indicator view as OpenDocument spreadsheet file
      description: |
        For further information see cadenza.js documentation for fetch data.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/parts'
        - $ref: '#/components/parameters/file_name'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      x-codeSamples:
        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=ods" 
                    download>Download ODS Data</a>
        - lang: 'HTML'
          label: 'Download Link With Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=ods" 
                    download="my_file.ods">Download ODS Data</a>

      responses:
        '200':
          description: successful operation
          content:
            application/vnd.oasis.opendocument.spreadsheet:
              schema:
                type: string
                format: binary

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embeddingTargetId}?dataType=pdf:
    get:
      operationId: fetchReport
      summary: Create report from report embedding target or JasperReport view
      description: |
        For further information see cadenza.js documentation for fetch data.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/file_name'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      x-codeSamples:
        - lang: 'HTML'
          label: 'Iframe Embedding'
          source: |
            <iframe src="https://{url}/{embeddingTargetId}?dataType=pdf" 
                    width="800" height="600"></iframe>
        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=pdf" 
                    download>Download PDF Report</a>
        - lang: 'HTML'
          label: 'Download Link With Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=pdf" 
                    download="my_file.pdf">Download PDF Report</a>

      responses:
        '200':
          description: successful operation
          content:
            application/pdf:
              schema:
                type: string
                format: binary

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embeddingTargetId}?dataType=png:
    get:
      operationId: fetchDataAsImage
      summary: Fetch map view as image
      description: |
        For further information see cadenza.js documentation for fetching a workbook map view as image.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/width'
        - $ref: '#/components/parameters/height'
        - $ref: '#/components/parameters/withScale'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      x-codeSamples:
        - lang: 'HTML'
          label: 'Image Embedding'
          source: |
            <img src="https://{url}/{embeddingTargetId}?dataType=png&width=800&height=800"
                    width="800" height="800" alt="Embedded Image">

        - lang: 'HTML'
          label: 'Download Link'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=png&width=800&height=800" 
                    download>Download PNG Map Image</a>
        - lang: 'HTML'
          label: 'Download Link With Custom Filename'
          source: |
            <a href="https://{url}/{embeddingTargetId}?dataType=png&width=800&height=800" 
                    download="my_file.png">Download PNG Image</a>

      responses:
        '200':
          description: successful operation
          content:
            image/png:
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embedding-target-id}/area-intersections:
    post:
      operationId: getAreaIntersection
      summary: Query intersecting geometries with area or length
      description: |
        For further information see cadenza.js documentation for fetching area intersections.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AreaIntersectionRequest'

      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AreaIntersectionsResult'

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /{embedding-target-id}/objectinfo:
    post:
      operationId: getObjectInfo
      summary: Query object information for given ids
      description: |
        For further information see cadenza.js documentation for fetching area intersections.
      parameters:
        - $ref: '#/components/parameters/embedded_target_id'
        - $ref: '#/components/parameters/filter'
        - $ref: '#/components/parameters/spatial_filter'

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ObjectInfoRequest'

      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FeatureCollection'

        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

components:

  parameters:

    embedded_target_id:
      in: path
      name: embeddingTargetId
      schema:
        type: string
      required: true

    file_name:
      in: query
      name: fileName
      schema:
        type: string
      required: false

    parts:
      in: query
      name: parts
      schema:
        type: array
        items:
          type: string
          enum: ['columns','values','totals']
        default: columns,values,totals
      required: false

    withScale:
      in: query
      name: withScale
      schema:
        type: boolean
        default: false
      required: false

    width:
      in: query
      name: width
      schema:
        type: integer
      required: true

    height:
      in: query
      name: height
      schema:
        type: integer
      required: true

    filter:
      in: query
      name: filter.{variableName}
      schema:
        oneOf:
          - type: string
          - type: number
          - type: integer
      required: false

    spatial_filter:
      in: query
      name: filter.$spatial
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SpatialFilter'
      required: false

  responses:
    BadRequest:
      description: |
        Bad Request

        The request is malformed in a way that does not fit into one of the other client-side error categories.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'

    Unauthorized:
      description: |
        Unauthorized
        * Authentication failed
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'

    Forbidden:
      description: |
        Forbidden

        The authenticated client does not have the necessary privileges to perform an operation on a resource.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'

    NotFound:
      description: |
        Not Found
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'

    InternalServerError:
      description: |
        Internal Server Error
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'

  schemas:
    ProblemDetails:
      type: object
      externalDocs:
        description: IETF RFC 9457 Problem Details for HTTP APIs
        url: https://datatracker.ietf.org/doc/rfc9457/
      properties:
        type:
          type: string
          format: uri
          description: |
            The primary identifier for the experienced problem type.
            As it is meant as an identifier, it is typically not navigable.
        httpStatus:
          type: string
          description: |
            Unique http state identifier name
        key:
          type: string
          description: |
            Unique error identifier name
        title:
          type: string
          description: |
            A short, human-readable summary of the problem type.
            For a given type, the title may only vary for localization.
      required:
        - type
        - title

    ObjectId:
      type: array
      items:
        anyOf:
          - type: string
          - type: integer

    ObjectIds:
      type: array
      items:
        $ref: '#/components/schemas/ObjectId'

    Coordinate:
      type: array
      items:
        type: number
        minItems: 2
        maxItems: 4

    Coordinates:
      type: array
      items:
        $ref: '#/components/schemas/Coordinate'

    Rings:
      type: array
      items:
        $ref: '#/components/schemas/Coordinates'

    Geometry:
      type: object
      properties:
        type:
          type: string
          enum: ['Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon']
        coordinates:
          oneOf:
            - $ref: '#/components/schemas/Coordinate'
            - $ref: '#/components/schemas/Coordinates'
            - $ref: '#/components/schemas/Rings'

    Polygon:
      type: object
      properties:
        type:
          type: string
          enum: ['Polygon']
        coordinates:
          $ref: '#/components/schemas/Rings'

    Feature:
      type: object
      properties:
        type:
          type: string
          enum: ['Feature']
        objectId:
          $ref: '#/components/schemas/ObjectId'
        geometry:
          $ref: '#/components/schemas/Geometry'
        properties:
          type: object
          properties:
            AnyValue: {}
        area:
          type: number
        length:
          type: number

    FeatureCollection:
      type: object
      properties:
        type:
          type: string
          enum: ['FeatureCollection']
        srs:
          type: string
          description: |
            Authority of used coordinate reference system e.g. EPSG:3857
        features:
          type: array
          items:
            $ref: '#/components/schemas/Feature'

    SpatialFilter:
      type: object
      properties:
        spatialRelation:
          type: string
          enum: ['overlaps', 'notOverlaps', 'contains']
        geometry:
          $ref: '#/components/schemas/Polygon'

    Table:
      type: object
      properties:
        columns:
          type: array
          items:
            type: string
        values:
          type: array
          items:
            type: array
            items:
              anyOf:
                - type: string
                - type: number
                - type: integer
        totals:
          type: array
          items:
            anyOf:
              - type: string
              - type: number
              - type: integer

    LayerPath:
      type: array
      items:
        type: string

    Distance:
      type: object
      properties:
        value:
          type: number
        lengthUnit:
          type: string
          enum: ['m', 'km']

    AreaIntersectionRequest:
      type: object
      properties:
        layerPath:
          $ref: '#/components/schemas/LayerPath'
        geometry:
          $ref: '#/components/schemas/Geometry'
        useMapSrs:
          type: boolean
        buffer:
          $ref: '#/components/schemas/Distance'
        useAutoCorrection:
          type: boolean
        includeGeometryValidationReport:
          type: boolean

    AreaIntersectionsResult:
      type: object
      properties:
        results:
          $ref: '#/components/schemas/FeatureCollection'
        errors:
          $ref: '#/components/schemas/FeatureCollection'

    ObjectInfoRequest:
      type: object
      properties:
        layerPath:
          $ref: '#/components/schemas/LayerPath'
        objectIds:
          $ref: '#/components/schemas/ObjectIds'
        useMapSrs:
          type: boolean
        fullGeometries:
          type: boolean
