ControlUp Subscriptions API

The Subscriptions API from ControlUp — 27 operation(s) for subscriptions.

OpenAPI Specification

controlup-subscriptions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: DaaS IQ Subscriptions API
  description: 'Multi-cloud Virtual Desktop Infrastructure Management API (Default Version: v1.0)


    🔒 **Authentication**


    This API supports two authentication methods:


    **1. API Key (Bearer Token)** - Recommended for programmatic access

    - Create an API key at [API Key Management](https://support.controlup.com/docs/create-an-api-key)

    - Include in requests: `Authorization: Bearer YOUR_API_KEY`


    **2. Cookie Authentication** - For browser-based access

    - Login via DEX authentication service

    - The `user_dex_token` cookie will be automatically included'
  contact:
    name: ControlUp Support
    url: https://controlup.com/support
    email: support@controlup.com
  version: v1
  x-build-version: 1.0.107
servers:
- url: https://api.controlup.com/daas-iq/v1
tags:
- name: Subscriptions
paths:
  /cloud/subscriptions/{id}/credentials/verify:
    post:
      tags:
      - Subscriptions
      summary: Verify subscription credentials (Deprecated)
      description: "\n<b>DEPRECATED:</b> Use POST /api/v1/cloud/tenants/{tenantId}/credentials/{credentialId}/verify to verify tenant credentials instead.\n            Verifies cloud provider credentials and permissions synchronously. Check the IsSuccess field to determine if credentials are valid."
      operationId: VerifySubscriptionCredentials
      parameters:
      - name: id
        in: path
        description: The unique subscription identifier.
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Verification completed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponse'
              example:
                isSuccess: true
                steps:
                - stepName: Authenticating with Azure AD
                  status: success
                  isSuccess: true
                  durationMs: 450
                - stepName: Listing subscriptions
                  status: success
                  isSuccess: true
                  durationMs: 320
                - stepName: Checking subscription access
                  status: success
                  isSuccess: true
                  durationMs: 180
                - stepName: Verifying Reader role
                  status: warning
                  detail: Role verification not fully implemented
                  isSuccess: false
                  durationMs: 220
                completedAt: '2025-10-09T14:30:00Z'
                durationMs: 1170
        '400':
          description: Bad request. Invalid subscription ID format.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have permission to view subscriptions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified subscription does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      deprecated: true
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{id}/credentials/verify/transcript:
    post:
      tags:
      - Subscriptions
      summary: Verify subscription credentials - transcript (Deprecated)
      description: "\n<b>DEPRECATED:</b> Use POST /api/v1/cloud/tenants/{tenantId}/credentials/{credentialId}/verify/transcript instead.\n            Verifies the connection and permissions with formatted output lines. Check IsSuccess field for result."
      operationId: VerifySubscriptionCredentialsTranscript
      parameters:
      - name: id
        in: path
        description: The unique subscription identifier.
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Verification completed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationTranscriptResponse'
              example:
                isSuccess: true
                output:
                - -- Running validations --
                - '  Authenticating with Azure AD ...... Success ✓'
                - '  Listing subscriptions ............. Success ✓'
                - '  Checking subscription access ...... Success ✓'
                - '  Verifying Reader role ............. Success ✓'
                - -- Validation success --
        '400':
          description: Bad request. Invalid subscription ID.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have subscription management permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified subscription does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      deprecated: true
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{id}/credentials/verify/stream:
    get:
      tags:
      - Subscriptions
      summary: Verify subscription credentials - streaming (Deprecated)
      description: "Streams real-time cloud credentials verification progress over a WebSocket connection using structured JSON messages.\nAll messages are serialized as JSON with camelCase property names and inherit from ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationMessage.\n            \n**Message Types (see Domain.Models.Verification.Messages namespace):**\n- ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationStartedMessage: Verification process begins\n  - Properties: `type`, `timestamp`\n            \n- ControlUp.Foundry.Domain.Models.Verification.Messages.StepStartedMessage: A verification step begins\n  - Properties: `type`, `timestamp`, `stepNumber`, `stepName`\n            \n- ControlUp.Foundry.Domain.Models.Verification.Messages.StepCompletedMessage: A verification step completes\n  - Properties: `type`, `timestamp`, `stepNumber`, `stepName`, `status`, `duration`, `detail`\n  - `status` values: \"success\" | \"warning\" | \"failure\"\n            \n- ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationCompletedMessage: Verification process ends\n  - Properties: `type`, `timestamp`, `success`, `duration`, `errorMessage`\n            \n**Usage Flow:**\n1. Client establishes WebSocket connection to `/api/v1/cloud/subscriptions/{id}/credentials/verify/stream`\n2. Server validates subscription exists and user has permission\n3. Server accepts WebSocket connection (HTTP 101 Switching Protocols)\n4. Server sends ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationStartedMessage\n5. For each verification step (provider-specific):\n   - Server sends ControlUp.Foundry.Domain.Models.Verification.Messages.StepStartedMessage\n   - Server performs verification against cloud provider API\n   - Server sends ControlUp.Foundry.Domain.Models.Verification.Messages.StepCompletedMessage with results\n6. Server sends ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationCompletedMessage\n7. Server closes WebSocket with normal closure or error status\n            \n**WebSocket Client Example (JavaScript):**\n```javascript\nconst subscriptionId = '123e4567-e89b-12d3-a456-426614174000';\nconst ws = new WebSocket(`wss://api.example.com/api/v1/cloud/subscriptions/${subscriptionId}/credentials/verify/stream`);\n            \nws.onopen = () => {\n  console.log('WebSocket connected - waiting for verification to start...');\n};\n            \nws.onmessage = (event) => {\n  const message = JSON.parse(event.data);\n            \n  switch(message.type) {\n    case 'verification_started':\n      console.log('Verification started at:', message.timestamp);\n      // Initialize UI for verification progress\n      break;\n            \n    case 'step_started':\n      console.log(`Step ${message.stepNumber}: ${message.stepName} - started`);\n      // Show spinner/progress indicator for this step\n      break;\n            \n    case 'step_completed':\n      console.log(`Step ${message.stepNumber}: ${message.stepName} - ${message.status} in ${message.duration}`);\n      if (message.detail) {\n        console.log(`  Detail: ${message.detail}`);\n      }\n      // Update UI with status icon: ✓ (success), ⚠ (warning), ✗ (failure)\n      break;\n            \n    case 'verification_completed':\n      console.log(`Verification ${message.success ? 'succeeded' : 'failed'} - Duration: ${message.duration}`);\n      if (message.errorMessage) {\n        console.error(`Error: ${message.errorMessage}`);\n      }\n      // Finalize UI with overall result\n      break;\n            \n    default:\n      console.warn('Unknown message type:', message.type);\n  }\n};\n            \nws.onerror = (error) => {\n  console.error('WebSocket error:', error);\n  // Handle connection errors\n};\n            \nws.onclose = (event) => {\n  console.log(`WebSocket closed - Code: ${event.code}, Reason: ${event.reason}`);\n  // Clean up UI and resources\n};\n```\n            \n**Example Message Sequence (Azure Subscription):**\n```json\n{\"type\":\"verification_started\",\"timestamp\":\"2025-10-23T10:30:00.000Z\"}\n{\"type\":\"step_started\",\"stepNumber\":1,\"stepName\":\"Validating Azure credentials format\",\"timestamp\":\"2025-10-23T10:30:00.100Z\"}\n{\"type\":\"step_completed\",\"stepNumber\":1,\"stepName\":\"Validating Azure credentials format\",\"status\":\"success\",\"duration\":\"00:00:00.150\",\"timestamp\":\"2025-10-23T10:30:00.250Z\"}\n{\"type\":\"step_started\",\"stepNumber\":2,\"stepName\":\"Testing connectivity to Azure Resource Manager\",\"timestamp\":\"2025-10-23T10:30:00.300Z\"}\n{\"type\":\"step_completed\",\"stepNumber\":2,\"stepName\":\"Testing connectivity to Azure Resource Manager\",\"status\":\"success\",\"duration\":\"00:00:01.200\",\"detail\":\"Successfully authenticated with tenant ID: abc123\",\"timestamp\":\"2025-10-23T10:30:01.500Z\"}\n{\"type\":\"step_started\",\"stepNumber\":3,\"stepName\":\"Verifying required Azure permissions\",\"timestamp\":\"2025-10-23T10:30:01.550Z\"}\n{\"type\":\"step_completed\",\"stepNumber\":3,\"stepName\":\"Verifying required Azure permissions\",\"status\":\"failure\",\"duration\":\"00:00:00.800\",\"detail\":\"Missing required role: Virtual Machine Contributor\",\"timestamp\":\"2025-10-23T10:30:02.350Z\"}\n{\"type\":\"verification_completed\",\"success\":false,\"duration\":\"00:00:02.500\",\"errorMessage\":\"Verification failed\",\"timestamp\":\"2025-10-23T10:30:02.500Z\"}\n```\n            \n**Notes:**\n- All timestamps are in ISO 8601 UTC format\n- Duration fields are in TimeSpan format (hh:mm:ss.fffffff)\n- Step numbers are sequential, starting from 1\n- The `detail` field in ControlUp.Foundry.Domain.Models.Verification.Messages.StepCompletedMessage is optional (null for success, may contain info for warnings/failures)\n- WebSocket closes automatically after sending ControlUp.Foundry.Domain.Models.Verification.Messages.VerificationCompletedMessage\n- If an error occurs during verification, the server will attempt to close the WebSocket with appropriate status code"
      parameters:
      - name: id
        in: path
        description: The unique cloud subscription identifier.
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '101':
          description: Switching Protocols - WebSocket connection established.
        '200':
          description: OK
        '400':
          description: Bad request. Invalid subscription ID or not a WebSocket request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have permission to view subscriptions in this organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified cloud subscription does not exist or does not belong to the current organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error occurred during verification.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      deprecated: true
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{id}/credentials/verify/sse:
    post:
      tags:
      - Subscriptions
      summary: Verify subscription credentials - streaming (Deprecated)
      description: '**DEPRECATED:** Use tenant-based credential verification endpoints instead.

        SSE replacement for the WebSocket `/verify/stream` endpoint. Same message format, simpler protocol.'
      parameters:
      - name: id
        in: path
        description: The unique subscription identifier.
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: SSE stream started successfully.
        '400':
          description: Bad request. Invalid tenant ID or tenant has no default credential.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have view tenants permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified tenant does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error occurred during verification.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      deprecated: true
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{subscriptionId}/metadata/regions:
    get:
      tags:
      - Subscriptions
      summary: Get available regions for a subscription
      description: 'Returns the regions the subscription can deploy into, paginated, filterable and sortable.

        Region identity and display names only — availability zones are omitted here and available per region from the single-region lookup.'
      operationId: GetRegions
      parameters:
      - name: subscriptionId
        in: path
        description: The subscription ID.
        required: true
        schema:
          type: string
          format: uuid
      - name: filter
        in: query
        description: 'Optional filter expression.


          Supports JSON and RQL formats:


          - JSON: {"and":[{"field":"status","op":"eq","value":"Active"},{"field":"name","op":"ct","value":"Smith, John"}]}

          - RQL: and(eq(status,Active),ct(name,Smith%2C%20John)) — values are URL-decoded; encode reserved characters


          Operators:

          and, or, not (logical); eq, neq, ct, nct, sw, nsw, ew, new, gt, gte, lt, lte (predicate)


          Fields (names are matched case-insensitively):

          displayName, geography, isPhysical, name, regionalDisplayName, regionCategory'
        schema:
          type: string
        examples:
          json:
            summary: json
            value: '{"field":"name","op":"eq","value":"value"}'
          rql:
            summary: rql
            value: eq(name,value)
        x-foundry-filter:
          fields:
          - displayName
          - geography
          - isPhysical
          - name
          - regionalDisplayName
          - regionCategory
          operators:
            logical:
            - and
            - or
            - not
            predicate:
            - eq
            - neq
            - ct
            - nct
            - sw
            - nsw
            - ew
            - new
            - gt
            - gte
            - lt
            - lte
          dynamicPaths: false
      - name: sort
        in: query
        description: 'Sort expression for ordering results.


          Format:

          field:direction,otherField:direction


          Directions: asc, desc, ascending, descending — defaults to ascending when omitted


          Fields (names are matched case-insensitively):

          displayName, geography, isPhysical, name, regionalDisplayName, regionCategory


          Default when omitted: displayName:asc.'
        schema:
          type: string
        examples:
          default:
            summary: default
            value: displayName:asc
        x-foundry-sort:
          fields:
          - displayName
          - geography
          - isPhysical
          - name
          - regionalDisplayName
          - regionCategory
          dynamicPaths: false
          defaultField: displayName
          defaultAscending: true
      - name: page
        in: query
        description: 'The page number to retrieve (1-based). Default: 1.'
        schema:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
      - name: pageSize
        in: query
        description: 'The number of items per page (1-100). Default: 50.'
        schema:
          maximum: 100
          minimum: 1
          type: integer
          format: int32
      responses:
        '200':
          description: Successfully retrieved regions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionMetadataDtoPagedResultDto'
        '400':
          description: Bad request. Invalid subscription ID or filter/sort parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have view subscriptions permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified subscription does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{subscriptionId}/metadata/regions/{region}:
    get:
      tags:
      - Subscriptions
      summary: Get region metadata
      description: 'Returns one named region''s metadata in the subscription''s context, including the availability zones that the region list omits.

        Describes a single region rather than enumerating which regions are available.'
      operationId: GetRegionMetadata
      parameters:
      - name: subscriptionId
        in: path
        description: The subscription ID.
        required: true
        schema:
          type: string
          format: uuid
      - name: region
        in: path
        description: Region code.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Successfully retrieved region metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionMetadataDto'
        '400':
          description: Bad request. Subscription ID is invalid or region is missing or blank.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized. User is not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required. No active license for the organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden. User does not have view subscriptions permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not found. The specified subscription or region does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable. License status could not be verified. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
      - BearerAuth: []
      - CookieAuth: []
  /cloud/subscriptions/{subscriptionId}/metadata/vm-sizes:
    get:
      tags:
      - Subscriptions
      summary: Get available VM sizes for a region with filtering, sorting, and pagination support
      description: 'Returns the VM SKUs offered in a region with full specifications: CPU count, memory, disk limits, IOPS, and capability flags.

        Describes what each SKU is capable of, not whether the subscription has quota left to deploy one.

        Supports filtering, sorting, and pagination for large result sets.'
      operationId: GetVmSizes
      parameters:
      - name: subscriptionId
        in: path
        description: The subscription ID.
        required: true
        schema:
          type: string
          format: uuid
      - name: region
        in: query
        description: 'Azure region/location (e.g., "eastus", "westeurope").

          Required.'
        required: true
        schema:
          maxLength: 64
          type: string
      - name: filter
        in: query
        description: 'Optional filter expression.


          Supports JSON and RQL formats:


          - JSON: {"and":[{"field":"status","op":"eq","value":"Active"},{"field":"name","op":"ct","value":"Smith, John"}]}

          - RQL: and(eq(status,Active),ct(name,Smith%2C%20John)) — values are URL-decoded; encode reserved characters


          Operators:

          and, or, not (logical); eq, neq, ct, nct, sw, nsw, ew, new, gt, gte, lt, lte (predicate)


          Fields (names are matched case-insensitively):

          cores, cpuArchitectureType, displayName, family, isRestricted, localStorageBytes, maxDataDisks, maxIops, maxNetworkInterfaces, memoryBytes, name, osDiskSizeBytes, size, supportsAcceleratedNetworking, supportsDiskControllerNVMe, supportsDiskControllerSCSI, supportsEphemeralOSDisk, supportsHyperVGenerationV1, supportsHyperVGenerationV2, supportsPremiumStorage, supportsTrustedLaunch, tier'
        schema:
          type: string
        examples:
          json:
            summary: json
            value: '{"field":"name","op":"eq","value":"value"}'
          rql:
            summary: rql
            value: eq(name,value)
        x-foundry-filter:
          fields:
          - cores
          - cpuArchitectureType
          - displayName
          - family
          - isRestricted
          - localStorageBytes
          - maxDataDisks
          - maxIops
          - maxNetworkInterfaces
          - memoryBytes
          - name
          - osDiskSizeBytes
          - size
          - supportsAcceleratedNetworking
          - supportsDiskControllerNVMe
          - supportsDiskControllerSCSI
          - supportsEphemeralOSDisk
          - supportsHyperVGenerationV1
          - supportsHyperVGenerationV2
          - supportsPremiumStorage
          - supportsTrustedLaunch
          - tier
          operators:
            logical:
            - and
            - or
            - not
            predicate:
            - eq
            - neq
            - ct
            - nct
            - sw
            - nsw
            - ew
            - new
            - gt
            - gte
            - lt
            - lte
          dynamicPaths: false
      - name: sort
        in: query
        description: 'Sort expression for ordering results.


          Format:

          field:direction,otherField:direction


          Directions: asc, desc, ascending, descending — defaults to ascending when omitted


          Fields (names are matched case-insensitively):

          cores, cpuArchitectureType, displayName, family, isRestricted, localStorageBytes, maxDataDisks, maxIops, maxNetworkInterfaces, memoryBytes, name, osDiskSizeBytes, size, supportsAcceleratedNetworking, supportsDiskControllerNVMe, supportsDiskControllerSCSI, supportsEphemeralOSDisk, supportsHyperVGenerationV1, supportsHyperVGenerationV2, supportsPremiumStorage, supportsTrustedLaunch, tier


          Default when omitted: name:asc.'
        schema:
          type: string
        examples:
          default:
            summary: default
            value: name:asc
        x-foundry-sort:
          fields:
          - cores
          - cpuArchitectureType
          - displayName
          - family
          - isRestricted
          - localStorageBytes
          - maxDataDisks
          - maxIops
          - maxNetworkInterfaces
          - memoryBytes
          - name
          - osDiskSizeBytes
          - size
          - supportsAcceleratedNetworking
          - supportsDiskControllerNVMe
          - supportsDiskControllerSCSI
          - supportsEphemeralOSDisk
          - supportsHyperVGenerationV1
          - supportsHyperVGenerationV2
          - supportsPremiumStorage
          - supportsTrustedLaunch
          - tier
          dynamicPaths: false
          defaultField: name
          defaultAscending: true
      - name: page
        in: query
        description: 'The page number to retrieve (1-based). Default: 1.'
        schema:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
      - name: pageSize
        in: query
        description: 'The number of items per page (1-100). Default: 50.'
        schema:
          maximum: 100
          minimum: 1
          type: integer
          format: int32
      responses:
        '200':
          description: Successfully retrieved VM sizes.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VmSizeDtoPagedResultDto'
              example:
                items:
                - name: Standard_D2s_v5
                  displayName: Standard D2s_v5
                  tier: Standard
                  size: D2s_v5
                  cores: 2
                  memoryBytes: 8589934592
                  maxDataDisks: 4
                  osDiskSizeBytes: 1098437885952
                  localStorageBytes: 0
                  family: standardDSv5Family
                  maxIops: 3750
                  maxNetworkInterfaces: 2
                  supportsPremiumStorage: true
                  supportsAcceleratedNetworking: true
                  supportsEphemeralOSDisk: true
                  supportsTrustedLaunch: true
                  availableZones:
                  - '1'
                  - '2'
                  - '3'
                  hyperVGenerations:
                  - V1
                  - V2
                  diskControllerTypes:
                  - SCSI
                  cpuArchitectureType: x64
                  supportsHyperVGenerationV1: true
                  supportsHyperVGenerationV2: true
                  supportsDiskControllerSCSI: true
                  supportsDiskControllerNVMe: false
                  isRestricted: false
                - name: Standard_D2s_v6
                  displayName: Standard D2s_v6
                  tier: Standard
                  size: D2s_v6
                  cores: 2
                  memoryBytes: 8589934592
       

# --- truncated at 32 KB (227 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/controlup/refs/heads/main/openapi/controlup-subscriptions-api-openapi.yml