openapi: '3.1.0'
info:
  title: Motionworks API - Popcast (Population Intelligence)
  version: 2.0.0
  description: >
    Segment-based population counts. Customer defines a cohort via
    demographic filters (Cohort Search), then queries Popcast At Home
    for how many matching people live in each geography.

    The v2 scaffold modeled Popcast as location profiles with lat/lng.
    The real product is fundamentally segment x geography x year → counts.
    There is no lat/lng at the record level; geography is a polygon
    reference via geography_id.

    Sources:
      https://docs.mworks.com/docs/popcast-at-home
      https://docs.mworks.com/docs/ref-segments
      API: apiref-popcast-at-home, apiref-popcast-cohort-search

  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:
    PopcastSegmentDefinition:
      type: object
      x-motionworks-status: production
      x-motionworks-source: popcast-cohort-search
      x-motionworks-source-doc: https://docs.mworks.com/docs/ref-segments
      required: [customer_segment_id, customer_segment_name]
      description: >
        Customer-defined population segment from demographic filters.
        Every filter is optional (omit = no restriction). Filters compose as AND.
      properties:
        customer_segment_id:
          type: string
        customer_segment_name:
          type: string
        age_min:
          type: integer
          minimum: 0
          maximum: 100
        age_max:
          type: integer
          minimum: 0
          maximum: 100
        gender:
          type: string
          enum: [f, m]
        races:
          type: array
          items:
            type: string
            enum: [white, black, native, asian, islander, other, multiple]
        hispanic:
          type: boolean
        worker:
          type: boolean
        language:
          type: array
          items:
            type: string
            enum: [english, spanish, other]
        household_size_min:
          type: integer
          minimum: 1
          maximum: 20
        household_size_max:
          type: integer
          minimum: 1
          maximum: 20
        household_children:
          type: boolean
        household_income_min:
          type: integer
          description: USD, inflation-adjusted. May be negative.
        household_income_max:
          type: integer
        household_vehicles_min:
          type: integer
          minimum: 0
          maximum: 5
        household_vehicles_max:
          type: integer
          minimum: 0
          maximum: 5
        prizm_segments:
          type: array
          items:
            type: integer
        consumer_segments:
          type: array
          items:
            type: string
        year:
          type: integer

    PopcastSegment:
      allOf:
        - $ref: '#/components/schemas/PopcastSegmentDefinition'
        - type: object
          properties:
            motionworks_segment_id:
              type: string
              format: uuid
            customer_id:
              type: integer
            customer_name:
              type: string
            vintage:
              type: string

    PopcastAtHome:
      type: object
      x-motionworks-status: production
      x-motionworks-source: popcast-at-home
      x-motionworks-source-doc: https://docs.mworks.com/docs/popcast-at-home
      properties:
        motionworks_segment_id:
          type: string
        customer_segment_id:
          type: string
        customer_segment_name:
          type: string
        year:
          type: integer
        geography_id:
          type: string
          description: >
            e.g. US2010XXBG360610031001 (block group), US2020STCO36061 (county),
            US2020XDMA532 (DMA).
        persons:
          type: integer
          description: Count matching the segment in this geography.
        households:
          type: integer
        all_persons:
          type: integer
          description: Total persons in the geography (no segment filter).
        all_households:
          type: integer
        hh_persons:
          type: integer
          description: Non-group-quarters persons.
        hh_households:
          type: integer
        gq_persons:
          type: integer
          description: Group-quarters persons (dorms, prisons, military, etc.)
        gq_households:
          type: integer
        vintage:
          type: string

    PopcastAnytime:
      type: object
      x-motionworks-status: roadmap
      x-motionworks-roadmap-issue: "TF-89"
      x-motionworks-source-doc: https://docs.mworks.com/docs/popcast-at-home
      description: >
        ROADMAP (TF-89) — Popcast Anytime is not a shipped product yet.
        When queried without roadmap mode, this endpoint returns 404.
        In roadmap mode, it returns 501 NOT_YET_AVAILABLE.
      properties:
        location_id:
          type: string
        daytime_population:
          type: integer
        nighttime_population:
          type: integer
        flow_index:
          type: number
        hourly_population:
          type: array
          items:
            type: integer
          minItems: 24
          maxItems: 24
        daypart_composition:
          type: array
          items:
            type: object

    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:
  # ─── Cohort Search (segment CRUD) ────────────────────────────────────

  /popcast/segments:
    post:
      operationId: createPopcastSegment
      summary: Define a custom population segment
      description: >
        Submits a segment definition from demographic filters. Returns the
        resolved segment with motionworks_segment_id that can be used in
        At Home queries and Set Dynamics cohorts.
      x-credit-cost: 0
      x-motionworks-status: production
      x-motionworks-source-doc: https://docs.mworks.com/reference/apiref-popcast-cohort-search
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PopcastSegmentDefinition'
      responses:
        '201':
          description: Segment created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PopcastSegment'
                  meta:
                    $ref: '#/components/schemas/Meta'

    get:
      operationId: listPopcastSegments
      summary: List segments defined for this org
      x-credit-cost: 0
      x-motionworks-status: production
      parameters:
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
      responses:
        '200':
          description: Paginated segments
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PopcastSegment'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  meta:
                    $ref: '#/components/schemas/Meta'

  /popcast/segments/{segment_id}:
    get:
      operationId: getPopcastSegment
      summary: Get a segment by motionworks_segment_id
      x-credit-cost: 0
      x-motionworks-status: production
      parameters:
        - name: segment_id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Segment
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PopcastSegment'
                  meta:
                    $ref: '#/components/schemas/Meta'
        '404':
          description: Segment not found

  # ─── At Home ─────────────────────────────────────────────────────────

  /popcast/at-home:
    get:
      operationId: getPopcastAtHome
      summary: Count matching persons per geography for a segment
      description: >
        Returns one row per geography matching the query. Provide both
        segment_id and geography_id for a single row; omit geography_id
        and provide geography_type to iterate across all geographies of
        that type. Counts are from the segment's year Digital Population.
      x-credit-cost: 2
      x-motionworks-status: production
      x-motionworks-source-doc: https://docs.mworks.com/docs/popcast-at-home
      parameters:
        - name: segment_id
          in: query
          required: true
          schema:
            type: string
        - name: geography_id
          in: query
          schema:
            type: string
        - name: year
          in: query
          schema:
            type: integer
        - name: geography_type
          in: query
          schema:
            type: string
            enum: [stco, bg, dma, cbsa, state, zcta]
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 5000
            default: 100
      responses:
        '200':
          description: Paginated PopcastAtHome rows
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PopcastAtHome'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  meta:
                    $ref: '#/components/schemas/Meta'

  # ─── Anytime (ROADMAP TF-89) ─────────────────────────────────────────

  /popcast/anytime/{location_id}:
    get:
      operationId: getPopcastAnytime
      summary: Hourly population by location [ROADMAP]
      description: >
        ROADMAP (TF-89). Popcast Anytime is not a shipped data product yet.
        In customer/internal mode this returns 404. In roadmap mode this
        returns 501 NOT_YET_AVAILABLE with the tracking link.
      x-credit-cost: 2
      x-motionworks-status: roadmap
      x-motionworks-roadmap-issue: "TF-89"
      parameters:
        - name: location_id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: >-
            Anytime profile (only returned when the data product ships in a
            future release; until then this endpoint returns 501 or 404
            depending on the caller's data_maturity_mode).
        '501':
          description: Not yet available (roadmap mode only)
        '404':
          description: Not found (customer/internal mode)
