openapi: '3.1.0'
info:
  title: Motionworks API - Viewcast (Inventory Profiles)
  version: 2.0.0
  description: >
    Face-level and spot-level OOH measurement data including circulation,
    opportunity-to-see (OTS), likelihood-to-see (LTS), and audience reach
    at effective-frequency thresholds.

    Key corrections from the v2 scaffold:
      - media_type is size-based (Display/Panel/Junior Poster/Poster/Bulletin/Murals)
      - classification_type is 2-value (Roadside | Place-Based)
      - Reach is 4 variants: total/market x eff1/eff3 — not a single reach_pct
      - Both face-level and spot-level measurements exposed
      - viewcast_score removed (roadmap TF-90)

    Invariant: LTS <= OTS <= Circulation <= Traffic (at both face and spot level)

  contact:
    name: Motionworks AI
    url: https://mworks.com
    email: api@mworks.com

servers:
  - url: https://api.mworks.com/v2
    description: Production

security:
  - apiKey: []

components:
  securitySchemes:
    apiKey:
      type: apiKey
      name: X-API-Key
      in: header

  schemas:
    ViewcastMarket:
      type: object
      properties:
        co_geoid:
          type: string
        co_name:
          type: string
        st_name:
          type: string
        cbsa_geoid:
          type: string
        cbsa_name:
          type: string
        cbsa_type:
          type: string
        dma_geoid:
          type: string
        dma_name:
          type: string
        postal_code:
          type: string

    FaceMeasurements:
      type: object
      x-motionworks-status: production
      description: >
        Aggregated across all spots on the face. LTS <= OTS <= face_circ <= traffic.
      properties:
        traffic:
          type: integer
          description: Weekly average vehicles + pedestrians in the viewshed.
        face_circ:
          type: integer
          description: Weekly average circulation (persons) to the face.
        face_ots:
          type: integer
          description: Weekly average OTS impressions for the face.
        face_lts:
          type: integer
          description: Weekly average LTS impressions (OTS x Geopath VAI).
        face_share_of_voice:
          type: number
          minimum: 0
          maximum: 1
        dwell:
          type: number
          description: Circulation-weighted dwell in minutes within the viewshed.

    SpotMeasurements:
      type: object
      x-motionworks-status: production
      description: >
        Weighted by share_of_voice and spot_length for digital displays.
        For static (SoV=1.0), equals face measurements.
        spot_lts <= spot_ots <= spot_circ.
      properties:
        spot_circ:
          type: integer
        spot_ots:
          type: integer
        spot_lts:
          type: integer
        share_of_voice:
          type: number
          minimum: 0
          maximum: 1
          description: Fraction of time this spot is visible on the face.
        spot_length:
          type: integer
          description: Spot duration in seconds (digital only).

    ViewcastReach:
      type: object
      x-motionworks-status: production
      description: >
        4 reach variants: total-US and DMA-market populations, each at
        effective frequency 1+ and 3+.
      properties:
        total_population:
          type: integer
        market_population:
          type: integer
        total_reach_eff1:
          type: integer
          description: Total US population reached at least once.
        market_reach_eff1:
          type: integer
        total_reach_eff3:
          type: integer
          description: Total US population reached at least 3 times.
        market_reach_eff3:
          type: integer

    ViewcastProfile:
      type: object
      x-motionworks-status: production
      x-motionworks-source: viewcast-profiles
      x-motionworks-source-doc: https://docs.mworks.com/docs/viewcast-profiles
      properties:
        place_id:
          type: integer
        spot_id:
          type: integer
        geopath_spot_id:
          type: integer
        geopath_frame_id:
          type: integer
        location:
          type: string
          description: WKT POINT of the face.
        market:
          $ref: '#/components/schemas/ViewcastMarket'
        construction_type:
          type: string
          enum:
            - Freestanding
            - Interior Wall
            - Furniture
            - Exterior Wall
            - Bus Exterior
            - Exterior Vehicle
            - Ceiling
            - Floor
            - Column
            - Elevator
            - Stairs
            - Furniture - Top
            - Interior Vehicle
            - Tablet
            - Rooftop
        classification_type:
          type: string
          enum: [Roadside, Place-Based]
          description: Replaces the invented 4-value media_class from the v2 scaffold.
        media_type:
          type: string
          enum: [Display, Panel, Junior Poster, Poster, Bulletin, Murals]
          description: Size-based display classification. Replaces the scaffold's 4-value enum.
        digital:
          type: boolean
        face_orientation:
          type: number
          description: Display orientation in degrees (0=N, 180=S).
        face_height:
          type: number
          description: Display height in inches.
        face_width:
          type: number
          description: Display width in inches.
        viewable_distance:
          type: number
          description: Maximum viewable distance in feet.
        face_audit_status:
          type: integer
        period_start:
          type: string
          format: date
        period_end:
          type: string
          format: date
        period_days:
          type: integer
        face:
          $ref: '#/components/schemas/FaceMeasurements'
        spot:
          $ref: '#/components/schemas/SpotMeasurements'
        reach:
          $ref: '#/components/schemas/ViewcastReach'
        assignment_status:
          type: string
          enum:
            - Industry Assigned
            - System Assigned
            - Motionworks Assigned
            - Unverified Assignments

    Pagination:
      type: object
      properties:
        cursor:
          type: string
          nullable: true
        has_more:
          type: boolean
        total:
          type: integer

    Provenance:
      type: object
      properties:
        source:
          type: string
        source_doc:
          type: string
          format: uri
        methodology_version:
          type: string
        data_vintage:
          type: string
          format: date
        data_freshness:
          type: string
        data_latency_days:
          type: integer
        data_maturity:
          type: string
          enum: [production, research-preview, synthetic-only, roadmap]

    Meta:
      type: object
      properties:
        request_id:
          type: string
        credits_used:
          type: integer
        credits_remaining:
          type: integer
        product:
          type: string
        version:
          type: string
        provenance:
          $ref: '#/components/schemas/Provenance'

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            status:
              type: integer
            request_id:
              type: string
            docs_url:
              type: string

