📄 OpenAPI Specification

Happy Campers AI Agent API v1.0.0
openapi: 3.0.3
info:
  title: Happy Campers AI Agent API
  description: |
    API for AI agents to discover vehicle availability and pricing for the Happy Campers booking system.

    ## Workflow

    1. **Discover Depots**: GET `/depots` to get available pickup/dropoff locations
    2. **Check Availability**: GET `/vehicles/availability` with dates and locations to get available vehicles
    3. **Discover Options**: For a chosen vehicle, get accessories and insurance options:
       - GET `/vehicles/{vehicleId}/accessories`
       - GET `/vehicles/{vehicleId}/insurance-types`
    4. **Get Quote**: GET `/quotes` with vehicle and selected options for final pricing
    5. **Direct Website Query**: AI Agents can also query vehicle availability directly on the website by appending search parameters to the `/book` URL. Example: `/book?pick_up_depot_id=1&drop_off_depot_id=1&pick_up_date=YYYY-MM-DD&drop_off_date=YYYY-MM-DD`
  version: 1.0.0
  contact:
    name: Happy Campers API Support

servers:
  - url: https://www.happycampers.co.nz/api/agent
    description: Happy Campers AI Agent API

paths:
  /depots:
    get:
      summary: Get all available depot locations
      description: Returns a list of all active depot locations with their operating hours
      tags:
        - Discovery
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Depot"
              example:
                - id: 1
                  name: "Auckland Airport"
                  pickup_times:
                    - { "time": "09:00", "day": "weekday" }
                    - { "time": "10:00", "day": "weekend" }
                  drop_off_times:
                    - { "time": "17:00", "day": "weekday" }
                    - { "time": "16:00", "day": "weekend" }
                  opening_hours_description: "Weekdays 9am-5pm, Weekends 10am-4pm"
                - id: 2
                  name: "Auckland City"
                  pickup_times:
                    - { "time": "08:00", "day": "weekday" }
                    - { "time": "09:00", "day": "weekend" }
                  drop_off_times:
                    - { "time": "18:00", "day": "weekday" }
                    - { "time": "17:00", "day": "weekend" }
                  opening_hours_description: "Weekdays 8am-6pm, Weekends 9am-5pm"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /vehicles/availability:
    get:
      summary: Get available vehicles for given criteria
      description: Returns a list of vehicles available for the specified dates and locations
      tags:
        - Discovery
      parameters:
        - name: pick_up_depot_id
          in: query
          required: true
          schema:
            type: integer
          description: ID of the pickup depot
          example: 1
        - name: drop_off_depot_id
          in: query
          required: true
          schema:
            type: integer
          description: ID of the drop-off depot
          example: 2
        - name: pick_up_date
          in: query
          required: true
          schema:
            type: string
            format: date
          description: Pickup date (YYYY-MM-DD)
          example: "2024-01-15"
        - name: drop_off_date
          in: query
          required: true
          schema:
            type: string
            format: date
          description: Drop-off date (YYYY-MM-DD)
          example: "2024-01-22"
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Vehicle"
              example:
                - vehicleId: 4
                  name: "Lucky Rover Beta"
                  rentalDailyRate: 45.00
                  imageUrl: "https://www.happycampers.co.nz/vehicle-type/4/image"
                - vehicleId: 7
                  name: "Adventure Camper Plus"
                  rentalDailyRate: 65.00
                  imageUrl: "https://www.happycampers.co.nz/vehicle-type/7/image"
        "400":
          $ref: "#/components/responses/BadRequest"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /vehicles/{vehicleId}/accessories:
    get:
      summary: Get accessories available for a specific vehicle
      description: Returns a list of accessories that can be added to the specified vehicle
      tags:
        - Options Discovery
      parameters:
        - name: vehicleId
          in: path
          required: true
          schema:
            type: integer
          description: ID of the vehicle
          example: 4
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Accessory"
              example:
                - id: 1
                  name: "Bedding Pack (for 2 people)"
                  price: 10.00
                - id: 2
                  name: "Camping Chairs (set of 2)"
                  price: 10.00
                - id: 15
                  name: "Portable BBQ"
                  price: 25.00
                - id: 23
                  name: "Outdoor Table"
                  price: 15.00
        "400":
          $ref: "#/components/responses/BadRequest"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /vehicles/{vehicleId}/insurance-types:
    get:
      summary: Get insurance options available for a specific vehicle
      description: Returns a list of insurance plans that can be selected for the specified vehicle
      tags:
        - Options Discovery
      parameters:
        - name: vehicleId
          in: path
          required: true
          schema:
            type: integer
          description: ID of the vehicle
          example: 4
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Insurance"
              example:
                - id: 1
                  name: "Basic Insurance (No excess reduction)"
                  price: 0.00
                - id: 15
                  name: '"On the Fence" Insurance ($1500 Excess)'
                  price: 15.00
                - id: 3
                  name: "Premium Insurance ($500 Excess)"
                  price: 35.00
        "400":
          $ref: "#/components/responses/BadRequest"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

  /quotes:
    get:
      summary: Get detailed price quote for vehicle configuration
      x-web-checkout-template: "https://www.happycampers.co.nz/book?pick_up_depot_id={pick_up_depot_id}&drop_off_depot_id={drop_off_depot_id}&pick_up_date={pick_up_date}&drop_off_date={drop_off_date}&vehicle_id={vehicle_id}&insurance_id={insurance_id}&accessory_ids={accessory_ids}"
      description: Returns a comprehensive price breakdown for the specified vehicle and options
      tags:
        - Quoting
      parameters:
        - name: pick_up_depot_id
          in: query
          required: true
          schema:
            type: integer
          description: ID of the pickup depot
          example: 1
        - name: drop_off_depot_id
          in: query
          required: true
          schema:
            type: integer
          description: ID of the drop-off depot
          example: 1
        - name: pick_up_date
          in: query
          required: true
          schema:
            type: string
            format: date
          description: Pickup date (YYYY-MM-DD)
          example: "2025-09-17"
        - name: drop_off_date
          in: query
          required: true
          schema:
            type: string
            format: date
          description: Drop-off date (YYYY-MM-DD)
          example: "2025-09-24"
        - name: vehicle_id
          in: query
          required: true
          schema:
            type: integer
          description: ID of the selected vehicle
          example: 4
        - name: accessory_ids
          in: query
          required: false
          schema:
            type: string
          description: Comma-separated list of accessory IDs (e.g., "1,5,7")
          example: "1,2"
        - name: insurance_id
          in: query
          required: false
          schema:
            type: integer
          description: ID of the selected insurance plan
          example: 15
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Quote"
              example:
                quoteId: "1757992557279-4"
                expiresAt: "2025-09-16T03:45:57.279Z"
                currency: "NZD"
                priceBreakdown:
                  rentalFee: 360.00
                  routeFee: 0.00
                  accessoriesFee: 20.00
                  insuranceFee: 120.00
                  accessories:
                    - id: 1
                      name: "Bedding Pack (for 2 people)"
                      cost: 10.00
                      quantity: 1
                    - id: 2
                      name: "Camping Chairs (set of 2)"
                      cost: 10.00
                      quantity: 1
                  insurance:
                    id: 15
                    name: '"On the Fence" Insurance ($1500 Excess)'
                    cost: 120.00
                totalAmount: 500.00
                note: "All amounts are in NZD dollars. Original external API returns values in cents which are automatically converted for AI consumption."
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"

