openapi: 3.0.0
info:
  title: Connect API - Public Submission
  description: Standalone OpenAPI document for the public WaterlyConnect submission endpoint.
  version: 1.0.0
  contact: {}
servers:
  - url: https://connect.waterly.com
    description: Production
tags:
  - name: Public Submission
    description: Public ingestion endpoint for WaterlyConnect devices
paths:
  /api/data-submission/v1/submit:
    post:
      operationId: SubmissionController_submit
      summary: Submit WaterlyConnect edge device data
      description: Server-to-server submission endpoint. Browser CORS is not supported. Persist the submission, enqueue downstream processing, and return a minimal success envelope. Requests are limited to 1 MB and rate limited. If you need to send more data, split it into multiple requests.
      parameters:
        - name: X-Waterly-Connect-Token
          in: header
          description: Provisioned edge-device token.
          required: true
          schema:
            type: string
        - name: X-Waterly-Request-Type
          in: header
          description: Must be WaterlyConnect.
          required: true
          schema:
            type: string
            example: WaterlyConnect
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SubmissionSubmitRequestDto"
      responses:
        "200":
          description: Submission accepted and queued.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionSuccessResponseDto"
        "400":
          description: Validation failure.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionErrorResponseDto"
        "401":
          description: Authentication failure.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionErrorResponseDto"
        "413":
          description: Request body exceeded the 1 MB size limit. Split larger payloads into multiple requests.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionErrorResponseDto"
        "429":
          description: Request was throttled due to abusive or excessive traffic.
          headers:
            Retry-After:
              description: Seconds until the client should retry the request.
              schema:
                type: string
                example: "300"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionErrorResponseDto"
        "500":
          description: Persistence or queueing failure.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmissionFailureResponseDto"
      tags:
        - Public Submission
components:
  schemas:
    SubmissionSubmitRequestDto:
      type: object
      properties:
        timestamp:
          type: number
          example: 1712345678
        device:
          type: object
          additionalProperties: true
          example:
            type: ewon
            id: device-123
            serial: serial-123
            uptime_millis: 123456
            lan_ip: 10.0.0.10
            wan_ip: 198.51.100.10
        tags:
          type: array
          items:
            type: object
            additionalProperties: true
          example:
            - name: temperature
              value: "22.5"
              type: 1
              unit: celsius
              last_change_timestamp: 1712345678
      required:
        - timestamp
        - device
        - tags
    SubmissionSuccessResponseDto:
      type: object
      properties:
        success:
          type: boolean
          example: true
      required:
        - success
    SubmissionErrorResponseDto:
      type: object
      properties:
        statusCode:
          type: number
          example: 401
        error:
          type: string
          example: Unauthorized
        message:
          type: string
          example: Incorrect Request Type
      required:
        - statusCode
        - error
        - message
    SubmissionFailureResponseDto:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: An error occurred persisting data submission.
      required:
        - success
        - message
