openapi: 3.0.3
info:
  title: NovaTrek Guide Management Service
  description: |
    Manages adventure guides for NovaTrek Adventures, including guide profiles,
    certifications, scheduling, availability windows, and guest performance ratings.
    
    This service is the authoritative source for guide data and coordinates with
    svc-trip-catalog for trip assignments and svc-reservations for guest rating linkage.
  version: 2.4.0
  contact:
    name: NovaTrek Platform Engineering
    email: platform-eng@novatrek.example.com
    url: https://developer.novatrek.example.com
  license:
    name: Proprietary
    url: https://novatrek.example.com/legal/api-license

servers:
  - url: https://api.novatrek.example.com/guides/v1
    description: Production
  - url: https://api.staging.novatrek.example.com/guides/v1
    description: Staging
  - url: https://api.dev.novatrek.example.com/guides/v1
    description: Development

tags:
  - name: Guides
    description: Guide profile management
  - name: Certifications
    description: Guide certification records
  - name: Scheduling
    description: Trip assignments and schedule
  - name: Availability
    description: Guide availability windows
  - name: Ratings
    description: Guest ratings and reviews

paths:
  /guides:
    get:
      operationId: searchGuides
      summary: Search guides with filters
      description: Returns a paginated list of guides matching the specified filter criteria.
      tags:
        - Guides
      parameters:
        - name: certification
          in: query
          description: Filter by certification type held by the guide.
          schema:
            type: string
            example: swift_water_rescue
        - name: activity_type
          in: query
          description: Filter by activity specialization (e.g., kayaking, rock_climbing).
          schema:
            type: string
            example: rock_climbing
        - name: region
          in: query
          description: Filter by assigned region identifier.
          schema:
            type: string
            example: pacific_northwest
        - name: availability_date
          in: query
          description: Filter to guides available on this date.
          schema:
            type: string
            format: date
            example: "2026-07-15"
        - name: status
          in: query
          description: Filter by guide status.
          schema:
            $ref: '#/components/schemas/GuideStatus'
        - $ref: '#/components/parameters/PageOffset'
        - $ref: '#/components/parameters/PageLimit'
      responses:
        '200':
          description: Paginated list of guides matching the filters.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Guide'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      operationId: createGuide
      summary: Create a new guide profile
      description: Registers a new adventure guide in the system.
      tags:
        - Guides
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GuideCreateRequest'
      responses:
        '201':
          description: Guide created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Guide'
          headers:
            Location:
              description: URI of the newly created guide resource.
              schema:
                type: string
                format: uri
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: Conflict - a guide with the same email already exists.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /guides/{guide_id}:
    parameters:
      - $ref: '#/components/parameters/GuideId'
    get:
      operationId: getGuide
      summary: Get guide by ID
      description: Retrieves the full profile for a specific guide.
      tags:
        - Guides
      responses:
        '200':
          description: Guide profile returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Guide'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

    patch:
      operationId: updateGuide
      summary: Update guide profile
      description: Partially updates a guide profile. Only provided fields are modified.
      tags:
        - Guides
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GuideUpdateRequest'
      responses:
        '200':
          description: Guide updated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Guide'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /guides/{guide_id}/certifications:
    parameters:
      - $ref: '#/components/parameters/GuideId'
    get:
      operationId: getGuideCertifications
      summary: List guide certifications
      description: Returns all certifications held by the specified guide.
      tags:
        - Certifications
      responses:
        '200':
          description: List of certifications.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/GuideCertification'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

    post:
      operationId: addGuideCertification
      summary: Add a certification to a guide
      description: Records a new certification for the specified guide.
      tags:
        - Certifications
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GuideCertificationCreateRequest'
      responses:
        '201':
          description: Certification added successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuideCertification'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Duplicate certification record.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /guides/{guide_id}/schedule:
    parameters:
      - $ref: '#/components/parameters/GuideId'
    get:
      operationId: getGuideSchedule
      summary: Get upcoming trip assignments
      description: |
        Returns the guide's upcoming scheduled trip assignments.
        Trip details reference svc-trip-catalog trip identifiers.
      tags:
        - Scheduling
      parameters:
        - name: from_date
          in: query
          description: Start of date range filter (inclusive). Defaults to today.
          schema:
            type: string
            format: date
        - name: to_date
          in: query
          description: End of date range filter (inclusive). Defaults to 90 days from today.
          schema:
            type: string
            format: date
      responses:
        '200':
          description: List of scheduled trip assignments.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/GuideScheduleEntry'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /guides/{guide_id}/availability:
    parameters:
      - $ref: '#/components/parameters/GuideId'
    get:
      operationId: getGuideAvailability
      summary: Get guide availability windows
      description: Returns the availability windows configured for this guide.
      tags:
        - Availability
      parameters:
        - name: from_date
          in: query
          description: Filter windows starting on or after this date.
          schema:
            type: string
            format: date
        - name: to_date
          in: query
          description: Filter windows ending on or before this date.
          schema:
            type: string
            format: date
      responses:
        '200':
          description: List of availability windows.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AvailabilityWindow'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

    post:
      operationId: setGuideAvailability
      summary: Set availability windows
      description: Creates or updates availability windows for the guide.
      tags:
        - Availability
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AvailabilityWindowCreateRequest'
      responses:
        '201':
          description: Availability window created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AvailabilityWindow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /guides/{guide_id}/ratings:
    parameters:
      - $ref: '#/components/parameters/GuideId'
    get:
      operationId: getGuideRatings
      summary: Get guest ratings and reviews
      description: Returns paginated guest ratings and reviews for the specified guide.
      tags:
        - Ratings
      parameters:
        - $ref: '#/components/parameters/PageOffset'
        - $ref: '#/components/parameters/PageLimit'
        - name: min_rating
          in: query
          description: Filter to ratings at or above this value.
          schema:
            type: integer
            minimum: 1
            maximum: 5
      responses:
        '200':
          description: Paginated list of ratings.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/GuideRating'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

    post:
      operationId: submitGuideRating
      summary: Submit a guest rating
      description: |
        Records a guest rating and optional review for a guide.
        The reservation_id links to svc-reservations to validate the guest participated.
      tags:
        - Ratings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GuideRatingCreateRequest'
      responses:
        '201':
          description: Rating submitted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuideRating'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Guest has already rated this guide for the given reservation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /guides/available:
    get:
      operationId: findAvailableGuides
      summary: Find available guides for a date, activity, and region
      description: |
        Searches for guides who are available on the specified date, hold relevant
        certifications for the activity type, and are assigned to the given region.
      tags:
        - Availability
      parameters:
        - name: date
          in: query
          required: true
          description: The date to check availability for.
          schema:
            type: string
            format: date
            example: "2026-08-20"
        - name: activity_type
          in: query
          required: true
          description: The type of activity the guide must be qualified for.
          schema:
            type: string
            example: whitewater_rafting
        - name: region
          in: query
          required: true
          description: The region identifier where the trip will take place.
          schema:
            type: string
            example: rocky_mountain
        - name: min_experience_years
          in: query
          description: Minimum years of experience required.
          schema:
            type: integer
            minimum: 0
        - name: min_rating
          in: query
          description: Minimum average rating threshold.
          schema:
            type: number
            format: float
            minimum: 1.0
            maximum: 5.0
      responses:
        '200':
          description: List of available guides matching criteria.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Guide'
                  match_count:
                    type: integer
                    description: Total number of matching guides.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

