openapi: 3.1.0
info:
  title: Popcast Conscience API
  version: 0.1.0
  description: |
    The Conscience Stack fusion endpoint. One call, all five layers:
    Conversation + Reporting + Change + Attention + Ambient, attributed
    to a US Census block group FIPS.

    Filter layers via `?layers=ambient,change` to pay only for the
    slices you need. Partial-success tolerance: one layer failing does
    not fail the fusion; failures populate `payload.layer_errors[]`.
  contact: { name: Motionworks AI, url: https://docs.mworks.com }

servers:
  - url: https://api.mworks.com

tags:
  - name: conscience
    description: Fusion across all Conscience Stack layers

paths:
  /v2/popcast/conscience/{fips}:
    get:
      operationId: getConscienceSignal
      summary: Fused signal across all (or selected) Conscience Stack layers
      description: |
        Full fusion costs 5 credits; filtered fusion costs 1 per
        requested layer.
      tags: [conscience]
      x-motionworks-status: roadmap
      x-motionworks-data-maturity: synthetic-only
      x-credit-cost: 5
      parameters:
        - $ref: '#/components/parameters/FipsParam'
        - name: layers
          in: query
          description: Comma-separated list of layers to include.
          schema:
            type: string
            example: "conversation,ambient"
      responses:
        '200':
          description: Conscience signal
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ConscienceSignalResponse' }
        '404': { $ref: '#/components/responses/NotFound' }
        '400': { $ref: '#/components/responses/ValidationError' }

  /v2/popcast/conscience/batch:
    post:
      operationId: batchConscienceSignals
      summary: Batch fused signals (up to 50 FIPS)
      description: Up to 50 FIPS per call. Credit = 5 per FIPS (or N per FIPS when filtered).
      tags: [conscience]
      x-motionworks-status: roadmap
      x-motionworks-data-maturity: synthetic-only
      x-credit-cost: 250
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ConscienceBatchRequest' }
      responses:
        '200':
          description: Batch results
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ConscienceBatchResponse' }

components:
  parameters:
    FipsParam:
      name: fips
      in: path
      required: true
      schema: { type: string, pattern: '^\d{12}$' }

  schemas:
    ConscienceLayer:
      type: string
      enum: [conversation, reporting, change, attention, ambient]

    ConscienceLayerError:
      type: object
      properties:
        layer: { $ref: '#/components/schemas/ConscienceLayer' }
        error: { type: string }
        status: { type: integer }

    ConsciencePayload:
      type: object
      description: |
        Optional per-layer payloads. Each property mirrors the
        corresponding layer's `payload` shape (see individual layer
        specs).
      properties:
        conversation: { type: object, additionalProperties: true }
        reporting: { type: object, additionalProperties: true }
        change: { type: object, additionalProperties: true }
        attention: { type: object, additionalProperties: true }
        ambient: { type: object, additionalProperties: true }
        layer_errors:
          type: array
          items: { $ref: '#/components/schemas/ConscienceLayerError' }

    ConscienceSignal:
      type: object
      required: [fips, signal_layer, period_end, refreshed_at, layers_included, payload]
      properties:
        fips: { type: string }
        signal_layer: { type: string, enum: [conscience] }
        period_end: { type: string }
        refreshed_at: { type: string, format: date-time }
        data_quality: { type: string, enum: [high, medium, low] }
        layers_included:
          type: array
          items: { $ref: '#/components/schemas/ConscienceLayer' }
        payload: { $ref: '#/components/schemas/ConsciencePayload' }

    Meta:
      type: object
      properties:
        request_id: { type: string }
        credits_used: { type: integer }
        product: { type: string }
        version: { type: string }
        requested_layers:
          type: array
          items: { $ref: '#/components/schemas/ConscienceLayer' }

    ConscienceSignalResponse:
      type: object
      properties:
        data: { $ref: '#/components/schemas/ConscienceSignal' }
        meta: { $ref: '#/components/schemas/Meta' }

    ConscienceBatchRequest:
      type: object
      required: [fips_codes]
      properties:
        fips_codes:
          type: array
          maxItems: 50
          items: { type: string, pattern: '^\d{12}$' }
        layers:
          type: array
          items: { $ref: '#/components/schemas/ConscienceLayer' }

    ConscienceBatchResponse:
      type: object
      properties:
        data:
          type: array
          items: { $ref: '#/components/schemas/ConscienceSignal' }
        meta: { $ref: '#/components/schemas/Meta' }

    ApiError:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string }
            message: { type: string }
            status: { type: integer }
            request_id: { type: string }

  responses:
    NotFound:
      description: Not found
      content:
        application/json:
          schema: { $ref: '#/components/schemas/ApiError' }
    ValidationError:
      description: Validation error
      content:
        application/json:
          schema: { $ref: '#/components/schemas/ApiError' }
