openapi: 3.0.0
info:
  title: PostData
  description: |
    The simplest API to get your device's data onto the cloud. No signup, no
    API keys, everything public. Works over https:// and, deliberately, plain
    http:// for constrained firmware.
  version: 2.0.0
components:
  schemas:
    Metric:
      type: object
      minProperties: 1
      maxProperties: 10
      description: |
        A flat object of 1-10 metrics. Values are numbers, or short strings
        (strings keep only their last value - no history). Keys named "ts" or
        "timestamp" are ignored; the server sets the reception timestamp.
      example:
        temperature: 12.52
        humidity: 81
        firmware: "rc2.0.2"
    MetricResponse:
      type: object
      minProperties: 1
      description: The stored metrics plus ts, the server reception time (unix seconds).
      example:
        ts: 1785239565
        temperature: 12.52
        humidity: 81
    Error:
      type: object
      properties:
        error:
          type: string
servers:
  - url: https://api.postdata.cloud
  - url: http://api.postdata.cloud
    description: Plain HTTP, for devices where TLS is impractical
paths:
  /add/{id}:
    post:
      tags:
        - Devices
      summary: Send a new set of metrics for a device
      requestBody:
        description: A flat JSON object with the metrics for this device.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Metric'
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: |
            A unique name for the device (letters, numbers, "_", ".", "-",
            max 64 chars). First come, first served - use something
            hard to guess (e.g. a UUID) if you want practical obscurity.
      responses:
        '200':
          description: Responds with the stored metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Metric'
        '400':
          description: Invalid device name, metric name, or body structure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limited (one message per device per 30 seconds). See the Retry-After header.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the next message is accepted
    get:
      tags:
        - Devices
      summary: Send metrics via query parameters (for constrained firmware)
      description: |
        Same as the POST variant, but metrics travel as query parameters, e.g.
        `/add/my-sensor?temp=21.5&hum=60`. Values that parse as numbers are
        stored as numbers.
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: The unique device name
      responses:
        '200':
          description: Responds with the stored metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Metric'
        '400':
          description: Invalid device name, metric name, or no metrics provided
        '429':
          description: Rate limited. See the Retry-After header.
  /last/{id}:
    get:
      tags:
        - Devices
      summary: Get the last metrics sent from a device
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: The unique device name
      responses:
        '200':
          description: The last stored metrics, plus the server reception timestamp.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetricResponse'
        '400':
          description: Invalid device name
        '404':
          description: Unknown device
  /past/{id}/{hours}:
    get:
      tags:
        - Devices
      summary: Get historical numeric metrics from a device
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: The unique device name
        - in: path
          name: hours
          schema:
            type: integer
            default: 168
            maximum: 2208
          required: true
          description: |
            How many hours to look back (168 = one week; capped at 2208, about
            92 days, which is also the retention window). May be omitted
            entirely (`/past/{id}`) to get the default week.
      responses:
        '200':
          description: A timestamp-ordered array of readings (numeric metrics only)
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MetricResponse'
        '400':
          description: Invalid device name
        '404':
          description: Unknown device
  /live/{id}:
    get:
      tags:
        - Live
      summary: Stream metrics live over a WebSocket
      description: |
        Upgrade to a WebSocket and receive the current reading immediately,
        then every new reading as it arrives. Each message is a JSON object
        shaped like /last. Text frame "ping" is answered with "pong".
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: The unique device name
        - in: header
          name: Upgrade
          required: true
          schema:
            type: string
            enum: [websocket]
      responses:
        '101':
          description: WebSocket established
        '426':
          description: Not a WebSocket upgrade request
  /explore:
    get:
      tags:
        - Discovery
      summary: List the 20 most recently active devices
      responses:
        '200':
          description: Recently active devices with their latest data
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    name:
                      type: string
                    ts:
                      type: integer
                      description: Last reception time, unix milliseconds
                    data:
                      $ref: '#/components/schemas/Metric'