paths:
  /profiles/{place_id}:
    get:
      operationId: getViewcastProfile
      summary: Get a single Viewcast profile (face + spot measurements)
      x-credit-cost: 1
      x-motionworks-status: production
      x-motionworks-source-doc: https://docs.mworks.com/docs/viewcast-profiles
      parameters:
        - name: place_id
          in: path
          required: true
          schema:
            type: integer
        - name: fields
          in: query
          schema:
            type: string
          description: Comma-separated field names to project.
        - name: include
          in: query
          schema:
            type: string
          description: 'Additional data: geopath, demographics, history'
      responses:
        '200':
          description: ViewcastProfile
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ViewcastProfile'
                  meta:
                    $ref: '#/components/schemas/Meta'
        '404':
          description: Profile not found

  /profiles:
    get:
      operationId: searchViewcastProfiles
      summary: Search Viewcast profiles
      x-credit-cost: 5
      x-motionworks-status: production
      parameters:
        - name: market_id
          in: query
          schema:
            type: string
        - name: media_type
          in: query
          schema:
            type: string
            enum: [Display, Panel, Junior Poster, Poster, Bulletin, Murals]
        - name: classification_type
          in: query
          schema:
            type: string
            enum: [Roadside, Place-Based]
        - name: construction_type
          in: query
          schema:
            type: string
        - name: digital
          in: query
          schema:
            type: boolean
        - name: min_ots
          in: query
          schema:
            type: integer
        - name: max_ots
          in: query
          schema:
            type: integer
        - name: bbox
          in: query
          schema:
            type: string
          description: 'sw_lat,sw_lng,ne_lat,ne_lng'
        - name: updated_since
          in: query
          schema:
            type: string
            format: date-time
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
      responses:
        '200':
          description: Paginated ViewcastProfiles
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ViewcastProfile'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  meta:
                    $ref: '#/components/schemas/Meta'

  /profiles/{place_id}/history:
    get:
      operationId: getViewcastHistory
      summary: Historical measurements for a profile
      x-credit-cost: 10
      x-motionworks-status: production
      parameters:
        - name: place_id
          in: path
          required: true
          schema:
            type: integer
        - name: granularity
          in: query
          schema:
            type: string
            enum: [by_year, by_month, by_week]
            default: by_month
        - name: start_date
          in: query
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Array of historical ViewcastProfile periods

  /profiles/bulk:
    post:
      operationId: bulkViewcastProfiles
      summary: Batch retrieve multiple profiles
      description: >
        Convenience endpoint — each entry in ids[] resolves via the
        single-profile path. Max 500 per batch.
      x-credit-cost: 50
      x-motionworks-status: production
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                  maxItems: 500
                fields:
                  type: array
                  items:
                    type: string
      responses:
        '200':
          description: Array of ViewcastProfile objects
