openapi: 3.0.0
paths:
  /:
    get:
      operationId: AppController_getHello
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: string
      summary: Root endpoint
      tags:
        - App
  /health:
    get:
      operationId: AppController_healthCheck
      parameters: []
      responses:
        '200':
          description: Service is healthy
      summary: Health check
      tags:
        - App
  /users/me:
    patch:
      operationId: UsersController_updateMyProfile
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProfileDto'
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Update current user profile
      tags:
        - Users
    delete:
      operationId: UsersController_deleteMyAccount
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AccountActionDto'
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Permanently delete current user account
      tags:
        - Users
  /users/me/deactivate:
    post:
      operationId: UsersController_deactivateMyAccount
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AccountActionDto'
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Deactivate current user account
      tags:
        - Users
  /users/me/reactivate:
    post:
      operationId: UsersController_reactivateMyAccount
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Reactivate current user account
      tags:
        - Users
  /users/me/use-cases:
    get:
      operationId: UsersController_getMyUseCases
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
      security:
        - bearer: []
      summary: Get current user use cases
      tags:
        - Users
    patch:
      operationId: UsersController_updateMyUseCases
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUseCasesDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
      security:
        - bearer: []
      summary: Update current user use cases
      tags:
        - Users
  /users/me/org-context:
    get:
      operationId: UsersController_getMyOrgContext
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Get org context for org switcher UI
      tags:
        - Users
  /users:
    post:
      operationId: UsersController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a user (admin)
      tags:
        - Users
    get:
      operationId: UsersController_findAll
      parameters:
        - name: role
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all users (admin)
      tags:
        - Users
  /users/{id}:
    get:
      operationId: UsersController_findOne
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get user by ID (admin)
      tags:
        - Users
    patch:
      operationId: UsersController_update
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update user by ID (admin)
      tags:
        - Users
    delete:
      operationId: UsersController_delete
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete user by ID (admin)
      tags:
        - Users
  /me/onboarding:
    get:
      operationId: OnboardingController_getOnboarding
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Get onboarding status for current user
      tags:
        - Onboarding
  /me/customer-organizations:
    get:
      operationId: OnboardingController_getCustomerOrganizations
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
      security:
        - bearer: []
      summary: Get customer organizations for agent ordering
      tags:
        - Onboarding
  /auth/register:
    post:
      operationId: AuthController_register
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterDto'
      responses:
        '201':
          description: ''
      summary: Register a new account
      tags:
        - Auth
  /auth/login:
    post:
      operationId: AuthController_login
      parameters: []
      responses:
        '201':
          description: ''
      summary: Login with email and password
      tags:
        - Auth
  /auth/oauth/google:
    post:
      operationId: AuthController_oauthGoogle
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OAuthLoginDto'
      responses:
        '201':
          description: ''
      summary: Login or register via Google OAuth
      tags:
        - Auth
  /auth/oauth/facebook:
    post:
      operationId: AuthController_oauthFacebook
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OAuthLoginDto'
      responses:
        '201':
          description: ''
      summary: Login or register via Facebook OAuth
      tags:
        - Auth
  /auth/me:
    get:
      operationId: AuthController_me
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get current authenticated user
      tags:
        - Auth
  /auth/me/bootstrap:
    get:
      operationId: AuthController_bootstrap
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Bootstrap user session — ensures provisioning and returns app state
      tags:
        - Auth
  /auth/register/onboarding:
    post:
      operationId: AuthController_registerOnboarding
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OnboardingRegisterDto'
      responses:
        '201':
          description: ''
      summary: Register via onboarding flow with OTP verification
      tags:
        - Auth
  /auth/test-login:
    post:
      operationId: AuthController_testLogin
      parameters: []
      responses:
        '201':
          description: ''
      summary: Get Clerk sign-in token for test accounts
      tags:
        - Auth
  /auth/otp/send:
    post:
      operationId: OtpController_sendOtp
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendOtpDto'
      responses:
        '201':
          description: ''
      summary: Send OTP to email address
      tags:
        - OTP
  /auth/otp/verify:
    post:
      operationId: OtpController_verifyOtp
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyOtpDto'
      responses:
        '201':
          description: ''
      summary: Verify OTP code
      tags:
        - OTP
  /auth/otp/check-email/{email}:
    get:
      operationId: OtpController_checkEmail
      parameters:
        - name: email
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Check if email is registered
      tags:
        - OTP
  /projects:
    get:
      operationId: ProjectsController_getProjects
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all projects in organization
      tags:
        - Projects
  /projects/{projectId}/media:
    get:
      operationId: ProjectsController_getProjectMedia
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List media for a project
      tags:
        - Projects
    post:
      operationId: ProjectsController_addProjectMedia
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectMediaDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Add media to a project
      tags:
        - Projects
  /projects/{projectId}/media/{mediaId}:
    delete:
      operationId: ProjectsController_deleteProjectMedia
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
        - name: mediaId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete media from a project
      tags:
        - Projects
  /projects/mine:
    get:
      operationId: ProjectsController_findMine
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List current user projects
      tags:
        - Projects
  /projects/{id}/messages:
    get:
      operationId: ProjectsController_getMessages
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
        - name: channel
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get messages for a project
      tags:
        - Projects
    post:
      operationId: ProjectsController_addMessage
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMessageDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Add a message to a project
      tags:
        - Projects
  /projects/create:
    post:
      operationId: ProjectsController_createProject
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a new project
      tags:
        - Projects
  /projects/{id}:
    get:
      operationId: ProjectsController_findOne
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get project by ID
      tags:
        - Projects
    patch:
      operationId: ProjectsController_updateProject
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProjectDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update a project
      tags:
        - Projects
    delete:
      operationId: ProjectsController_remove
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete a project
      tags:
        - Projects
  /projects/{id}/assign:
    patch:
      operationId: ProjectsController_assign
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignProjectDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Assign technician and editor to a project
      tags:
        - Projects
  /projects/{id}/assign-technician:
    patch:
      operationId: ProjectsController_assignTechnician
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Assign technician to a project
      tags:
        - Projects
  /projects/{id}/assign-customer:
    patch:
      operationId: ProjectsController_assignCustomer
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Assign customer to a project
      tags:
        - Projects
  /projects/{id}/assign-project-manager:
    patch:
      operationId: ProjectsController_assignProjectManager
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Assign project manager
      tags:
        - Projects
  /projects/{id}/assign-editor:
    patch:
      operationId: ProjectsController_assignEditor
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Assign editor to a project
      tags:
        - Projects
  /projects/{id}/schedule:
    patch:
      operationId: ProjectsController_scheduleProject
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Schedule a project
      tags:
        - Projects
  /projects/{id}/status:
    patch:
      operationId: ProjectsController_updateStatus
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProjectStatusDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update project status
      tags:
        - Projects
  /projects/{id}/delivery:
    get:
      operationId: ProjectsController_getDeliveryStatus
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get delivery status for a project
      tags:
        - Projects
  /projects/{id}/delivery/enable:
    post:
      operationId: ProjectsController_enableDelivery
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Enable delivery for a project
      tags:
        - Projects
  /projects/{id}/delivery/disable:
    post:
      operationId: ProjectsController_disableDelivery
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Disable delivery for a project
      tags:
        - Projects
  /projects/{id}/delivery/regenerate-token:
    post:
      operationId: ProjectsController_regenerateDeliveryToken
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Regenerate delivery token
      tags:
        - Projects
  /projects/{id}/delivery/rotate-token:
    post:
      operationId: ProjectsController_rotateDeliveryToken
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Rotate delivery token
      tags:
        - Projects
  /availability:
    get:
      operationId: CronofyController_getAvailability
      parameters:
        - name: startDate
          required: true
          in: query
          schema:
            type: string
        - name: endDate
          required: true
          in: query
          schema:
            type: string
        - name: technicianIds
          required: true
          in: query
          schema:
            type: string
        - name: duration
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get technician availability slots
      tags:
        - Cronofy
  /availability/check:
    get:
      operationId: CronofyController_checkSlot
      parameters:
        - name: technicianId
          required: true
          in: query
          schema:
            type: string
        - name: scheduledTime
          required: true
          in: query
          schema:
            type: string
        - name: duration
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Check if a specific time slot is available
      tags:
        - Cronofy
  /media/confirm-upload:
    post:
      operationId: MediaController_confirmUpload
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmUploadDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Confirm a media upload
      tags:
        - Media
  /media/project/{projectId}:
    get:
      operationId: MediaController_getMediaForProject
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get media for a project
      tags:
        - Media
  /media/{id}:
    get:
      operationId: MediaController_getMediaById
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get media by ID
      tags:
        - Media
    delete:
      operationId: MediaController_deleteMedia
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete media by ID
      tags:
        - Media
  /user-availability:
    get:
      operationId: AvailabilityController_getMyAvailability
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Get current user availability settings
      tags:
        - Availability
  /user-availability/status:
    patch:
      operationId: AvailabilityController_updateAvailabilityStatus
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AvailabilityStatusDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Update availability status
      tags:
        - Availability
  /user-availability/work-hours:
    patch:
      operationId: AvailabilityController_updateWorkHours
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkHoursDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Update work hours for a specific day
      tags:
        - Availability
    put:
      operationId: AvailabilityController_updateAllWorkHours
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Update all work hours at once
      tags:
        - Availability
  /nylas/oauth/start:
    get:
      operationId: NylasController_getOAuthUrl
      parameters:
        - name: provider
          required: true
          in: query
          schema:
            type: string
        - name: returnTo
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Start OAuth flow for calendar connection
      tags:
        - Nylas
  /nylas/oauth/callback:
    get:
      operationId: NylasController_handleOAuthCallback
      parameters:
        - name: code
          required: true
          in: query
          schema:
            type: string
        - name: state
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Handle OAuth callback redirect
      tags:
        - Nylas
  /nylas/connection/{integrationId}:
    delete:
      operationId: NylasController_disconnect
      parameters:
        - name: integrationId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Disconnect calendar integration
      tags:
        - Nylas
  /nylas/connection:
    get:
      operationId: NylasController_getConnectionStatus
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get calendar connection status
      tags:
        - Nylas
  /nylas/configured:
    get:
      operationId: NylasController_isConfigured
      parameters: []
      responses:
        '200':
          description: ''
      summary: Check if Nylas is configured
      tags:
        - Nylas
  /nylas/calendars:
    get:
      operationId: NylasController_getCalendars
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get user calendars
      tags:
        - Nylas
  /nylas/calendars/{integrationId}/write-target:
    patch:
      operationId: NylasController_setWriteTarget
      parameters:
        - name: integrationId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Set write target calendar
      tags:
        - Nylas
  /nylas/availability:
    get:
      operationId: NylasController_getAvailability
      parameters:
        - name: start
          required: true
          in: query
          schema:
            type: string
        - name: end
          required: true
          in: query
          schema:
            type: string
        - name: durationMins
          required: true
          in: query
          schema:
            type: string
        - name: timezone
          required: true
          in: query
          schema:
            type: string
        - name: technicianId
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get available time slots
      tags:
        - Nylas
  /nylas/projects/{projectId}/sync-status:
    get:
      operationId: NylasController_getProjectSyncStatus
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get project calendar sync status
      tags:
        - Nylas
  /nylas/projects/{projectId}/reconcile:
    post:
      operationId: NylasController_reconcileProject
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Reconcile project calendar event
      tags:
        - Nylas
  /nylas/sync-all:
    post:
      operationId: NylasController_syncAllProjects
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Sync all assigned projects to calendar
      tags:
        - Nylas
  /me/notifications:
    get:
      operationId: NotificationsController_getMyNotifications
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/NotificationResponseDto'
      security:
        - bearer: []
      summary: Get my notifications
      tags:
        - Notifications
  /invitations/{id}/accept:
    post:
      operationId: NotificationsController_acceptInvitation
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Accept an invitation
      tags:
        - Notifications
  /invitations/{id}/decline:
    post:
      operationId: NotificationsController_declineInvitation
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Decline an invitation
      tags:
        - Notifications
  /notifications/{id}/read:
    post:
      operationId: NotificationsController_markAsRead
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Mark a notification as read
      tags:
        - Notifications
  /notifications/read-all:
    post:
      operationId: NotificationsController_markAllAsRead
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Mark all notifications as read
      tags:
        - Notifications
  /notifications/count:
    get:
      operationId: NotificationsController_getUnreadCount
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get unread notification count
      tags:
        - Notifications
  /organizations/{id}/public:
    get:
      operationId: NotificationsController_getOrganizationPublic
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get public organization info
      tags:
        - Notifications
  /messages:
    post:
      operationId: MessagesController_sendMessage
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendMessageDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Send a message
      tags:
        - Messages
  /messages/project/{projectId}:
    get:
      operationId: MessagesController_getMessagesForProject
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
        - name: channel
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get messages for a project
      tags:
        - Messages
  /messages/{id}:
    get:
      operationId: MessagesController_getMessageById
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get message by ID
      tags:
        - Messages
    delete:
      operationId: MessagesController_deleteMessage
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete a message
      tags:
        - Messages
  /inquiries:
    post:
      operationId: InquiriesController_createInquiry
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateInquiryDto'
      responses:
        '201':
          description: ''
      summary: Submit a public inquiry
      tags:
        - Inquiries
    get:
      operationId: InquiriesController_getAllInquiries
      parameters: []
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all inquiries
      tags:
        - Inquiries
  /inquiries/{id}:
    get:
      operationId: InquiriesController_getInquiryById
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get inquiry by ID
      tags:
        - Inquiries
    patch:
      operationId: InquiriesController_updateInquiry
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateInquiryDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update an inquiry
      tags:
        - Inquiries
  /inquiries/{id}/convert:
    post:
      operationId: InquiriesController_convertToProject
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Convert inquiry to a project
      tags:
        - Inquiries
  /dashboard:
    get:
      operationId: DashboardController_getDashboard
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get dashboard metrics and analytics
      tags:
        - Dashboard
  /organizations/invite/validate/{token}:
    get:
      operationId: OrganizationsController_validateInviteCode
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Validate an invite code (public)
      tags:
        - Organizations
  /organizations/invitations/by-email/{email}:
    get:
      operationId: OrganizationsController_getPendingInvitationsByEmail
      parameters:
        - name: email
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get pending invitations by email (public)
      tags:
        - Organizations
  /organizations:
    post:
      operationId: OrganizationsController_createOrg
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrganizationDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a new organization
      tags:
        - Organizations
    get:
      operationId: OrganizationsController_listMyOrgs
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List my organizations
      tags:
        - Organizations
  /organizations/{orgId}/invite:
    post:
      operationId: OrganizationsController_invite
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateInviteDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Invite a user to an organization
      tags:
        - Organizations
  /organizations/accept-invite:
    post:
      operationId: OrganizationsController_acceptInvite
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AcceptInviteDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Accept an organization invite
      tags:
        - Organizations
  /organizations/{orgId}:
    get:
      operationId: OrganizationsController_getOrganization
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get organization by ID
      tags:
        - Organizations
  /organizations/{orgId}/members:
    get:
      operationId: OrganizationsController_listMembers
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List organization members
      tags:
        - Organizations
  /organizations/{orgId}/settings:
    patch:
      operationId: OrganizationsController_updateOrganizationSettings
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateOrganizationSettingsDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update organization settings
      tags:
        - Organizations
  /organizations/{orgId}/members/{memberId}/role:
    patch:
      operationId: OrganizationsController_updateMemberRole
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
        - name: memberId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateMemberRoleDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update a member role
      tags:
        - Organizations
  /customers:
    get:
      operationId: CustomersController_list
      parameters:
        - name: search
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List customers (with optional search)
      tags:
        - Customers
    post:
      operationId: CustomersController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCustomerDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a customer
      tags:
        - Customers
  /customers/{id}:
    patch:
      operationId: CustomersController_update
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCustomerDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update a customer
      tags:
        - Customers
    delete:
      operationId: CustomersController_delete
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete a customer
      tags:
        - Customers
  /orders/create:
    post:
      operationId: OrdersController_createOrder
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a new order
      tags:
        - Orders
  /orders/checkout:
    post:
      operationId: OrdersController_createCheckout
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create Stripe checkout session for an order
      tags:
        - Orders
  /orders/status/{sessionId}:
    get:
      operationId: OrdersController_getOrderStatus
      parameters:
        - name: sessionId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Get order status by Stripe session ID
      tags:
        - Orders
  /orders:
    get:
      operationId: OrdersController_listOrders
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all orders for organization
      tags:
        - Orders
  /orders/{projectId}/cancel:
    delete:
      operationId: OrdersController_cancelOrder
      parameters:
        - name: projectId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
        - bearer: []
      summary: Cancel an order as customer
      tags:
        - Orders
  /packages/org/{orgId}:
    get:
      operationId: PackagesController_getPackagesForOrg
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Get active packages for an organization
      tags:
        - Packages
  /packages/org/{orgId}/addons:
    get:
      operationId: PackagesController_getAddOnsForOrg
      parameters:
        - name: orgId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Get active add-ons for an organization
      tags:
        - Packages
  /packages/calculate:
    post:
      operationId: PackagesController_calculateTotal
      parameters: []
      responses:
        '201':
          description: ''
      summary: Calculate price for package and add-ons
      tags:
        - Packages
  /packages:
    get:
      operationId: PackagesController_getAllPackages
      parameters: []
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all packages including inactive
      tags:
        - Packages
    post:
      operationId: PackagesController_createPackage
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePackageDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create a package
      tags:
        - Packages
  /packages/addons:
    get:
      operationId: PackagesController_getAllAddOns
      parameters: []
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: List all add-ons including inactive
      tags:
        - Packages
    post:
      operationId: PackagesController_createAddOn
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAddOnDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Create an add-on
      tags:
        - Packages
  /packages/{id}:
    put:
      operationId: PackagesController_updatePackage
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePackageDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update a package
      tags:
        - Packages
    delete:
      operationId: PackagesController_deletePackage
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete a package
      tags:
        - Packages
  /packages/addons/{id}:
    put:
      operationId: PackagesController_updateAddOn
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAddOnDto'
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Update an add-on
      tags:
        - Packages
    delete:
      operationId: PackagesController_deleteAddOn
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Delete an add-on
      tags:
        - Packages
  /delivery/{token}:
    get:
      operationId: DeliveryController_getDeliveryByToken
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeliveryResponseDto'
      summary: Get delivery data by public token
      tags:
        - Delivery
  /delivery/{token}/comments:
    get:
      operationId: DeliveryController_getComments
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CommentDto'
      summary: Get comments for a delivery
      tags:
        - Delivery
    post:
      operationId: DeliveryController_addComment
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddCommentDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommentDto'
      security:
        - bearer: []
      summary: Add a comment to a delivery
      tags:
        - Delivery
  /delivery/{token}/download-request:
    post:
      operationId: DeliveryController_requestDownload
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DownloadAllDto'
      responses:
        '201':
          description: ''
      summary: Request a download artifact
      tags:
        - Delivery
  /delivery/{token}/download-status/{artifactId}:
    get:
      operationId: DeliveryController_getDownloadStatus
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
        - name: artifactId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Get download artifact status
      tags:
        - Delivery
  /delivery/{token}/approve:
    post:
      operationId: DeliveryController_approveDelivery
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Approve a delivery
      tags:
        - Delivery
  /delivery/{token}/request-changes:
    post:
      operationId: DeliveryController_requestChanges
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestChangesDto'
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Request changes on a delivery
      tags:
        - Delivery
  /delivery/admin/retry-artifact:
    post:
      operationId: DeliveryController_retryArtifact
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RetryArtifactDto'
      responses:
        '201':
          description: ''
        '401':
          description: Missing or invalid JWT token
        '403':
          description: Not a member of the specified organization
      security:
        - bearer: []
        - x-org-id: []
      summary: Retry a failed artifact generation
      tags:
        - Delivery
  /calendar-integrations/ics-feed:
    get:
      operationId: IcsFeedController_getIcsFeed
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get or create ICS feed URL
      tags:
        - Calendar
  /calendar-integrations/ics-feed/regenerate:
    post:
      operationId: IcsFeedController_regenerateIcsFeed
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Regenerate ICS feed token
      tags:
        - Calendar
  /ics/{token}.ics:
    get:
      operationId: IcsFeedController_serveIcsFile
      parameters:
        - name: token
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      summary: Serve ICS calendar file
      tags:
        - Calendar
  /tours/status:
    get:
      operationId: ToursController_getTourStatus
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get user tour status and progress
      tags:
        - Tours
  /tours/progress/{track}:
    get:
      operationId: ToursController_getTrackProgress
      parameters:
        - name: track
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Get progress for a tour track
      tags:
        - Tours
  /tours/progress:
    patch:
      operationId: ToursController_updateProgress
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTourProgressDto'
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Update progress for a tour step
      tags:
        - Tours
  /tours/complete/{track}:
    post:
      operationId: ToursController_completeTrack
      parameters:
        - name: track
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Mark a tour track as completed
      tags:
        - Tours
  /tours/skip/{track}:
    post:
      operationId: ToursController_skipTrack
      parameters:
        - name: track
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Skip a tour track
      tags:
        - Tours
  /tours/dismiss-guide:
    post:
      operationId: ToursController_dismissGuide
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Dismiss the setup guide
      tags:
        - Tours
  /tours/reset:
    post:
      operationId: ToursController_resetProgress
      parameters: []
      responses:
        '201':
          description: ''
      security:
        - bearer: []
      summary: Reset all tour progress
      tags:
        - Tours
  /tours/demo-project:
    post:
      operationId: ToursController_createDemoProject
      parameters:
        - name: x-org-id
          required: true
          in: header
          schema:
            type: string
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Create a demo project for tour
      tags:
        - Tours
    get:
      operationId: ToursController_getDemoProject
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
      security:
        - bearer: []
      summary: Get demo project
      tags:
        - Tours
    delete:
      operationId: ToursController_deleteDemoProject
      parameters: []
      responses:
        '200':
          description: ''
      security:
        - bearer: []
      summary: Delete demo project
      tags:
        - Tours
