openapi: 3.0.3
info:
  title: NovaTrek Partner Integrations Service
  description: |
    Manages third-party partner relationships and bookings from travel agents,
    tour operators, online travel agencies (OTAs), and corporate accounts.
    Handles commission tracking, booking reconciliation, and partner lifecycle.
  version: 1.0.0
  contact:
    name: NovaTrek Partnerships Team
    email: partnerships@novatrek.example.com

servers:
  - url: https://api.novatrek.example.com/partners/v1
    description: Production

security:
  - BearerAuth: []

paths:
  /partner-bookings:
    post:
      operationId: createPartnerBooking
      summary: External partner creates a booking
      description: |
        Allows an authenticated partner to submit a booking request. Creates
        a corresponding reservation in svc-reservations and applies the
        partner's commission rate.
      tags: [Partner Bookings]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerBookingCreate'
      responses:
        '201':
          description: Partner booking created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Partner account is suspended or inactive
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /partner-bookings/{booking_id}:
    get:
      operationId: getPartnerBooking
      summary: Get partner booking details
      tags: [Partner Bookings]
      parameters:
        - $ref: '#/components/parameters/BookingIdPath'
      responses:
        '200':
          description: Partner booking details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerBooking'
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'
    patch:
      operationId: updatePartnerBooking
      summary: Update a partner booking
      tags: [Partner Bookings]
      parameters:
        - $ref: '#/components/parameters/BookingIdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerBookingUpdate'
      responses:
        '200':
          description: Partner booking updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /partner-bookings/{booking_id}/confirm:
    post:
      operationId: confirmPartnerBooking
      summary: Confirm a pending partner booking
      description: |
        Confirms availability and finalizes the partner booking. Triggers
        reservation confirmation in svc-reservations and sends confirmation
        to the partner's callback URL.
      tags: [Partner Bookings]
      parameters:
        - $ref: '#/components/parameters/BookingIdPath'
      responses:
        '200':
          description: Booking confirmed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerBooking'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Booking not in confirmable state or availability changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /partners:
    get:
      operationId: listPartners
      summary: List registered partners
      tags: [Partners]
      parameters:
        - name: type
          in: query
          schema:
            $ref: '#/components/schemas/PartnerType'
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/PartnerStatus'
        - name: limit
          in: query
          schema:
            type: integer
            default: 25
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: List of partners
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerList'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: registerPartner
      summary: Register a new partner
      tags: [Partners]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerCreate'
      responses:
        '201':
          description: Partner registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Partner'
        '400':
          $ref: '#/components/responses/BadRequest'
        '409':
          description: Partner with this name or contact email already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /partners/{partner_id}/commission-report:
    get:
      operationId: getCommissionReport
      summary: Get commission report for a partner
      tags: [Partners]
      parameters:
        - $ref: '#/components/parameters/PartnerIdPath'
        - name: start_date
          in: query
          required: true
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          required: true
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Commission report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommissionReport'
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  parameters:
    BookingIdPath:
      name: booking_id
      in: path
      required: true
      schema:
        type: string
        format: uuid
    PartnerIdPath:
      name: partner_id
      in: path
      required: true
      schema:
        type: string
        format: uuid

  schemas:
    PartnerBooking:
      type: object
      required: [id, partner_id, external_reference, status, commission_rate]
      properties:
        id:
          type: string
          format: uuid
        partner_id:
          type: string
          format: uuid
        external_reference:
          type: string
          description: Partner's own booking reference number
          example: "TRV-2026-884421"
        reservation_id:
          type: string
          format: uuid
          description: References reservation in svc-reservations (set after confirmation)
        status:
          $ref: '#/components/schemas/BookingStatus'
        commission_rate:
          type: number
          format: float
          minimum: 0
          maximum: 1
          example: 0.12
          description: Commission rate as decimal (0.12 = 12%)
        commission_amount:
          type: number
          format: float
          description: Calculated commission in USD
          example: 48.00
        booking_total:
          type: number
          format: float
          example: 400.00
        activity_id:
          type: string
          format: uuid
        trip_date:
          type: string
          format: date
        participant_count:
          type: integer
          minimum: 1
        created_at:
          type: string
          format: date-time
        confirmed_at:
          type: string
          format: date-time

    PartnerBookingCreate:
      type: object
      required: [partner_id, external_reference, activity_id, trip_date, participant_count]
      properties:
        partner_id:
          type: string
          format: uuid
        external_reference:
          type: string
        activity_id:
          type: string
          format: uuid
        trip_date:
          type: string
          format: date
        participant_count:
          type: integer
          minimum: 1
        special_requests:
          type: string
          maxLength: 500

    PartnerBookingUpdate:
      type: object
      properties:
        trip_date:
          type: string
          format: date
        participant_count:
          type: integer
          minimum: 1
        special_requests:
          type: string
          maxLength: 500

    BookingStatus:
      type: string
      enum: [PENDING, CONFIRMED, CANCELLED, COMPLETED, DISPUTED]

    Partner:
      type: object
      required: [id, name, type, commission_rate, status]
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: "Summit Trail Travel Agency"
        type:
          $ref: '#/components/schemas/PartnerType'
        api_key_hash:
          type: string
          description: SHA-256 hash of partner API key (write-only on creation)
        commission_rate:
          type: number
          format: float
          example: 0.10
        status:
          $ref: '#/components/schemas/PartnerStatus'
        contact_email:
          type: string
          format: email
        callback_url:
          type: string
          format: uri
          description: Webhook URL for booking status notifications
        created_at:
          type: string
          format: date-time

    PartnerCreate:
      type: object
      required: [name, type, commission_rate, contact_email]
      properties:
        name:
          type: string
        type:
          $ref: '#/components/schemas/PartnerType'
        commission_rate:
          type: number
          format: float
        contact_email:
          type: string
          format: email
        callback_url:
          type: string
          format: uri

    PartnerList:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Partner'
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer

    PartnerType:
      type: string
      enum: [TRAVEL_AGENT, TOUR_OPERATOR, OTA, CORPORATE_ACCOUNT]

    PartnerStatus:
      type: string
      enum: [ACTIVE, SUSPENDED, PENDING_APPROVAL, INACTIVE]

    CommissionReport:
      type: object
      required: [partner_id, period_start, period_end]
      properties:
        partner_id:
          type: string
          format: uuid
        period_start:
          type: string
          format: date
        period_end:
          type: string
          format: date
        total_bookings:
          type: integer
        total_revenue:
          type: number
          format: float
        total_commission:
          type: number
          format: float
        line_items:
          type: array
          items:
            $ref: '#/components/schemas/CommissionLineItem'

    CommissionLineItem:
      type: object
      properties:
        booking_id:
          type: string
          format: uuid
        external_reference:
          type: string
        trip_date:
          type: string
          format: date
        booking_total:
          type: number
          format: float
        commission_rate:
          type: number
          format: float
        commission_amount:
          type: number
          format: float

    ErrorResponse:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: object
          additionalProperties: true

  responses:
    BadRequest:
      description: Invalid request payload
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid JWT token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
