openapi: 3.1.0
info:
  title: Popcast Change API
  version: 0.1.0
  description: |
    Change layer of The Conscience Stack. Per-block-group physical change
    velocity: building permits, business open/close events, real-estate
    aggregates. Sources: Atlanta/NYC/LA/Chicago/SF Socrata portals (real),
    state SoS business registries (per-state stub), real-estate aggregate
    (synthetic placeholder).
  contact:
    name: Motionworks AI
    url: https://docs.mworks.com
servers:
  - url: https://api.mworks.com
tags:
  - name: change
    description: Block group change signal endpoints
paths: {}
components:
  parameters:
    FipsParam:
      name: fips
      in: path
      required: true
      schema:
        type: string
        pattern: ^\d{12}$
  schemas:
    PermitEvent:
      type: object
      properties:
        id:
          type: string
        permit_type:
          type: string
          enum:
            - new-construction
            - addition
            - renovation
            - demolition
            - signage
            - electrical
            - plumbing
            - mechanical
            - other
        description:
          type: string
        issue_date:
          type: string
        estimated_value_usd:
          type: number
        latitude:
          type: number
        longitude:
          type: number
        address:
          type: string
        source:
          type: string
    BusinessEvent:
      type: object
      properties:
        id:
          type: string
        change_type:
          type: string
          enum:
            - new-open
            - closed
            - renovation
            - ownership-transfer
            - rebranding
        business_name:
          type: string
        effective_date:
          type: string
        source:
          type: string
    RealEstateSnapshot:
      type: object
      properties:
        active_listings:
          type: integer
        median_list_price_usd:
          type: number
          nullable: true
        median_days_on_market:
          type: number
          nullable: true
        price_trend_30d_pct:
          type: number
          nullable: true
        new_listings_window:
          type: integer
        sold_window:
          type: integer
        source:
          type: string
    ChangePayload:
      type: object
      properties:
        permits:
          type: object
          properties:
            total:
              type: integer
            total_value_usd:
              type: number
            by_type:
              type: object
              additionalProperties:
                type: integer
            recent:
              type: array
              items:
                $ref: '#/components/schemas/PermitEvent'
        business_changes:
          type: object
          properties:
            total:
              type: integer
            by_type:
              type: object
              additionalProperties:
                type: integer
            recent:
              type: array
              items:
                $ref: '#/components/schemas/BusinessEvent'
        real_estate:
          $ref: '#/components/schemas/RealEstateSnapshot'
        change_velocity:
          type: number
          minimum: 0
          maximum: 100
    ChangeSignal:
      type: object
      required:
        - fips
        - signal_layer
        - period_end
        - window_days
        - refreshed_at
        - payload
      properties:
        fips:
          type: string
        signal_layer:
          type: string
          enum:
            - change
        period_end:
          type: string
        window_days:
          type: integer
          enum:
            - 30
            - 90
            - 180
            - 365
        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/ChangePayload'
    Meta:
      type: object
      properties:
        request_id:
          type: string
        credits_used:
          type: integer
        credits_remaining:
          type: integer
        product:
          type: string
        version:
          type: string
        provenance:
          type: object
          properties:
            source:
              type: string
            data_maturity:
              type: string
    ChangeSignalResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ChangeSignal'
        meta:
          $ref: '#/components/schemas/Meta'
    ChangeHistorySnapshot:
      type: object
      properties:
        fips:
          type: string
        period_start:
          type: string
        period_end:
          type: string
        window_days:
          type: integer
        permit_count:
          type: integer
        business_event_count:
          type: integer
        change_velocity:
          type: number
        data_quality:
          type: string
    ChangeHistoryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ChangeHistorySnapshot'
        pagination:
          type: object
          properties:
            cursor:
              type: string
              nullable: true
            has_more:
              type: boolean
            total:
              type: integer
        meta:
          $ref: '#/components/schemas/Meta'
    ChangeBatchRequest:
      type: object
      required:
        - fips_codes
      properties:
        fips_codes:
          type: array
          maxItems: 100
          items:
            type: string
            pattern: ^\d{12}$
        window:
          type: integer
          enum:
            - 30
            - 90
            - 180
            - 365
    ChangeBatchResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ChangeSignal'
        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'
