> ## Documentation Index
> Fetch the complete documentation index at: https://docs.msportal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Get technician capacity forecast

> Technician capacity against demand for this quarter and the next ones. Demand is the ticket run rate (average weekly ticket hours over the last 13 complete weeks), remaining budget on open project tasks and open Planner item hours weighted by probability. Work up to 90 days overdue lands in this quarter; work with no dates or more than 90 days overdue is reported as unscheduled. Per-technician rows are included only for callers with technician performance access. companyId limits demand to those clients; capacity always covers the whole team. vCIO advisory hours are not included. Staff only; requires `analytics.read`, read_msp_calculators and the technician_capacity feature.



## OpenAPI

````yaml /openapi.json get /api/public/v1/analytics/technician-forecast
openapi: 3.0.3
info:
  title: MSPortal Public API
  version: 1.0.0
  description: >-
    Public API for MSPortal - provides programmatic access to tenant data.


    ## Authentication


    All endpoints require authentication via API key passed as a Bearer token:


    ```

    Authorization: Bearer <your-api-key>

    ```


    API keys can be created in the MSPortal dashboard under Settings →
    Integrations → API Access.


    **Important:** Do not include cookies in API requests. The public API uses
    stateless authentication only.


    ## Scopes


    API keys are granted specific scopes that determine what operations they can
    perform. Each endpoint documents its required scope(s).


    ## Rate Limiting


    API calls are rate limited per API key. Rate limit information is returned
    in response headers:


    - `X-RateLimit-Limit`: Maximum requests per minute

    - `X-RateLimit-Remaining`: Remaining requests in current window

    - `X-RateLimit-Reset`: When the rate limit resets (ISO 8601)


    ## Request ID


    All responses include an `X-Request-Id` header for debugging and support.
    You can also pass your own `X-Request-Id` header to correlate requests.
  contact:
    name: MSPortal Support
    email: support@msportal.ai
  license:
    name: Proprietary
servers:
  - url: https://app.msportal.ai
    description: Production (US)
  - url: https://eu.msportal.ai
    description: Production (EU)
security:
  - BearerAuth: []
tags:
  - name: Budgets
    description: >-
      Budget management - create, track, and forecast budgets with line items,
      categories, and products
  - name: Calendar
    description: Calendar and meeting management - events, participants, and meeting types
  - name: Companies
    description: Company management endpoints
  - name: Company Users
    description: Company user management - client portal contacts (read-only, paginated)
  - name: Compliance
    description: Compliance check management - runs, assigned checks, and status updates
  - name: Dashboards
    description: Dashboard management - external iframe resources and internal dashboards
  - name: Devices
    description: Device management - inventory, types, and locations
  - name: Goals
    description: Goal management - create, track, and manage goals with tasks and updates
  - name: NPS Surveys
    description: >-
      NPS survey management - Net Promoter Score surveys, responses, and
      analytics
  - name: Reports
    description: >-
      Report management - create, manage, and schedule reports with templates
      and types
  - name: Planner
    description: >-
      Planner item management - tasks, roadmap items, and project planning with
      linked goals, compliance, and projects
  - name: Surveys
    description: >-
      General survey management - multi-question surveys, responses, and
      statistics
  - name: Tickets
    description: Ticket management - view and filter tickets from PSA integrations
  - name: Training
    description: >-
      Training management - courses, enrollments, certificates, and progress
      tracking
  - name: Users
    description: Tenant user management - internal staff and team members (read-only)
  - name: Automation Rules
    description: >-
      Automation rule management - create, configure, and monitor automation
      rules with triggers, conditions, and actions
  - name: Analytics
    description: >-
      Analytics and reporting - company audit data, training analytics, user
      activity, and portfolio metrics
  - name: Client Onboarding
    description: >-
      Client onboarding - portals (phases, tasks, contacts, activation),
      templates, checklist templates, forms and documentation pages
  - name: Backup
    description: >-
      Backup - summaries, protected devices, alerts and SaaS protection (Datto,
      Axcient, Slide, Kaseya)
  - name: Microsoft 365
    description: Microsoft 365 - licenses, users, domains and Secure Score
  - name: Security
    description: >-
      Security - posture summary, EDR incidents, vulnerabilities, email threats,
      firewalls, DNS filtering and security awareness
  - name: Financial
    description: Financial - quotes, invoices and revenue summaries
  - name: Integrations
    description: Integrations - status, sync health, pause and resume (never credentials)
  - name: Documentation
    description: >-
      Documentation - pages, folders and articles synced from Hudu or IT Glue,
      plus built-in pages
  - name: Broadcasts
    description: Broadcasts - emergency broadcasts, recipients and groups
  - name: Notifications
    description: Notifications - the linked user's in-app notifications
  - name: Standards
    description: >-
      Standards - technology standards catalog, service plans, applicability,
      deployment statuses, compliance rollups, white space and costs
  - name: Customer Success
    description: >-
      Customer success - client health scores, trends, benchmarks and Traffic
      Light Reviews
  - name: Tasks
    description: Tasks - the linked user's personal task list
  - name: Tenant Setup
    description: Tenant setup - profile, branding and portal settings (never secrets)
  - name: Roles
    description: Roles - staff and client roles and their permission grants
  - name: Ticket Templates
    description: Ticket templates - reusable ticket definitions
  - name: Readiness
    description: Client readiness - account readiness assessments
  - name: Projects
    description: >-
      Projects - PSA projects with health overlays (deliverables, milestones,
      client actions, weekly updates), phases, tickets, time entries, PSA
      status/owner/priority write-through, ticket notes, task controls, display
      settings and the document library
