openapi: 3.0.3
info:
  title: BATbern Event Notifications API
  version: 1.0.0
  description: 'In-app notification management — listing, read-state, delivery history, deletion,
    and unread counts (Story BAT-7).


    Authored during the API consolidation adversarial-review follow-up (2026-06-30) to bring the
    previously hand-rolled NotificationController under the contract-first standard (ADR-013). Paths
    and wire shapes preserved verbatim.'
  contact:
    name: BATbern Platform Team
    email: platform@batbern.ch
  license:
    name: Proprietary
servers:
- url: https://api.batbern.ch/api/v1
  description: Production
- url: https://api.batbern.ch/api/v1
  description: Staging
- url: http://localhost:8080/api/v1
  description: Development
security:
- BearerAuth: []
tags:
- name: Notifications
  description: In-app notification inbox — list, read-state, history, deletion, counts (Story BAT-7)
paths:
  /notifications:
    get:
      tags:
      - Notifications
      operationId: listNotifications
      summary: List notifications for a user (paginated, 1-based)
      parameters:
      - name: username
        in: query
        required: true
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
        description: Optional status filter (e.g. UNREAD, READ). Case-insensitive.
      - name: page
        in: query
        required: false
        schema:
          type: integer
        description: 1-based page number (default 1)
      - name: limit
        in: query
        required: false
        schema:
          type: integer
        description: Page size (default per PaginationUtils)
      responses:
        '200':
          description: Paginated notifications
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationsResponse'
  /notifications/count:
    get:
      tags:
      - Notifications
      operationId: getUnreadCount
      summary: Count notifications by status (defaults to UNREAD)
      parameters:
      - name: username
        in: query
        required: true
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
          default: UNREAD
      responses:
        '200':
          description: Notification count
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationCountResponse'
  /notifications/{id}/read:
    put:
      tags:
      - Notifications
      operationId: markAsRead
      summary: Mark a single notification as read
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Notification marked as read
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarkAsReadResponse'
        '404':
          description: Notification not found
  /notifications/batch-read:
    put:
      tags:
      - Notifications
      operationId: batchMarkAsRead
      summary: Mark multiple notifications as read
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchOperationRequest'
      responses:
        '200':
          description: Notifications marked as read
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarkAsReadResponse'
  /notifications/history:
    get:
      tags:
      - Notifications
      operationId: getDeliveryHistory
      summary: Delivery history for a user by channel
      parameters:
      - name: username
        in: query
        required: true
        schema:
          type: string
      - name: channel
        in: query
        required: true
        schema:
          type: string
        description: Delivery channel (e.g. EMAIL, IN_APP). Case-insensitive.
      responses:
        '200':
          description: Notification delivery history (newest first)
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/NotificationResponse'
  /notifications/{id}:
    delete:
      tags:
      - Notifications
      operationId: deleteNotification
      summary: Delete a single notification
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Notification deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteNotificationResponse'
        '404':
          description: Notification not found
  /notifications/batch-delete:
    delete:
      tags:
      - Notifications
      operationId: batchDelete
      summary: Delete multiple notifications
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchOperationRequest'
      responses:
        '200':
          description: Notifications deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteNotificationResponse'
components:
  schemas:
    NotificationResponse:
      type: object
      description: A single in-app notification. Null fields are serialized (not omitted).
      properties:
        id:
          type: string
          format: uuid
        recipientUsername:
          type: string
        eventCode:
          type: string
          nullable: true
        notificationType:
          type: string
        channel:
          type: string
        priority:
          type: string
        subject:
          type: string
          nullable: true
        body:
          type: string
          nullable: true
        status:
          type: string
        sentAt:
          type: string
          format: date-time
          nullable: true
        readAt:
          type: string
          format: date-time
          nullable: true
        failedAt:
          type: string
          format: date-time
          nullable: true
        failureReason:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
          nullable: true
        createdAt:
          type: string
          format: date-time
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
    NotificationsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/NotificationResponse'
        pagination:
          $ref: '#/components/schemas/NotificationPagination'
    NotificationPagination:
      type: object
      description: 1-based pagination metadata (notification inbox wire — page/limit/totalItems/totalPages only).
      properties:
        page:
          type: integer
        limit:
          type: integer
        totalItems:
          type: integer
          format: int64
        totalPages:
          type: integer
    NotificationCountResponse:
      type: object
      properties:
        count:
          type: integer
          format: int64
    MarkAsReadResponse:
      type: object
      properties:
        success:
          type: boolean
        markedCount:
          type: integer
        updatedAt:
          type: string
          format: date-time
    DeleteNotificationResponse:
      type: object
      properties:
        success:
          type: boolean
    BatchOperationRequest:
      type: object
      required:
      - notificationIds
      properties:
        notificationIds:
          type: array
          items:
            type: string
            format: uuid
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: AWS Cognito JWT token
