openapi: 3.0.0

info:
    title: Devocean Whale Detection API
    description: Public API for retrieving whale detection data.
    version: 1.0.0

security:
    - ApiKeyAuth: []

tags:
    - name: Whale Detections
      description: Endpoints related to whale detection data

components:
    securitySchemes:
        ApiKeyAuth:
            type: apiKey
            in: header
            name: x-api-key
            description: |
                Send your API key in the header named `x-api-key`.

                Use the header name exactly as `x-api-key` or `X-Api-Key` in your client configuration.

                Example:
                `x-api-key: your_api_key_here`
    parameters:
        PageParam:
            name: page
            in: query
            description: Page number. Defaults to `1`.
            schema:
                type: integer
                minimum: 1
                default: 1
        LimitParam:
            name: limit
            in: query
            description: Number of records per page. Defaults to `50`.
            schema:
                type: integer
                minimum: 1
                default: 50
        SortParam:
            name: sort
            in: query
            description: Sort field. Only the documented values are accepted.
            schema:
                type: string
                enum:
                    - whale_type
                    - prediction
                    - time_recorded
                    - validated
                default: time_recorded
        OrderParam:
            name: order
            in: query
            description: Sort direction. Defaults to `desc`.
            schema:
                type: string
                enum:
                    - asc
                    - desc
                default: desc
    schemas:
        WhaleDetection:
            type: object
            required:
                - lat
                - lng
                - timeRecorded
                - whaleType
                - prediction
                - rmse
                - validated
            properties:
                lat:
                    type: number
                    example: 44.6488
                lng:
                    type: number
                    example: -63.5752
                timeRecorded:
                    type: string
                    format: date-time
                    example: '2026-03-23T14:52:10.000Z'
                whaleType:
                    type: string
                    example: NARW
                prediction:
                    type: number
                    example: 0.9821
                rmse:
                    type: number
                    example: 0.0417
                validated:
                    type: boolean
                    example: false
                buoyId:
                    type: integer
                    nullable: true
                    description: May be absent or null depending on the selected fields returned by the endpoint.
                    example: 42
                spectogramKey:
                    type: string
                    nullable: true
                    example: detections/example-spectogram.png
                id:
                    type: string
                    format: uuid
                    description: May be absent depending on the selected fields returned by the endpoint.
                    example: 2da9fce5-c9c1-4a17-8667-bf7f6caed91f
        WhaleDetectionPagination:
            type: object
            required:
                - page
                - limit
                - total
                - totalPages
            properties:
                page:
                    type: integer
                    example: 1
                limit:
                    type: integer
                    example: 50
                total:
                    type: integer
                    example: 231
                totalPages:
                    type: integer
                    example: 5
        WhaleDetectionsResponse:
            type: object
            required:
                - data
                - pagination
            properties:
                data:
                    type: array
                    items:
                        $ref: '#/components/schemas/WhaleDetection'
                pagination:
                    $ref: '#/components/schemas/WhaleDetectionPagination'
        ErrorResponse:
            type: object
            required:
                - message
            properties:
                message:
                    type: string
                    example: Unauthorized access

paths:
    /whale-detections:
        get:
            tags:
                - Whale Detections
            summary: Get whale detections
            operationId: listWhaleDetections
            security:
                - ApiKeyAuth: []
            description: |
                Retrieves whale detections with pagination and optional sorting.

                Authentication is required. Send your API key in the `x-api-key` header.
                
                Use the exact header name shown here, because the header is case-sensitive.

                Example:

                ```bash
                curl -H "x-api-key: your_api_key_here" "/whale-detections?page=1&limit=50&sort=time_recorded&order=desc"
                ```
            parameters:
                - $ref: '#/components/parameters/PageParam'
                - $ref: '#/components/parameters/LimitParam'
                - $ref: '#/components/parameters/SortParam'
                - $ref: '#/components/parameters/OrderParam'
            responses:
                '200':
                    description: Whale detections returned successfully.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/WhaleDetectionsResponse'
                            examples:
                                success:
                                    value:
                                        data:
                                            - lat: 44.6488
                                              lng: -63.5752
                                              timeRecorded: '2026-03-23T14:52:10.000Z'
                                              whaleType: NARW
                                              prediction: 0.9821
                                              rmse: 0.0417
                                              validated: false
                                        pagination:
                                            page: 1
                                            limit: 50
                                            total: 231
                                            totalPages: 5
                '401':
                    description: Missing API key, invalid API key, or invalid sort value.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ErrorResponse'
                            examples:
                                missingApiKey:
                                    summary: Header not provided
                                    value:
                                        message: Unauthorized access
                                invalidApiKey:
                                    summary: API key is not valid
                                    value:
                                        message: Invalid Token
                                invalidSort:
                                    summary: Unsupported sort field
                                    value:
                                        message: Invalid sort
                '500':
                    description: Internal server error.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ErrorResponse'
                            example:
                                message: Internal Server Error