components:
  schemas:
    Depot:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the depot
        name:
          type: string
          description: Display name of the depot
        pickup_times:
          type: array
          items:
            type: object
          description: Available pickup times
        drop_off_times:
          type: array
          items:
            type: object
          description: Available drop-off times
        opening_hours_description:
          type: string
          description: Human-readable description of opening hours

    Vehicle:
      type: object
      properties:
        vehicleId:
          type: integer
          description: Unique identifier for the vehicle
        name:
          type: string
          description: Display name of the vehicle
        rentalDailyRate:
          type: number
          format: float
          description: Base daily rental rate
        imageUrl:
          type: string
          format: uri
          description: URL to vehicle image

    Accessory:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the accessory
        name:
          type: string
          description: Display name of the accessory
        price:
          type: number
          format: float
          description: Price of the accessory

    Insurance:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the insurance plan
        name:
          type: string
          description: Display name of the insurance plan
        price:
          type: number
          format: float
          description: Price of the insurance plan

    Quote:
      type: object
      properties:
        quoteId:
          type: string
          description: Unique identifier for this quote
        expiresAt:
          type: string
          format: date-time
          description: When this quote expires
        priceBreakdown:
          type: object
          properties:
            rentalFee:
              type: number
              format: float
              description: Base vehicle rental cost
            accessoriesFee:
              type: number
              format: float
              description: Total cost of selected accessories
            insuranceFee:
              type: number
              format: float
              description: Cost of selected insurance
            accessories:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                  cost:
                    type: number
                    format: float
            insurance:
              type: object
              nullable: true
              properties:
                name:
                  type: string
                cost:
                  type: number
                  format: float
        totalAmount:
          type: number
          format: float
          description: Final total cost

    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message

  responses:
    BadRequest:
      description: Bad request - invalid parameters
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error: "Missing required query parameter: pick_up_depot_id"

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error: "Vehicle not available for the selected criteria."

    RateLimited:
      description: Too many requests
      content:
        text/plain:
          schema:
            type: string
            example: "Too Many Requests"
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
        X-RateLimit-Reset:
          schema:
            type: string

    ServiceUnavailable:
      description: Service temporarily unavailable
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"

tags:
  - name: Discovery
    description: Endpoints for discovering available options
  - name: Options Discovery
    description: Endpoints for discovering vehicle-specific options
  - name: Quoting
    description: Endpoints for generating price quotes