openapi: 3.1.0
info:
  title: Event Tracking API
  version: 1.0.0
  description: |
    Flexible API for ingesting analytics and tracking events.
    Supports single and bulk event ingestion.
    Each request must include a valid API key in the `Authorization` header.
    Each event includes a unique `messageId` for deduplication and traceability.

servers:
  - url: https://{host}/v1
    description: Base URL determined at deployment time
    variables:
      host:
        default: localhost:8080
        description: The host name or domain of the deployment.

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: |
        Include your API key as:
        ```
        Authorization: Bearer YOUR_API_KEY
        ```

  schemas:
    Event:
      type: object
      required:
        - event
        - properties
        - timestamp
      additionalProperties: true
      properties:
        messageId:
          type: string
          description: >
            Unique identifier for this event.  
            If not provided by the client, the server will generate one automatically.  
            Used for deduplication and traceability through downstream systems.
          example: "8b0f62f9-1e8e-4f15-8c2a-9d23c9c6c0e2"
        event:
          type: string
          description: The name/type of the event.
          example: "signup"
        timestamp:
          type: string
          format: date-time
          description: When the event occurred.
          example: "2025-10-29T22:00:00.778Z"
        properties:
          type: object
          description: Event-specific key/value pairs.
          additionalProperties: true
          example:
            plan: "basic"
            accountType: "email"
            freeTrial: true

    BulkEventRequest:
      type: array
      items:
        $ref: "#/components/schemas/Event"
      minItems: 1
      description: List of events to be tracked in bulk.

  responses:
    Success:
      description: Request accepted and processed successfully.
      content:
        application/json:
          schema:
            oneOf:
              - type: object
                description: Response for a single event.
                properties:
                  status:
                    type: string
                    example: "ok"
                  messageId:
                    type: string
                    description: Unique ID assigned to the processed event.
                    example: "8b0f62f9-1e8e-4f15-8c2a-9d23c9c6c0e2"
              - type: object
                description: Response for a bulk request.
                properties:
                  status:
                    type: string
                    example: "ok"
                  messageIds:
                    type: array
                    description: List of message IDs corresponding to successfully processed events.
                    items:
                      type: string
                    example:
                      - "8b0f62f9-1e8e-4f15-8c2a-9d23c9c6c0e2"
                      - "ef32acb1-9b9f-4ac8-a2e0-c6a3c91e7761"

    BadRequest:
      description: Invalid request payload.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Invalid event format."

    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Unauthorized"

    PayloadTooLarge:
      description: Request body too large.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Payload exceeds maximum allowed size (10MB)."

    TooManyRequests:
      description: Too many requests; rate limit exceeded.
      headers:
        Retry-After:
          description: Number of seconds until the client can retry.
          schema:
            type: integer
            example: 30
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Rate limit exceeded. Please retry later."

    InternalServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Internal server error. Please try again later."

security:
  - ApiKeyAuth: []

paths:
  /track:
    post:
      summary: Track a single event
      description: |
        Accepts a single event object and records it for ingestion.  
        If `messageId` is not provided, the server will generate one automatically.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Event"
      responses:
        "200":
          $ref: "#/components/responses/Success"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "413":
          $ref: "#/components/responses/PayloadTooLarge"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"

  /bulk-track:
    post:
      summary: Track multiple events in bulk
      description: |
        Accepts an array of event objects and records them in bulk.
        Clients may optionally gzip the request body.
        The total uncompressed request size must not exceed 10 MB.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BulkEventRequest"
      responses:
        "200":
          $ref: "#/components/responses/Success"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "413":
          $ref: "#/components/responses/PayloadTooLarge"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"