components:
  parameters:
    GuideId:
      name: guide_id
      in: path
      required: true
      description: Unique identifier for the guide.
      schema:
        type: string
        format: uuid
        example: "d4f7a2c1-89b3-4e6f-a1d0-3c5e7b9f0a12"

    PageOffset:
      name: offset
      in: query
      description: Number of records to skip for pagination.
      schema:
        type: integer
        minimum: 0
        default: 0

    PageLimit:
      name: limit
      in: query
      description: Maximum number of records to return.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25

  schemas:
    GuideStatus:
      type: string
      enum:
        - ACTIVE
        - ON_LEAVE
        - TRAINING
        - SUSPENDED
        - TERMINATED
      description: Current operational status of the guide.

    EmergencyTrainingLevel:
      type: string
      enum:
        - WILDERNESS_FIRST_AID
        - WILDERNESS_FIRST_RESPONDER
        - WILDERNESS_EMT
        - PARAMEDIC
      description: Highest level of emergency/medical training completed.

    GuideRole:
      type: string
      enum:
        - LEAD
        - ASSISTANT
        - TRAINEE
      description: Role the guide fulfills on a trip assignment.

    Guide:
      type: object
      required:
        - id
        - first_name
        - last_name
        - email
        - region_ids
        - status
      properties:
        id:
          type: string
          format: uuid
          description: Unique guide identifier.
          example: "d4f7a2c1-89b3-4e6f-a1d0-3c5e7b9f0a12"
        first_name:
          type: string
          description: Guide's first name.
          example: Maya
        last_name:
          type: string
          description: Guide's last name.
          example: Hernandez
        email:
          type: string
          format: email
          description: Guide's email address.
          example: maya.hernandez@novatrek.example.com
        phone:
          type: string
          description: Guide's contact phone number.
          example: "+1-541-555-0192"
        region_ids:
          type: array
          items:
            type: string
          description: Region identifiers where this guide operates.
          example:
            - pacific_northwest
            - rocky_mountain
        certifications:
          type: array
          items:
            type: string
          description: List of certification type codes held by the guide.
          example:
            - swift_water_rescue
            - avalanche_level_2
            - leave_no_trace_master
        activity_specialties:
          type: array
          items:
            type: string
          description: Activity types this guide specializes in.
          example:
            - whitewater_rafting
            - kayaking
            - rock_climbing
        years_experience:
          type: integer
          minimum: 0
          description: Total years of guiding experience.
          example: 8
        max_group_size:
          type: integer
          minimum: 1
          description: Maximum group size this guide is approved to lead.
          example: 12
        status:
          $ref: '#/components/schemas/GuideStatus'
        average_rating:
          type: number
          format: float
          minimum: 1.0
          maximum: 5.0
          description: Average guest rating (read-only, computed).
          readOnly: true
          example: 4.7
        total_trips_led:
          type: integer
          minimum: 0
          description: Total number of trips led (read-only, computed).
          readOnly: true
          example: 342
        emergency_training_level:
          $ref: '#/components/schemas/EmergencyTrainingLevel'
        languages:
          type: array
          items:
            type: string
          description: Languages the guide speaks (ISO 639-1 codes).
          example:
            - en
            - es
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: Timestamp when the guide profile was created.
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: Timestamp of the last profile update.

    GuideCreateRequest:
      type: object
      required:
        - first_name
        - last_name
        - email
        - region_ids
        - emergency_training_level
      properties:
        first_name:
          type: string
          example: Kai
        last_name:
          type: string
          example: Nakamura
        email:
          type: string
          format: email
          example: kai.nakamura@novatrek.example.com
        phone:
          type: string
          example: "+1-406-555-0234"
        region_ids:
          type: array
          items:
            type: string
          example:
            - rocky_mountain
        activity_specialties:
          type: array
          items:
            type: string
          example:
            - backcountry_skiing
            - mountaineering
        years_experience:
          type: integer
          minimum: 0
          example: 3
        max_group_size:
          type: integer
          minimum: 1
          example: 8
        emergency_training_level:
          $ref: '#/components/schemas/EmergencyTrainingLevel'
        languages:
          type: array
          items:
            type: string
          example:
            - en
            - ja

    GuideUpdateRequest:
      type: object
      description: Partial update - only include fields to modify.
      properties:
        first_name:
          type: string
        last_name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        region_ids:
          type: array
          items:
            type: string
        activity_specialties:
          type: array
          items:
            type: string
        years_experience:
          type: integer
          minimum: 0
        max_group_size:
          type: integer
          minimum: 1
        status:
          $ref: '#/components/schemas/GuideStatus'
        emergency_training_level:
          $ref: '#/components/schemas/EmergencyTrainingLevel'
        languages:
          type: array
          items:
            type: string

    GuideCertification:
      type: object
      required:
        - certification_type
        - issued_date
        - issuing_body
        - certificate_number
        - status
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
          description: Unique certification record identifier.
        guide_id:
          type: string
          format: uuid
          readOnly: true
        certification_type:
          type: string
          description: Type code of the certification.
          example: swift_water_rescue
        issued_date:
          type: string
          format: date
          description: Date the certification was issued.
          example: "2024-03-15"
        expiry_date:
          type: string
          format: date
          description: Date the certification expires. Null if no expiry.
          nullable: true
          example: "2027-03-15"
        issuing_body:
          type: string
          description: Organization that issued the certification.
          example: American Canoe Association
        certificate_number:
          type: string
          description: Unique certificate number from the issuing body.
          example: ACA-SWR-2024-08817
        status:
          type: string
          enum:
            - VALID
            - EXPIRED
            - REVOKED
            - PENDING_RENEWAL
          description: Current status of the certification.

    GuideCertificationCreateRequest:
      type: object
      required:
        - certification_type
        - issued_date
        - issuing_body
        - certificate_number
      properties:
        certification_type:
          type: string
          example: avalanche_level_2
        issued_date:
          type: string
          format: date
          example: "2025-11-01"
        expiry_date:
          type: string
          format: date
          nullable: true
          example: "2028-11-01"
        issuing_body:
          type: string
          example: Canadian Avalanche Association
        certificate_number:
          type: string
          example: CAA-AVL2-2025-44291

    GuideScheduleEntry:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        guide_id:
          type: string
          format: uuid
        trip_id:
          type: string
          format: uuid
          description: References a trip in svc-trip-catalog.
        trip_name:
          type: string
          description: Display name of the trip (denormalized from svc-trip-catalog).
          example: "Snake River Whitewater Adventure"
        departure_date:
          type: string
          format: date
          description: Scheduled departure date for the trip.
          example: "2026-07-22"
        return_date:
          type: string
          format: date
          description: Scheduled return date for the trip.
          example: "2026-07-25"
        role:
          $ref: '#/components/schemas/GuideRole'
        group_size:
          type: integer
          description: Current number of guests booked on this trip.
          example: 9

    AvailabilityWindow:
      type: object
      required:
        - guide_id
        - start_date
        - end_date
        - available
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        guide_id:
          type: string
          format: uuid
          description: The guide this availability window belongs to.
        start_date:
          type: string
          format: date
          description: Start of the availability window (inclusive).
          example: "2026-07-01"
        end_date:
          type: string
          format: date
          description: End of the availability window (inclusive).
          example: "2026-07-31"
        available:
          type: boolean
          description: Whether the guide is available (true) or blocked (false) during this window.
          example: true
        notes:
          type: string
          description: Optional notes about the availability window.
          example: "Available for multi-day rafting trips only"

    AvailabilityWindowCreateRequest:
      type: object
      required:
        - start_date
        - end_date
        - available
      properties:
        start_date:
          type: string
          format: date
          example: "2026-08-01"
        end_date:
          type: string
          format: date
          example: "2026-08-31"
        available:
          type: boolean
          example: true
        notes:
          type: string
          example: "Prefer day trips this month"

    GuideRating:
      type: object
      required:
        - reservation_id
        - guest_id
        - rating
        - date
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        guide_id:
          type: string
          format: uuid
          readOnly: true
        reservation_id:
          type: string
          format: uuid
          description: References a reservation in svc-reservations.
        guest_id:
          type: string
          format: uuid
          description: Identifier of the guest who submitted the rating.
        rating:
          type: integer
          minimum: 1
          maximum: 5
          description: Rating score from 1 (poor) to 5 (excellent).
          example: 5
        review_text:
          type: string
          maxLength: 2000
          description: Optional free-text review from the guest.
          nullable: true
          example: "Maya was an incredible guide - kept us safe through Class IV rapids while making sure everyone had a blast."
        date:
          type: string
          format: date
          description: Date the rating was submitted.
          example: "2026-07-28"

    GuideRatingCreateRequest:
      type: object
      required:
        - reservation_id
        - guest_id
        - rating
      properties:
        reservation_id:
          type: string
          format: uuid
        guest_id:
          type: string
          format: uuid
        rating:
          type: integer
          minimum: 1
          maximum: 5
          example: 4
        review_text:
          type: string
          maxLength: 2000
          nullable: true
          example: "Great experience on the mountain trail. Very knowledgeable about local wildlife."

    Pagination:
      type: object
      properties:
        offset:
          type: integer
          description: Current offset.
          example: 0
        limit:
          type: integer
          description: Page size.
          example: 25
        total:
          type: integer
          description: Total number of matching records.
          example: 47
        has_more:
          type: boolean
          description: Whether additional pages exist beyond the current result set.
          example: true

    ErrorResponse:
      type: object
      required:
        - error_code
        - message
      properties:
        error_code:
          type: string
          description: Machine-readable error code.
          example: GUIDE_NOT_FOUND
        message:
          type: string
          description: Human-readable error description.
          example: "No guide found with the specified identifier."
        details:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
                example: email
              reason:
                type: string
                example: "Invalid email format."
          description: Field-level validation errors, if applicable.
        request_id:
          type: string
          format: uuid
          description: Correlation ID for support and debugging.

  responses:
    BadRequest:
      description: Invalid request parameters or body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

    Unauthorized:
      description: Authentication credentials missing or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

    NotFound:
      description: The requested resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token issued by NovaTrek identity service.

security:
  - BearerAuth: []