info:
  title: VREM API
  description: VX Real Estate Media — Backend API Reference
  version: '1.0'
  contact: {}
tags:
  - name: App
    description: Health check
  - name: Auth
    description: Authentication & session management
  - name: OTP
    description: One-time password verification
  - name: Onboarding
    description: User onboarding flow
  - name: Users
    description: User management
  - name: Organizations
    description: Organization management
  - name: Projects
    description: Project CRUD & workflow
  - name: Orders
    description: Order management
  - name: Customers
    description: Customer management
  - name: Messages
    description: In-app messaging
  - name: Inquiries
    description: Public inquiry forms
  - name: Media
    description: Media file management
  - name: Dashboard
    description: Dashboard metrics & analytics
  - name: Notifications
    description: Notification management
  - name: Packages
    description: Service packages & add-ons
  - name: Availability
    description: Scheduling & availability
  - name: Cronofy
    description: Cronofy calendar integration
  - name: Delivery
    description: Project delivery & public galleries
  - name: Tours
    description: Virtual tour management
  - name: Nylas
    description: Nylas email integration
  - name: Calendar
    description: ICS calendar feeds
  - name: Stripe
    description: Stripe payments & webhooks
servers: []
components:
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http
    x-org-id:
      type: apiKey
      in: header
      name: x-org-id
  schemas:
    UpdateProfileDto:
      type: object
      properties:
        name:
          type: string
        avatarUrl:
          type: string
    AccountActionDto:
      type: object
      properties:
        password:
          type: string
          minLength: 1
      required:
        - password
    UpdateUseCasesDto:
      type: object
      properties:
        useCases:
          minItems: 1
          type: array
          items:
            type: object
      required:
        - useCases
    CreateUserDto:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        password:
          type: string
          minLength: 6
        accountType:
          type: object
      required:
        - email
        - name
        - password
        - accountType
    UpdateUserDto:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        avatarUrl:
          type: string
        accountType:
          type: object
    RegisterDto:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        password:
          type: string
          minLength: 6
        accountType:
          type: object
          description: |-
            User-facing intent for the account.
            Only AGENT and PROVIDER are user-facing in the UI.
      required:
        - email
        - name
        - password
        - accountType
    OAuthLoginDto:
      type: object
      properties:
        token:
          type: string
        accountType:
          type: object
        name:
          type: string
      required:
        - token
        - accountType
    OnboardingRegisterDto:
      type: object
      properties:
        otpToken:
          type: string
        email:
          type: string
          format: email
        name:
          type: string
        password:
          type: string
          minLength: 8
        accountType:
          type: object
        inviteCode:
          type: string
        useCases:
          type: array
          items:
            type: object
      required:
        - otpToken
        - email
        - name
        - password
        - accountType
    SendOtpDto:
      type: object
      properties:
        email:
          type: string
          format: email
      required:
        - email
    VerifyOtpDto:
      type: object
      properties:
        email:
          type: string
          format: email
        code:
          type: string
          minLength: 6
          maxLength: 6
      required:
        - email
        - code
    CreateProjectMediaDto:
      type: object
      properties:
        key:
          type: string
        cdnUrl:
          type: string
        filename:
          type: string
        size:
          type: number
        type:
          type: object
      required:
        - key
        - filename
        - size
        - type
    CreateMessageDto:
      type: object
      properties:
        content:
          type: string
        channel:
          type: object
        thread:
          type: string
          nullable: true
      required:
        - content
    CreateProjectDto:
      type: object
      properties:
        addressLine1:
          type: string
        addressLine2:
          type: string
        city:
          type: string
        region:
          type: string
        postalCode:
          type: string
        countryCode:
          type: string
        lat:
          type: number
        lng:
          type: number
        notes:
          type: string
        scheduledTime:
          type: string
        customerId:
          type: string
        projectManagerId:
          type: string
        technicianId:
          type: string
        editorId:
          type: string
      required:
        - scheduledTime
    AssignProjectDto:
      type: object
      properties:
        technicianId:
          type: string
        editorId:
          type: string
    UpdateProjectDto:
      type: object
      properties:
        addressLine1:
          type: string
        addressLine2:
          type: string
        city:
          type: string
        region:
          type: string
        postalCode:
          type: string
        countryCode:
          type: string
        lat:
          type: number
        lng:
          type: number
        notes:
          type: string
        scheduledTime:
          type: string
    UpdateProjectStatusDto:
      type: object
      properties:
        status:
          type: object
      required:
        - status
    ConfirmUploadDto:
      type: object
      properties:
        key:
          type: string
        cdnUrl:
          type: string
        filename:
          type: string
        size:
          type: number
        type:
          type: object
        projectId:
          type: string
      required:
        - key
        - filename
        - size
        - type
        - projectId
    AvailabilityStatusDto:
      type: object
      properties:
        isAvailable:
          type: boolean
        availabilityNote:
          type: string
          nullable: true
        autoDeclineBookings:
          type: boolean
      required:
        - isAvailable
    WorkHoursDto:
      type: object
      properties:
        dayOfWeek:
          type: object
        isEnabled:
          type: boolean
        startTime:
          type: string
          pattern: /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/
        endTime:
          type: string
          pattern: /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/
      required:
        - dayOfWeek
        - isEnabled
        - startTime
        - endTime
    NotificationResponseDto:
      type: object
      properties:
        id:
          type: string
        type:
          type: object
        orgId:
          type: string
        orgName:
          type: string
        orgType:
          type: object
        createdAt:
          format: date-time
          type: string
        readAt:
          format: date-time
          type: string
          nullable: true
        invitationId:
          type: string
        role:
          type: object
        projectId:
          type: string
        projectAddress:
          type: string
        assignedRole:
          type: object
        messagePreview:
          type: string
        messageChannel:
          type: object
        approverName:
          type: string
        deliveryToken:
          type: string
      required:
        - id
        - type
        - orgId
        - orgName
        - orgType
        - createdAt
    SendMessageDto:
      type: object
      properties:
        projectId:
          type: string
        content:
          type: string
        channel:
          type: object
        thread:
          type: string
          nullable: true
      required:
        - projectId
        - content
    CreateInquiryDto:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        address:
          type: string
        message:
          type: string
      required:
        - name
        - email
    UpdateInquiryDto:
      type: object
      properties:
        status:
          type: object
    CreateOrganizationDto:
      type: object
      properties:
        name:
          type: string
        type:
          type: object
      required:
        - name
    CreateInviteDto:
      type: object
      properties:
        email:
          type: string
          format: email
        role:
          type: object
        inviteType:
          type: object
      required:
        - email
    AcceptInviteDto:
      type: object
      properties:
        token:
          type: string
      required:
        - token
    UpdateOrganizationSettingsDto:
      type: object
      properties:
        name:
          type: string
        legalName:
          type: string
        slug:
          type: string
        logoUrl:
          type: string
        websiteUrl:
          type: string
        phone:
          type: string
        primaryEmail:
          type: string
        addressLine1:
          type: string
        addressLine2:
          type: string
        city:
          type: string
        region:
          type: string
        postalCode:
          type: string
        countryCode:
          type: string
        lat:
          type: number
        lng:
          type: number
        timezone:
          type: string
        serviceArea:
          type: object
    UpdateMemberRoleDto:
      type: object
      properties:
        role:
          type: object
      required:
        - role
    CreateCustomerDto:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        notes:
          type: string
        userId:
          type: string
    UpdateCustomerDto:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        notes:
          type: string
    NewCustomerDto:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        notes:
          type: string
      required:
        - name
    CreateOrderDto:
      type: object
      properties:
        providerOrgId:
          type: string
        customerId:
          type: string
        newCustomer:
          $ref: '#/components/schemas/NewCustomerDto'
        addressLine1:
          type: string
        addressLine2:
          type: string
        city:
          type: string
        region:
          type: string
        postalCode:
          type: string
        countryCode:
          type: string
        lat:
          type: number
        lng:
          type: number
        scheduledTime:
          type: string
        estimatedDuration:
          type: number
        schedulingMode:
          enum:
            - scheduled
            - requested
          type: string
        mediaTypes:
          type: array
          items:
            type: string
        priority:
          enum:
            - standard
            - rush
            - urgent
          type: string
        notes:
          type: string
        technicianId:
          type: string
        editorId:
          type: string
        projectManagerId:
          type: string
        packageId:
          type: string
        addOnIds:
          type: array
          items:
            type: string
        addOnQuantities:
          type: object
        idempotencyKey:
          type: string
      required:
        - addressLine1
        - scheduledTime
        - mediaTypes
        - priority
    CreatePackageDto:
      type: object
      properties:
        name:
          type: string
          description: Package name
        description:
          type: string
          description: Package description
        price:
          type: number
          description: Price in cents
        currency:
          type: string
          description: 'Currency code (default: usd)'
        mediaTypes:
          type: array
          description: Included media types
          items:
            type: string
            enum:
              - PHOTO
              - VIDEO
              - FLOORPLAN
              - DOCUMENT
              - VIRTUAL_TOUR
        turnaroundDays:
          type: number
          description: Turnaround time in days
        photoCount:
          type: number
          description: Number of photos included
        videoMinutes:
          type: number
          description: Minutes of video included
        features:
          description: Feature list
          type: array
          items:
            type: string
        images:
          description: Image URLs
          type: array
          items:
            type: string
        displayOrder:
          type: number
          description: Display order
      required:
        - name
        - price
        - mediaTypes
    UpdatePackageDto:
      type: object
      properties:
        name:
          type: string
          description: Package name
        description:
          type: string
          description: Package description
        price:
          type: number
          description: Price in cents
        currency:
          type: string
          description: Currency code
        mediaTypes:
          type: array
          description: Included media types
          items:
            type: string
            enum:
              - PHOTO
              - VIDEO
              - FLOORPLAN
              - DOCUMENT
              - VIRTUAL_TOUR
        isActive:
          type: boolean
          description: Whether package is active
        turnaroundDays:
          type: number
          description: Turnaround time in days
        photoCount:
          type: number
          description: Number of photos included
        videoMinutes:
          type: number
          description: Minutes of video included
        features:
          description: Feature list
          type: array
          items:
            type: string
        images:
          description: Image URLs
          type: array
          items:
            type: string
        displayOrder:
          type: number
          description: Display order
    CreateAddOnDto:
      type: object
      properties:
        name:
          type: string
          description: Add-on name
        description:
          type: string
          description: Add-on description
        price:
          type: number
          description: Price in cents
        currency:
          type: string
          description: 'Currency code (default: usd)'
        category:
          type: string
          description: Add-on category
          enum:
            - AERIAL
            - TWILIGHT
            - VIRTUAL_TOUR
            - FLOORPLAN
            - RUSH
            - OTHER
        displayOrder:
          type: number
          description: Display order
      required:
        - name
        - price
    UpdateAddOnDto:
      type: object
      properties:
        name:
          type: string
          description: Add-on name
        description:
          type: string
          description: Add-on description
        price:
          type: number
          description: Price in cents
        currency:
          type: string
          description: Currency code
        category:
          type: string
          description: Add-on category
          enum:
            - AERIAL
            - TWILIGHT
            - VIRTUAL_TOUR
            - FLOORPLAN
            - RUSH
            - OTHER
        isActive:
          type: boolean
          description: Whether add-on is active
        displayOrder:
          type: number
          description: Display order
    MediaDto:
      type: object
      properties:
        id:
          type: string
        key:
          type: string
          nullable: true
        cdnUrl:
          type: string
          nullable: true
        externalUrl:
          type: string
          nullable: true
        filename:
          type: string
        size:
          type: number
        type:
          type: object
        createdAt:
          format: date-time
          type: string
      required:
        - id
        - key
        - cdnUrl
        - externalUrl
        - filename
        - size
        - type
        - createdAt
    CommentDto:
      type: object
      properties:
        id:
          type: string
        content:
          type: string
        timestamp:
          format: date-time
          type: string
        user:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            avatarUrl:
              type: string
              nullable: true
          required:
            - id
            - name
      required:
        - id
        - content
        - timestamp
        - user
    DeliveryResponseDto:
      type: object
      properties:
        project:
          type: object
          properties:
            id:
              type: string
            addressLine1:
              type: string
              nullable: true
            city:
              type: string
              nullable: true
            region:
              type: string
              nullable: true
            scheduledTime:
              format: date-time
              type: string
            status:
              type: object
            clientApprovalStatus:
              type: object
            clientApprovedAt:
              format: date-time
              type: string
              nullable: true
            deliveryEnabledAt:
              format: date-time
              type: string
              nullable: true
          required:
            - id
            - addressLine1
            - city
            - region
            - scheduledTime
            - status
            - clientApprovalStatus
            - clientApprovedAt
            - deliveryEnabledAt
        organization:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            logoUrl:
              type: string
              nullable: true
            primaryEmail:
              type: string
              nullable: true
            phone:
              type: string
              nullable: true
          required:
            - id
            - name
            - logoUrl
            - primaryEmail
            - phone
        media:
          type: array
          items:
            $ref: '#/components/schemas/MediaDto'
        comments:
          type: array
          items:
            $ref: '#/components/schemas/CommentDto'
        customer:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            email:
              type: string
              nullable: true
          required:
            - id
            - name
            - email
        canApprove:
          type: boolean
        canComment:
          type: boolean
        downloadEnabled:
          type: boolean
          description: Whether bulk download is available (requires storage backend)
        canRetryArtifact:
          type: boolean
          description: >-
            Whether user can retry failed artifacts (OWNER/ADMIN/PROJECT_MANAGER
            only)
      required:
        - project
        - organization
        - media
        - comments
        - canApprove
        - canComment
        - downloadEnabled
        - canRetryArtifact
    DownloadAllDto:
      type: object
      properties:
        mediaTypes:
          type: array
          description: Filter download by media types
          items:
            type: string
            enum:
              - PHOTO
              - VIDEO
              - FLOORPLAN
              - DOCUMENT
              - VIRTUAL_TOUR
    RequestChangesDto:
      type: object
      properties:
        feedback:
          type: string
          description: Feedback text for requested changes
      required:
        - feedback
    AddCommentDto:
      type: object
      properties:
        content:
          type: string
          description: Comment content
      required:
        - content
    RetryArtifactDto:
      type: object
      properties:
        artifactId:
          type: string
          description: ID of the artifact to retry
      required:
        - artifactId
    UpdateTourProgressDto:
      type: object
      properties:
        tourTrack:
          type: object
        stepId:
          type: string
        completed:
          type: boolean
        skipped:
          type: boolean
      required:
        - tourTrack
        - stepId
