openapi: 3.1.0
info:
  title: Popcast Reporting API
  version: 0.1.0
  description: |
    Reporting layer of The Conscience Stack. Per-block-group rolling
    headline windows sourced from local newspaper RSS, TV station RSS,
    Patch, Substack local publications, Wikipedia pageview surges, and
    GNews (credential-gated). Every response follows the standard
    `{data, meta}` envelope with provenance per ADR-003.

    Data maturity: `synthetic-only` at launch; promotes to `production`
    once ingest has run against the feed registry for 7 days.
  contact:
    name: Motionworks AI
    url: https://docs.mworks.com
servers:
  - url: https://api.mworks.com
    description: Production
tags:
  - name: reporting
    description: Block group reporting signal endpoints
paths: {}
components:
  parameters:
    FipsParam:
      name: fips
      in: path
      required: true
      schema:
        type: string
        pattern: ^\d{12}$
      description: 12-digit US Census block group GEOID
  schemas:
    Headline:
      type: object
      required:
        - id
        - title
        - source_type
        - source_name
        - published_at
      properties:
        id:
          type: string
        title:
          type: string
        source_type:
          type: string
          enum:
            - news-api
            - patch
            - tv-rss
            - substack
            - local-gov
            - wikipedia
            - newspaper-rss
        source_name:
          type: string
        url:
          type: string
          format: uri
        published_at:
          type: string
          format: date-time
        sentiment:
          type: string
          enum:
            - positive
            - neutral
            - negative
        topics:
          type: array
          items:
            type: string
    ReportingPayload:
      type: object
      properties:
        headlines:
          type: array
          items:
            $ref: '#/components/schemas/Headline'
        topics:
          type: array
          items:
            type: string
        sentiment:
          type: object
          properties:
            positive_pct:
              type: number
            neutral_pct:
              type: number
            negative_pct:
              type: number
        sources:
          type: object
          additionalProperties:
            type: integer
    ReportingSignal:
      type: object
      required:
        - fips
        - signal_layer
        - period_end
        - window_days
        - refreshed_at
        - data_quality
        - source_breakdown
        - payload
      properties:
        fips:
          type: string
        signal_layer:
          type: string
          enum:
            - reporting
        period_end:
          type: string
        window_days:
          type: integer
          enum:
            - 7
            - 14
            - 30
        refreshed_at:
          type: string
          format: date-time
        data_quality:
          type: string
          enum:
            - high
            - medium
            - low
        source_breakdown:
          type: object
          additionalProperties:
            type: integer
        payload:
          $ref: '#/components/schemas/ReportingPayload'
    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'
    Provenance:
      type: object
      properties:
        source:
          type: string
        source_doc:
          type: string
          format: uri
        methodology_version:
          type: string
        data_vintage:
          type: string
        data_freshness:
          type: string
        data_latency_days:
          type: integer
        data_maturity:
          type: string
    ReportingSignalResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ReportingSignal'
        meta:
          $ref: '#/components/schemas/Meta'
    ReportingHistorySnapshot:
      type: object
      properties:
        fips:
          type: string
        period_start:
          type: string
        period_end:
          type: string
        window_days:
          type: integer
        headline_count:
          type: integer
        topics:
          type: array
          items:
            type: string
        sentiment:
          type: object
          properties:
            positive_pct:
              type: number
            neutral_pct:
              type: number
            negative_pct:
              type: number
        data_quality:
          type: string
          enum:
            - high
            - medium
            - low
    ReportingHistoryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingHistorySnapshot'
        pagination:
          type: object
          properties:
            cursor:
              type: string
              nullable: true
            has_more:
              type: boolean
            total:
              type: integer
        meta:
          $ref: '#/components/schemas/Meta'
    ReportingBatchRequest:
      type: object
      required:
        - fips_codes
      properties:
        fips_codes:
          type: array
          maxItems: 100
          items:
            type: string
            pattern: ^\d{12}$
        window:
          type: integer
          enum:
            - 7
            - 14
            - 30
    ReportingBatchResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingSignal'
        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: No data for block group
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
