openapi: 3.0.0
info:
  title: Site API
  version: 1.0.0
  description: >
    The Site API manages sites, kiosks, and/or materials for the Hauler Hero
    platform.


    ## Overview


    This specification is designed for integration partners to implement on
    their platform. Once implemented, Hauler Hero will call this endpoint to
    retrieve and synchronize disposal sites, kiosks, and materials from your
    system.


    ## Partner Implementation Requirements


    1. **Implement** the GET /scale-hero/v1/sites endpoint following this
    specification

    2. **Expose** the endpoint at a public URL (e.g.,
    `https://api.yourcompany.com/scale-hero/v1/sites`)

    3. **Provide** API-KEY credentials to Hauler Hero

    4. **Return** all active sites, kiosks, and materials for the requested
    hauler

    5. **Maintain** accurate `updatedAt` timestamps for change tracking

    6. **Follow** the required/optional fields defined in the Schemas section
    below


    ## How It Works


    1. Partner implements this API specification

    2. Partner provides endpoint URL and API-KEY to Hauler Hero

    3. Hauler Hero calls GET /scale-hero/v1/sites with the partner's `haulerId`

    4. Partner returns sites, kiosks, and materials in the specified format

    5. Hauler Hero maps and stores the data for ongoing synchronization


    ## Data Model


    See the **Schemas** section below for complete field definitions:

    - **Site** - Disposal site with address details (always required)

    - **Kiosk** - Kiosk/station linked to a site (optional - only if your system
    uses this concept)

    - **Material** - Material types with pricing at kiosks/sites


    ### Important: Kiosk Concept is Optional


    If your system uses **kiosks** (stations/points within a site):

    - Include the `kiosks` array in the response

    - Materials must have a `kioskId` to link them to a kiosk


    If your system does **not use kiosks**:

    - Return an empty `kiosks` array or omit it

    - Materials must have a `siteId` to link them directly to a site


    **Note:** Each material must have either a `siteId` OR/AND a `kioskId`,
    depending on your system's hierarchy.


    ## Authentication


    All requests require an `API-KEY` header for authentication.
servers:
  - url: https://api.yourcompany.com
    description: Production server
security:
  - apiKey: []
tags:
  - name: Sites
    description: Site, Kiosk, and Material management operations
paths:
  /scale-hero/v1/sites:
    get:
      summary: Get Sites, Kiosks, and materials
      description: Retrieve all sites, kiosks, and materials for a specific hauler
      operationId: getSiteData
      tags:
        - Sites
      security:
        - apiKey: []
      parameters:
        - name: haulerId
          in: query
          required: true
          description: Unique identifier for the hauler
          schema:
            type: string
            format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
      responses:
        '200':
          description: Sites, kiosks, and materials retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetSitesResponse'
              example:
                success: true
                data:
                  sites:
                    - id: 64318450-1ce2-499d-8a70-f313aabe1831
                      name: GTest Site 11
                      address:
                        line1: 1250 Riverside Drive
                        city: Austin
                        state: Texas
                        country: United States
                        zipCode: '78701'
                      active: true
                      updatedAt: '2024-10-21T15:30:00Z'
                  kiosks:
                    - id: d3f3f3e3-1f2e-4f2b-8f7a-5e3b6c4d2a1b
                      siteId: 64318450-1ce2-499d-8a70-f313aabe1831
                      name: GTest Kiosk 11
                      active: true
                      updatedAt: '2024-10-21T15:30:00Z'
                  materials:
                    - id: a51b814b-1b23-4f28-8c2a-b90030340eea
                      kioskId: d3f3f3e3-1f2e-4f2b-8f7a-5e3b6c4d2a1b
                      siteId: 64318450-1ce2-499d-8a70-f313aabe1831
                      materialType: Appliance
                      measureUnit: Item
                      active: true
                      updatedAt: '2024-10-21T15:30:00Z'
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: INVALID_PAYLOAD
                  message: Invalid haulerId format
        '401':
          description: Unauthorized - Invalid or missing authentication
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: UNAUTHORIZED
                  message: Invalid API key
        '404':
          description: Not found - Hauler not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: NOT_FOUND
                  message: Hauler not found
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: INTERNAL_ERROR
                  message: An unexpected error occurred while retrieving the data
