openapi: 3.1.0
info:
  title: mATRIC API
  summary: REST API for the Multi Access Technology Intelligent Controller
  description: >

    mATRIC unifies 5G, WiFi and LiFi under a single management framework. This
    API is

    the interface to the platform for three kinds of caller, each authenticating

    through the same token endpoint with its own login type.


    **Users** manage the platform. Administrators register agents and third
    party

    applications, and manage user accounts. Anyone may register through the
    public

    signup endpoint and receives a standard user role.


    **Agents** run on access points. Each agent authenticates, onboards itself
    with

    its configuration and geolocation, and then posts telemetry on a regular

    schedule.


    **Third party applications** consume the platform. They request the details
    of

    active agents, retrieve historical data for a chosen agent and time range,
    and

    send commands back to the network. Results and subscribed data streams
    return

    through callback endpoints identified by a job number.


    Every call except authentication and public registration requires a bearer

    token in the Authorization header.
  contact:
    name: Smart Internet Lab, University of Bristol
    url: https://www.bristol.ac.uk/engineering/research/smart/
  license:
    name: BSD 3 Clause Licence
    url: https://github.com/mATRIC-Platforms/mATRIC-master/blob/master/LICENSE
  version: 1.0.0
paths:
  /api/v1/token/:
    post:
      tags:
        - token
      summary: Login
      operationId: login_api_v1_token__post
      parameters:
        - name: login_type
          in: query
          required: true
          schema:
            type: string
            description: 'Login type: user, agent or third_party_app'
            title: Login Type
          description: 'Login type: user, agent or third_party_app'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Body_login_api_v1_token__post'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/public:
    post:
      tags:
        - users
      summary: Create First User
      operationId: create_first_user_api_v1_users_public_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/signup:
    post:
      tags:
        - users
      summary: Register User
      operationId: register_user_api_v1_users_signup_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserRegister'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/password-recovery:
    post:
      tags:
        - users
      summary: Recover Password
      operationId: recover_password_api_v1_users_password_recovery_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PasswordRecoveryRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Recover Password Api V1 Users Password Recovery Post
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/reset-password:
    post:
      tags:
        - users
      summary: Reset Password
      operationId: reset_password_api_v1_users_reset_password_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PasswordReset'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Reset Password Api V1 Users Reset Password Post
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/:
    get:
      tags:
        - users
      summary: List Users
      operationId: list_users_api_v1_users__get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                items:
                  $ref: '#/components/schemas/TokenData'
                type: array
                title: Response List Users Api V1 Users  Get
      security:
        - OAuth2PasswordBearer: []
    post:
      tags:
        - users
      summary: Create User
      operationId: create_user_api_v1_users__post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/users/{username}:
    put:
      tags:
        - users
      summary: Update User
      operationId: update_user_api_v1_users__username__put
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
            title: Username
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserUpdate'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    delete:
      tags:
        - users
      summary: Delete User
      operationId: delete_user_api_v1_users__username__delete
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
            title: Username
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Delete User Api V1 Users  Username  Delete
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    get:
      tags:
        - users
      summary: Get User
      operationId: get_user_api_v1_users__username__get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
            title: Username
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/users/me:
    get:
      tags:
        - users
      summary: Read Users Me
      operationId: read_users_me_api_v1_users_me_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenData'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/agents/public:
    post:
      tags:
        - agents
      summary: Create First Agent
      operationId: create_first_agent_api_v1_agents_public_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentCreate'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/agents/:
    post:
      tags:
        - agents
      summary: Create Agent
      operationId: create_agent_api_v1_agents__post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentCreate'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/agents/{ap_id}:
    get:
      tags:
        - agents
      summary: Get Agent
      operationId: get_agent_api_v1_agents__ap_id__get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: ap_id
          in: path
          required: true
          schema:
            type: string
            title: Ap Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    put:
      tags:
        - agents
      summary: Update Agent
      operationId: update_agent_api_v1_agents__ap_id__put
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: ap_id
          in: path
          required: true
          schema:
            type: string
            title: Ap Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentUpdate'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    delete:
      tags:
        - agents
      summary: Delete Agent
      operationId: delete_agent_api_v1_agents__ap_id__delete
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: ap_id
          in: path
          required: true
          schema:
            type: string
            title: Ap Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Delete Agent Api V1 Agents  Ap Id  Delete
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/third_party_apps/:
    post:
      tags:
        - third_party_apps
      summary: Create Third Party App
      operationId: create_third_party_app_api_v1_third_party_apps__post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ThirdPartyAppCreate'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThirdPartyApp'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/third_party_apps/{app_name}:
    get:
      tags:
        - third_party_apps
      summary: Get Third Party App
      operationId: get_third_party_app_api_v1_third_party_apps__app_name__get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: app_name
          in: path
          required: true
          schema:
            type: string
            title: App Name
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThirdPartyApp'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    put:
      tags:
        - third_party_apps
      summary: Update Third Party App
      operationId: update_third_party_app_api_v1_third_party_apps__app_name__put
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: app_name
          in: path
          required: true
          schema:
            type: string
            title: App Name
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ThirdPartyAppUpdate'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThirdPartyApp'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
    delete:
      tags:
        - third_party_apps
      summary: Delete Third Party App
      operationId: delete_third_party_app_api_v1_third_party_apps__app_name__delete
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: app_name
          in: path
          required: true
          schema:
            type: string
            title: App Name
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: >-
                  Response Delete Third Party App Api V1 Third Party Apps  App
                  Name  Delete
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/agent_update/update:
    post:
      tags:
        - agent_update
      summary: Update Agent
      description: Endpoint to handle agent updates.
      operationId: update_agent_api_v1_agent_update_update_post
      requestBody:
        content:
          application/json:
            schema:
              type: object
              title: Data
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Update Agent Api V1 Agent Update Update Post
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/agent_details/request_all_agents_details:
    post:
      tags:
        - agent_details
      summary: Request All Agents Details
      description: |-
        Endpoint to request details for all agents.
        Only authenticated users and third-party apps can access this.
      operationId: >-
        request_all_agents_details_api_v1_agent_details_request_all_agents_details_post
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
      security:
        - OAuth2PasswordBearer: []
  /api/v1/agent_data/request_agent_data:
    post:
      tags:
        - agent_data
      summary: Request Agent Data
      description: |-
        Endpoint to request agent data for a specific period.
        Both authenticated agents and users can request agent data.
      operationId: request_agent_data_api_v1_agent_data_request_agent_data_post
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: agent_id
          in: query
          required: true
          schema:
            type: string
            title: Agent Id
        - name: start_time
          in: query
          required: true
          schema:
            type: string
            format: date-time
            title: Start Time
        - name: end_time
          in: query
          required: true
          schema:
            type: string
            format: date-time
            title: End Time
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/send_command:
    post:
      tags:
        - send_command
      summary: Send Command To Agent
      description: Endpoint to send a command to a specific agent.
      operationId: send_command_to_agent_api_v1_send_command_post
      parameters:
        - name: agent_id
          in: query
          required: true
          schema:
            type: string
            title: Agent Id
        - name: command
          in: query
          required: true
          schema:
            type: string
            title: Command
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/emulator/spinup:
    post:
      tags:
        - emulator
      summary: Spinup Emulators
      description: >-
        - Auth required (user or app).

        - Creates emulator agents using DatabaseManager.add_agent with hashed
        passwords.

        - Normalises locations to lat/lon and stores them ONLY in
        agent.configuration.geolocation.

        - Publishes a job to RabbitMQ (routing key: emulator_spinup) including
        agent creds and locations.
      operationId: spinup_emulators_api_v1_emulator_spinup_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmulatorSpinupRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - OAuth2PasswordBearer: []
  /api/v1/metrics/agent_details:
    get:
      tags:
        - metrics
      summary: Agent Details
      description: |-
        Return agents directly from the database with these fields:
        id, ap_id, configuration, onboard.
      operationId: agent_details_api_v1_metrics_agent_details_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
      security:
        - OAuth2PasswordBearer: []
  /api/v1/metrics/agent_data:
    get:
      tags:
        - metrics
      summary: Get Agent Data
      description: >-
        Pull time series for one agent using your exact InfluxDB reader (JWT
        required).

        Works only with the agent's ap_id. Returns the key from Influx as 'key'.
      operationId: get_agent_data_api_v1_metrics_agent_data_get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            description: >-
              Agent ap_id (exact value used in Influx measurement
              'agent/<ap_id>/data')
            title: Agent
          description: >-
            Agent ap_id (exact value used in Influx measurement
            'agent/<ap_id>/data')
        - name: window
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: integer
            description: Window size, for example 1, 5, 10 (minutes) or '1h'
            default: 5
            title: Window
          description: Window size, for example 1, 5, 10 (minutes) or '1h'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/metrics/agent_multi_metric_data:
    get:
      tags:
        - metrics
      summary: Get Agent Multi Metric Data
      description: >-
        Return time series for **multiple metrics** for a given agent over the
        same time window.


        This is the endpoint the real time chart will call once per second.

        The frontend can select many metrics; we fetch them in a single Influx
        query and

        group by metric (field) server-side.


        Response shape:

        {
          "agent_id": "<ap_id>",
          "window_minutes": <int>,
          "series": [
            { "metric": "throughput", "points": [ { "ts": "...", "value": 123.4 }, ... ] },
            { "metric": "latency",    "points": [ ... ] },
            ...
          ]
        }
      operationId: get_agent_multi_metric_data_api_v1_metrics_agent_multi_metric_data_get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            description: >-
              Agent ap_id (same value used in Influx measurement
              'agent/<ap_id>/data')
            title: Agent
          description: >-
            Agent ap_id (same value used in Influx measurement
            'agent/<ap_id>/data')
        - name: metrics
          in: query
          required: true
          schema:
            type: array
            items:
              type: string
            description: >-
              Metric names (Influx 'field' values). Can be repeated, e.g.
              metrics=throughput&metrics=latency, or a single comma separated
              string.
            title: Metrics
          description: >-
            Metric names (Influx 'field' values). Can be repeated, e.g.
            metrics=throughput&metrics=latency, or a single comma separated
            string.
        - name: window
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: integer
            description: Window size, for example 1, 5, 10 (minutes) or '1h'
            default: 5
            title: Window
          description: Window size, for example 1, 5, 10 (minutes) or '1h'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/metrics/agent_metrics:
    get:
      tags:
        - metrics
      summary: List Agent Metrics
      description: >-
        Return the list of metric names (Influx 'field' values) available for
        this agent

        in the given time window. Used by the frontend to populate the checkbox
        list.


        Response:

        {
          "agent_id": "<ap_id>",
          "window_minutes": <int>,
          "metrics": [
            { "name": "aa", "label": "aa" },
            { "name": "bb", "label": "bb" },
            ...
          ]
        }
      operationId: list_agent_metrics_api_v1_metrics_agent_metrics_get
      security:
        - OAuth2PasswordBearer: []
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            description: >-
              Agent ap_id (same value used in Influx measurement
              'agent/<ap_id>/data')
            title: Agent
          description: >-
            Agent ap_id (same value used in Influx measurement
            'agent/<ap_id>/data')
        - name: window
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: integer
            description: >-
              Window size for discovering metrics, e.g. 1, 5, 10 (minutes) or
              '1h'
            default: 5
            title: Window
          description: Window size for discovering metrics, e.g. 1, 5, 10 (minutes) or '1h'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/callback/agent_data:
    post:
      tags:
        - agent_data_callback
      summary: Agent Data Callback
      description: >-
        Callback endpoint to receive agent data from the subscriber.

        The data will be sent to the WebSocket client identified by the
        job_number.
      operationId: agent_data_callback_api_v1_callback_agent_data_post
      parameters:
        - name: job_number
          in: query
          required: true
          schema:
            type: string
            title: Job Number
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items: {}
              title: Data
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/callback/agent_details:
    post:
      tags:
        - agent_details_callback
      summary: Agent Details Callback
      description: >-
        HTTP callback endpoint to receive agent details from the subscriber.


        If a WebSocket is already connected for this job_number, the data is
        sent

        immediately.


        If NOT, we queue the data in pending_messages so it can be sent as soon

        as the WebSocket connects (avoids race conditions).
      operationId: agent_details_callback_api_v1_callback_agent_details_post
      parameters:
        - name: job_number
          in: query
          required: true
          schema:
            type: string
            title: Job Number
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
              title: Agent Details
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/callback/emulator:
    post:
      tags:
        - emulator_callback
      summary: Agent Details Callback
      description: >-
        HTTP callback endpoint to receive agent details from the subscriber.


        If a WebSocket is already connected for this job_number, the data is
        sent

        immediately.


        If NOT, we queue the data in pending_messages so it can be sent as soon

        as the WebSocket connects (avoids race conditions).
      operationId: agent_details_callback_api_v1_callback_emulator_post
      parameters:
        - name: job_number
          in: query
          required: true
          schema:
            type: string
            title: Job Number
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
              title: Agent Details
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    Agent:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        ap_id:
          type: string
          title: Ap Id
        configuration:
          type: object
          title: Configuration
      type: object
      required:
        - id
        - ap_id
        - configuration
      title: Agent
    AgentCreate:
      properties:
        ap_id:
          type: string
          title: Ap Id
        password:
          type: string
          title: Password
        configuration:
          type: object
          title: Configuration
      type: object
      required:
        - ap_id
        - password
        - configuration
      title: AgentCreate
    AgentUpdate:
      properties:
        password:
          anyOf:
            - type: string
            - type: 'null'
          title: Password
        configuration:
          anyOf:
            - type: object
            - type: 'null'
          title: Configuration
      type: object
      title: AgentUpdate
    Body_login_api_v1_token__post:
      properties:
        grant_type:
          anyOf:
            - type: string
              pattern: password
            - type: 'null'
          title: Grant Type
        username:
          type: string
          title: Username
        password:
          type: string
          title: Password
        scope:
          type: string
          title: Scope
          default: ''
        client_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Client Id
        client_secret:
          anyOf:
            - type: string
            - type: 'null'
          title: Client Secret
      type: object
      required:
        - username
        - password
      title: Body_login_api_v1_token__post
    EmulatorSpec:
      properties:
        access_point_type:
          type: string
          pattern: ^(5G|WiFi|LiFi)$
          title: Access Point Type
        num_access_points:
          type: integer
          maximum: 1000
          exclusiveMinimum: 0
          title: Num Access Points
        locations:
          items:
            type: string
          type: array
          title: Locations
        num_devices:
          type: integer
          exclusiveMinimum: 0
          title: Num Devices
        duration:
          type: integer
          exclusiveMinimum: 0
          title: Duration
      type: object
      required:
        - access_point_type
        - num_access_points
        - locations
        - num_devices
        - duration
      title: EmulatorSpec
    EmulatorSpinupRequest:
      properties:
        emulators:
          items:
            $ref: '#/components/schemas/EmulatorSpec'
          type: array
          title: Emulators
      type: object
      required:
        - emulators
      title: EmulatorSpinupRequest
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    PasswordRecoveryRequest:
      properties:
        username:
          type: string
          format: email
          title: Username
      type: object
      required:
        - username
      title: PasswordRecoveryRequest
    PasswordReset:
      properties:
        token:
          type: string
          title: Token
        new_password:
          type: string
          title: New Password
      type: object
      required:
        - token
        - new_password
      title: PasswordReset
    ThirdPartyApp:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        app_name:
          type: string
          title: App Name
        api_key:
          type: string
          title: Api Key
        permissions:
          type: object
          title: Permissions
      type: object
      required:
        - id
        - app_name
        - api_key
        - permissions
      title: ThirdPartyApp
    ThirdPartyAppCreate:
      properties:
        app_name:
          type: string
          title: App Name
        api_key:
          type: string
          title: Api Key
        permissions:
          type: object
          title: Permissions
      type: object
      required:
        - app_name
        - api_key
        - permissions
      title: ThirdPartyAppCreate
    ThirdPartyAppUpdate:
      properties:
        api_key:
          anyOf:
            - type: string
            - type: 'null'
          title: Api Key
        permissions:
          anyOf:
            - type: object
            - type: 'null'
          title: Permissions
      type: object
      title: ThirdPartyAppUpdate
    Token:
      properties:
        access_token:
          type: string
          title: Access Token
        token_type:
          type: string
          title: Token Type
        expires_in:
          type: integer
          title: Expires In
      type: object
      required:
        - access_token
        - token_type
        - expires_in
      title: Token
    TokenData:
      properties:
        username:
          anyOf:
            - type: string
            - type: 'null'
          title: Username
        roles:
          type: string
          title: Roles
        scopes:
          items:
            type: string
          type: array
          title: Scopes
          default: []
      type: object
      required:
        - roles
      title: TokenData
    UserCreate:
      properties:
        username:
          type: string
          format: email
          title: Username
        password:
          type: string
          title: Password
        roles:
          items:
            type: string
          type: array
          title: Roles
      type: object
      required:
        - username
        - password
        - roles
      title: UserCreate
    UserRegister:
      properties:
        username:
          type: string
          format: email
          title: Username
        password:
          type: string
          title: Password
      type: object
      required:
        - username
        - password
      title: UserRegister
    UserUpdate:
      properties:
        password:
          anyOf:
            - type: string
            - type: 'null'
          title: Password
        roles:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Roles
      type: object
      title: UserUpdate
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - BearerAuth: []
