openapi: 3.0.3
info:
  title: BlueMaestro Cloud — Public Data API
  version: "1.0.0-beta"
  description: >
    **Beta.** Read-only API for pulling your device and log data into your own dashboards
    (Grafana, Power BI, scripts). Enterprise "API Access" add-on required.
    Authenticate with the `X-Api-Key` header using a key created in Account → API Keys.
    The base URL and contract are finalised as the API rolls out.
servers:
  - url: https://{apiId}.execute-api.us-west-2.amazonaws.com/v1
    description: Production (v1 stage)
    variables:
      apiId:
        default: REPLACE_WITH_V1_API_ID
security:
  - ApiKeyAuth: []
paths:
  /devices:
    get:
      summary: List your devices
      operationId: listDevices
      responses:
        "200":
          description: The devices visible to this API key's owner.
          content:
            application/json:
              schema:
                type: object
                properties:
                  devices:
                    type: array
                    items: { $ref: "#/components/schemas/Device" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "429": { $ref: "#/components/responses/RateLimited" }
  /devices/{deviceId}/logs:
    get:
      summary: Get time-series sensor data for one device
      operationId: getDeviceLogs
      parameters:
        - name: deviceId
          in: path
          required: true
          description: Full device MAC (hex pairs separated by ":").
          schema: { type: string, example: "AA:BB:CC:DD:EE:FF" }
        - name: version
          in: query
          required: true
          description: Device firmware/model version.
          schema: { type: string, enum: ["13", "23", "27", "41", "42", "43"] }
        - name: interval
          in: query
          required: false
          description: Binning interval in minutes (minimum 5; defaults to 15).
          schema: { type: integer, minimum: 5, default: 15 }
        - name: startDaysAgo
          in: query
          required: true
          description: Start of the window, in days before now (further in the past than endDaysAgo).
          schema: { type: integer, minimum: 0, example: 7 }
        - name: endDaysAgo
          in: query
          required: true
          description: End of the window, in days before now (0 = up to now).
          schema: { type: integer, minimum: 0, example: 0 }
        - name: nextToken
          in: query
          required: false
          description: Opaque pagination token from a previous response.
          schema: { type: string }
      responses:
        "200":
          description: A page of readings (newest first). Values are integers scaled ×100.
          content:
            application/json:
              schema:
                type: object
                properties:
                  deviceId: { type: string }
                  version: { type: string }
                  interval: { type: integer }
                  data:
                    type: array
                    items: { $ref: "#/components/schemas/Reading" }
                  hasMoreData: { type: boolean }
                  nextToken: { type: string, nullable: true }
        "400":
          description: >
            Invalid parameters (bad MAC/version/interval, or a time range over 31 days —
            paginate for longer ranges).
        "401": { $ref: "#/components/responses/Unauthorized" }
        "429": { $ref: "#/components/responses/RateLimited" }
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
  responses:
    Unauthorized:
      description: Missing, invalid, revoked, expired, or unentitled API key.
    RateLimited:
      description: Daily quota or rate limit exceeded.
      headers:
        Retry-After:
          schema: { type: integer }
  schemas:
    Device:
      type: object
      properties:
        gatewayId: { type: string }
        gatewayName: { type: string }
        mac: { type: string, nullable: true }
        name: { type: string, nullable: true }
    Reading:
      type: object
      description: Values are integers scaled ×100 (e.g. temp 2150 = 21.50). Fields depend on version.
      properties:
        unix: { type: string, description: ISO 8601 timestamp }
        temp: { type: integer, description: temperature ×100 }
        humi: { type: integer, description: humidity ×100 }
        press: { type: integer, description: pressure (Pa) }
        dewp: { type: integer, description: dewpoint ×100 }
        batt: { type: integer, description: battery % }