components:
  schemas:
    SiteData:
      type: object
      properties:
        sites:
          type: array
          description: List of sites for the hauler
          items:
            $ref: '#/components/schemas/Site'
        kiosks:
          type: array
          description: List of kiosks associated with the sites
          items:
            $ref: '#/components/schemas/Kiosk'
        materials:
          type: array
          description: List of materials available at the kiosks / sites
          items:
            $ref: '#/components/schemas/Material'
    GetSitesResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          description: Whether the request was successful
          example: true
        data:
          $ref: '#/components/schemas/SiteData'
    Site:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the site
          example: 64318450-1ce2-499d-8a70-f313aabe1831
        name:
          type: string
          description: Name of the site
          example: GTest Site 11
          maxLength: 255
        address:
          $ref: '#/components/schemas/Address'
        active:
          type: boolean
          description: Whether the site is currently active
          example: true
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the site was last updated
          example: '2024-10-21T15:30:00Z'
    Address:
      type: object
      required:
        - line1
        - city
        - state
        - country
        - zipCode
      properties:
        line1:
          type: string
          description: Primary address line
          example: 1250 Riverside Drive
          maxLength: 255
        city:
          type: string
          description: City name
          example: Austin
          maxLength: 100
        state:
          type: string
          description: State or province
          example: Texas
          maxLength: 100
        country:
          type: string
          description: Country name
          example: United States
          maxLength: 100
        zipCode:
          type: string
          description: Postal/ZIP code
          example: '78701'
          maxLength: 20
    Kiosk:
      type: object
      required:
        - id
        - siteId
        - name
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the kiosk
          example: d3f3f3e3-1f2e-4f2b-8f7a-5e3b6c4d2a1b
        siteId:
          type: string
          format: uuid
          description: Foreign key reference to the parent site
          example: 64318450-1ce2-499d-8a70-f313aabe1831
        name:
          type: string
          description: Name of the kiosk
          example: GTest Kiosk 11
          maxLength: 255
        active:
          type: boolean
          description: Whether the kiosk is currently active
          example: true
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the kiosk was last updated
          example: '2024-10-21T15:30:00Z'
    Material:
      type: object
      required:
        - id
        - materialType
        - measureUnit
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the material
          example: a51b814b-1b23-4f28-8c2a-b90030340eea
        siteId:
          type: string
          format: uuid
          description: >
            Foreign key reference to the parent site. 

            Required if your system does NOT use kiosks and materials are linked
            directly to sites.

            Either siteId or kioskId must be provided, not both.
          example: 64318450-1ce2-499d-8a70-f313aabe1831
        kioskId:
          type: string
          format: uuid
          description: >
            Foreign key reference to the parent kiosk.

            Required if your system uses kiosks and materials are linked to
            kiosks.

            Either siteId or kioskId must be provided, not both.
          example: d3f3f3e3-1f2e-4f2b-8f7a-5e3b6c4d2a1b
        materialType:
          type: string
          description: Type/category of material
          example: Appliance
          maxLength: 100
        measureUnit:
          type: string
          description: Unit of measurement for the material
          example: Item
          enum:
            - Item
            - Ton
            - Pound
            - Kilogram
            - Cubic Yard
            - Cubic Meter
        active:
          type: boolean
          description: Whether the material is currently active/available
          example: true
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the material was last updated
          example: '2024-10-21T15:30:00Z'
    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          description: Always false for errors
          example: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: INVALID_PAYLOAD
              enum:
                - INVALID_PAYLOAD
                - UNAUTHORIZED
                - INTERNAL_ERROR
                - VALIDATION_ERROR
                - NOT_FOUND
            message:
              type: string
              description: Human-readable error message
              example: 'Missing required field: eventId'
            details:
              type: object
              description: Additional error details (optional)
              additionalProperties: true
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: API-KEY
      description: |
        API key for authenticating requests.

        To obtain an API key:
        - Contact your account manager
        - Email: api-support@haulerhero.com

        Include in request header: `API-KEY: your_api_key_here`