paths:
  /api/public/v1/analytics/technician-forecast:
    get:
      tags:
        - Analytics
      summary: Get technician capacity forecast
      description: >-
        Technician capacity against demand for this quarter and the next ones.
        Demand is the ticket run rate (average weekly ticket hours over the last
        13 complete weeks), remaining budget on open project tasks and open
        Planner item hours weighted by probability. Work up to 90 days overdue
        lands in this quarter; work with no dates or more than 90 days overdue
        is reported as unscheduled. Per-technician rows are included only for
        callers with technician performance access. companyId limits demand to
        those clients; capacity always covers the whole team. vCIO advisory
        hours are not included. Staff only; requires `analytics.read`,
        read_msp_calculators and the technician_capacity feature.
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 8
            description: Quarters to forecast, starting with this one (default 4)
          required: false
          description: Quarters to forecast, starting with this one (default 4)
          name: quarters
          in: query
        - schema:
            type: array
            items:
              type: string
              format: uuid
            maxItems: 100
            description: Limit to one or more companies (repeat the key or comma-separate)
          required: false
          description: Limit to one or more companies (repeat the key or comma-separate)
          name: companyId
          in: query
      responses:
        '200':
          description: Technician forecast
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TechnicianForecast'
                required:
                  - data
        '400':
          description: Invalid query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Forbidden - missing scope (analytics.read) or read_msp_calculators,
            the endpoint is staff-only, or the technician_capacity feature is
            off
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - BearerAuth: []
components:
  schemas:
    TechnicianForecast:
      type: object
      properties:
        companyFiltered:
          type: boolean
        individualFiguresIncluded:
          type: boolean
        runRateFromWeeks:
          type: integer
        quarters:
          type: array
          items:
            type: object
            properties:
              label:
                type: string
                description: For example Q3 2026
              start:
                type: string
              endExclusive:
                type: string
              weeksLeft:
                type: number
                description: Remaining days / 7, two decimals
              team:
                type: object
                properties:
                  capacityHours:
                    type: number
                  demandHours:
                    type: number
                  ticketRunRateHours:
                    type: number
                  projectHours:
                    type: number
                  plannerHours:
                    type: number
                  unassignedHours:
                    type: number
                    description: Work nobody owns (team cells only)
                  loadPct:
                    type: number
                    nullable: true
                  status:
                    type: string
                    enum:
                      - over_capacity
                      - near_capacity
                      - within_capacity
                      - no_capacity
                      - idle
                required:
                  - capacityHours
                  - demandHours
                  - ticketRunRateHours
                  - projectHours
                  - plannerHours
                  - unassignedHours
                  - loadPct
                  - status
              unassigned:
                type: object
                properties:
                  capacityHours:
                    type: number
                  demandHours:
                    type: number
                  ticketRunRateHours:
                    type: number
                  projectHours:
                    type: number
                  plannerHours:
                    type: number
                  unassignedHours:
                    type: number
                    description: Work nobody owns (team cells only)
                  loadPct:
                    type: number
                    nullable: true
                  status:
                    type: string
                    enum:
                      - over_capacity
                      - near_capacity
                      - within_capacity
                      - no_capacity
                      - idle
                required:
                  - capacityHours
                  - demandHours
                  - ticketRunRateHours
                  - projectHours
                  - plannerHours
                  - unassignedHours
                  - loadPct
                  - status
            required:
              - label
              - start
              - endExclusive
              - weeksLeft
              - team
              - unassigned
        unscheduledHours:
          type: number
          description: Work with no dates or more than 90 days overdue
        unassignedUnscheduledHours:
          type: number
        technicians:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              source:
                type: string
                enum:
                  - connectwise
                  - halo
                  - autotask
                  - msportal
              userId:
                type: string
                nullable: true
                format: uuid
              role:
                type: string
                enum:
                  - technician
                  - engineer
                  - vcio
              counted:
                type: boolean
              stillActive:
                type: boolean
              ownsWorkWithoutLoggedTime:
                type: boolean
              weeklyCapacityHours:
                type: number
              ticketRunRateHoursPerWeek:
                type: number
              unscheduledHours:
                type: number
              quarters:
                type: object
                additionalProperties:
                  type: object
                  properties:
                    capacityHours:
                      type: number
                    demandHours:
                      type: number
                    ticketRunRateHours:
                      type: number
                    projectHours:
                      type: number
                    plannerHours:
                      type: number
                    unassignedHours:
                      type: number
                      description: Work nobody owns (team cells only)
                    loadPct:
                      type: number
                      nullable: true
                    status:
                      type: string
                      enum:
                        - over_capacity
                        - near_capacity
                        - within_capacity
                        - no_capacity
                        - idle
                  required:
                    - capacityHours
                    - demandHours
                    - ticketRunRateHours
                    - projectHours
                    - plannerHours
                    - unassignedHours
                    - loadPct
                    - status
                description: Keyed by quarter label
            required:
              - name
              - source
              - userId
              - role
              - counted
              - stillActive
              - ownsWorkWithoutLoggedTime
              - weeklyCapacityHours
              - ticketRunRateHoursPerWeek
              - unscheduledHours
              - quarters
      required:
        - companyFiltered
        - individualFiguresIncluded
        - runRateFromWeeks
        - quarters
        - unscheduledHours
        - unassignedUnscheduledHours
        - technicians
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message
        requestId:
          type: string
          description: Request correlation ID
        details:
          nullable: true
          description: Additional error details
        code:
          type: string
          description: Error code
      required:
        - error
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Use your API key as a Bearer token. API keys can be generated in
        Settings → Integrations → API Access.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.