ControlUp Jobs API
The Jobs API from ControlUp — 8 operation(s) for jobs.
The Jobs API from ControlUp — 8 operation(s) for jobs.
openapi: 3.2.0
info:
title: DaaS IQ Jobs 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: Jobs
paths:
/jobs/{jobId}:
get:
tags:
- Jobs
summary: Get a job by ID
description: 'Returns one job''s full record: status, progress, current step, and error details.
Does not include the job''s input parameters, and is heavier than the status-only payload — prefer that for repeated polling.
Regular users can only access jobs they initiated. Admins can access any job in their organization.'
operationId: GetJob
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Successfully retrieved the job.
content:
application/json:
schema:
$ref: '#/components/schemas/JobDto'
example:
errors: []
initiatedBy: user@example.com
initiationType: userInitiated
createdAt: '2026-08-02T03:32:44.6319791Z'
startedAt: '2026-08-02T03:33:44.631992Z'
id: a1b2c3d4-5678-90ab-cdef-1234567890ab
jobType: cloudResourceImport
action: Cloud Resource Import
status: inProgress
progress: 45
currentStep: Gathering resource data (45/100)
cancellationRequested: false
canRetry: false
'400':
description: Bad request. Invalid job 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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
/jobs/{jobId}/parameters:
get:
tags:
- Jobs
summary: Get job parameters
description: 'Returns the raw input parameters a job was created with, as a JSON object whose structure depends on JobType.
Carries the inputs only — no status, progress, or errors.
Regular users can only access parameters for jobs they initiated. Admins can access any job in their organization.'
operationId: GetJobParameters
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Successfully retrieved job parameters.
content:
application/json:
schema:
type: object
additionalProperties: {}
description: 'Documentation-only response shape for job parameters: a free-form JSON object whose keys depend
on the job''s type. Never instantiated — the endpoint writes the stored JSON to the response.'
'204':
description: Job exists but has no parameters.
'400':
description: Bad request. Invalid job 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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
/jobs:
get:
tags:
- Jobs
summary: Get jobs
description: 'Returns a paginated list of jobs for the current organization, each row carrying the job ID that per-job operations require.
Regular users see only their own jobs. Admins see all user-initiated jobs, and system-scheduled background jobs only when includeSystemJobs=true.
Rows carry no job parameters and no logs.'
operationId: GetJobs
parameters:
- 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):
action, cancellationRequested, cancellationRequestedAt, completedAt, createdAt, currentStep, errorCode, id, initiatedBy, initiationType, jobType, parentJobId, progress, retryOfJobId, retryRequestedBy, startedAt, status, targetResource, targetResourceName
Default when omitted: createdAt:desc.'
schema:
type: string
example: status:asc,createdAt:desc
examples:
default:
summary: default
value: createdAt:desc
x-foundry-sort:
fields:
- action
- cancellationRequested
- cancellationRequestedAt
- completedAt
- createdAt
- currentStep
- errorCode
- id
- initiatedBy
- initiationType
- jobType
- parentJobId
- progress
- retryOfJobId
- retryRequestedBy
- startedAt
- status
- targetResource
- targetResourceName
dynamicPaths: false
defaultField: createdAt
defaultAscending: false
- name: filter
in: query
description: 'Filter expression for filtering results.
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):
action, cancellationRequested, cancellationRequestedAt, completedAt, createdAt, currentStep, errorCode, id, initiatedBy, initiationType, jobType, parentJobId, progress, retryOfJobId, retryRequestedBy, startedAt, status, targetResource, targetResourceName'
schema:
maxLength: 512
type: string
example: and(eq(status,active),gte(progress,50))
examples:
json:
summary: json
value: '{"field":"action","op":"eq","value":"value"}'
rql:
summary: rql
value: eq(action,value)
x-foundry-filter:
fields:
- action
- cancellationRequested
- cancellationRequestedAt
- completedAt
- createdAt
- currentStep
- errorCode
- id
- initiatedBy
- initiationType
- jobType
- parentJobId
- progress
- retryOfJobId
- retryRequestedBy
- startedAt
- status
- targetResource
- targetResourceName
operators:
logical:
- and
- or
- not
predicate:
- eq
- neq
- ct
- nct
- sw
- nsw
- ew
- new
- gt
- gte
- lt
- lte
dynamicPaths: false
- 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
- name: includeSystemJobs
in: query
description: 'Whether to include system-scheduled background jobs (admin-only, default: false).'
schema:
type: boolean
default: false
responses:
'200':
description: Successfully retrieved jobs.
content:
application/json:
schema:
$ref: '#/components/schemas/JobPartialDtoPagedResultDto'
'400':
description: Bad request. Invalid pagination or 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 access to this organization.
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: []
/jobs/{jobId}/status:
get:
tags:
- Jobs
summary: Get job status
description: 'Returns six fields only — id, jobType, status, progress, currentStep, cancellationRequested — as the cheapest way to poll a running job.
Omits error details, parameters, and logs, so it cannot explain why a job failed.'
operationId: GetJobStatus
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Successfully retrieved job status.
content:
application/json:
schema:
$ref: '#/components/schemas/JobStatusDto'
example:
id: a1b2c3d4-5678-90ab-cdef-1234567890ab
jobType: cloudResourceImport
action: Cloud Resource Import
status: inProgress
progress: 45
currentStep: Gathering resource data (45/100)
cancellationRequested: false
canRetry: false
'400':
description: Bad request. Invalid job 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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
/jobs/{jobId}/cancel:
post:
tags:
- Jobs
summary: Cancel a job
description: 'Requests cancellation of a background job. The job will stop at the next safe checkpoint.
Regular users can only cancel jobs they initiated. Admins can cancel any job in their organization.'
operationId: CancelJob
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Cancellation requested successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/JobCancellationResponseDto'
'400':
description: Bad request. Invalid job ID, or Job cannot be cancelled (already completed, failed, or cancelled).
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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
/jobs/{jobId}/retry:
post:
tags:
- Jobs
summary: Retry a failed job
description: 'Creates a new job by retrying a previously failed job with the same parameters.
The original failed job remains as a historical record. The new retry job is linked
to the original via RetryOfJobId for traceability.
Only failed jobs whose type is registered as user-retriable can be retried, and a concurrency guard
permits just one active retry per original job.'
operationId: RetryJob
parameters:
- name: jobId
in: path
description: The ID of the failed job to retry.
required: true
schema:
type: string
format: uuid
responses:
'201':
description: Retry job created successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/JobCreatedDto'
example:
id: a1b2c3d4-5678-90ab-cdef-1234567890ab
jobType: cloudResourceImport
action: Cloud Resource Import
jobUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab
statusUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab/status
logsUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab/logs
message: Import job created successfully. Poll statusUrl for progress updates.
'400':
description: Bad request. Invalid job ID, or Job is not failed or job type is not retriable.
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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict. An active retry is already in progress for this job.
content:
application/json:
schema:
$ref: '#/components/schemas/JobCreatedDto'
example:
id: a1b2c3d4-5678-90ab-cdef-1234567890ab
jobType: cloudResourceImport
action: Cloud Resource Import
jobUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab
statusUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab/status
logsUrl: https://api.example.com/api/v1/jobs/a1b2c3d4-5678-90ab-cdef-1234567890ab/logs
message: Import job created successfully. Poll statusUrl for progress updates.
'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: []
/jobs/{jobId}/logs:
get:
tags:
- Jobs
summary: Get job logs
description: 'Returns a job''s user-facing log entries as structured JSON, oldest first, with cursor-based pagination via after and limit.
Structured records suited to filtering or incremental tailing, as opposed to the plain-text transcript of the same logs.'
operationId: GetJobLogs
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
- name: after
in: query
description: 'Cursor for pagination — returns logs with ID greater than this value.
Null returns from the beginning.'
schema:
type: integer
format: int64
- name: limit
in: query
description: 'Maximum number of logs to return (default: 100, max: 1000).'
schema:
maximum: 1000
minimum: 1
type: integer
format: int32
default: 100
responses:
'200':
description: Successfully retrieved job logs.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/JobLogDto'
example:
- id: 1
loggedAt: '2026-08-02T03:27:44.6618295Z'
severity: info
message: Starting resource import
phase: Initialization
- id: 2
loggedAt: '2026-08-02T03:28:44.6618295Z'
severity: info
message: Discovered 50 resources to import
phase: Discovery
- id: 3
loggedAt: '2026-08-02T03:32:44.6618295Z'
severity: info
message: Gathered data for 25/50 resources
phase: Gathering
- id: 4
loggedAt: '2026-08-02T03:33:44.6618295Z'
severity: warning
message: 'Failed to gather data for resource: Permission denied'
phase: Gathering
- id: 5
loggedAt: '2026-08-02T03:37:44.6618295Z'
severity: success
message: Successfully imported 49 of 50 resources
phase: Completion
'400':
description: Bad request. Invalid job ID, or limit or cursor parameter.
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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
/jobs/{jobId}/logs/transcript:
get:
tags:
- Jobs
summary: Get job logs transcript
description: 'Returns the same log entries as a streamed plain-text document for reading or download (no cursor, so no incremental tailing).
Success is `text/plain`; validation, not-found, and forbidden responses are `application/json` like other Jobs endpoints.'
operationId: GetJobLogsTranscript
parameters:
- name: jobId
in: path
description: The job ID.
required: true
schema:
type: string
format: uuid
- name: limit
in: query
description: 'Maximum number of logs to include in the transcript (default: 1000, max: 10000).'
schema:
maximum: 10000
minimum: 1
type: integer
format: int32
default: 1000
responses:
'200':
description: Successfully retrieved job logs as plain text transcript.
content:
text/plain:
schema:
type: string
application/json:
schema:
type: string
'400':
description: Bad request. Invalid job ID or limit parameter.
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 access to this job.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The specified job 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: []
components:
schemas:
JobType:
enum:
- cloudResourceImport
- inventorySync
- metricCollection
- costCollection
- budgetCollection
- sessionStateCollection
- sessionHostAction
- cloudResourceAction
- cloudCredentialVerification
- cloudTenantResourceImport
- masterImageDeploy
- masterImagePublish
- masterImageSync
- masterImageCleanup
- masterImageVersionDelete
- masterImagePublishCleanup
- licenseUsageReport
- hostPoolOrphanedResourcesCleanup
- hostPoolCreate
- hostPoolSessionHostCreate
- hostPoolSessionHostBatchCreate
- hostPoolDelete
type: string
description: 'Defines the types of background jobs supported by the system.
Each job type is processed by a specific worker and has its own parameter structure.'
JobInitiationType:
enum:
- userInitiated
- systemScheduled
type: string
description: 'Indicates how a job was initiated - by a user action or by a system scheduler.
Used to filter job lists in UI and apply different retention policies.'
JobStatus:
enum:
- queued
- inProgress
- completed
- failed
- cancelled
type: string
description: 'Generic status enum for all background jobs.
Represents the lifecycle states common to all job types.'
JobCancellationResponseDto:
required:
- jobId
- message
type: object
properties:
jobId:
type: string
description: Identifier of the job the cancellation was requested for.
format: uuid
message:
type: string
description: 'Human-readable confirmation that the request was accepted.
Cancellation is cooperative, so the job stops at its next safe checkpoint rather than immediately.'
additionalProperties: false
description: Response returned when cancellation of a job has been requested.
JobLogDto:
required:
- id
- loggedAt
- message
- severity
type: object
properties:
id:
type: integer
description: 'Unique identifier for this log entry (for cursor-based pagination).
Use this value in the ''after'' query parameter to get subsequent logs.'
format: int64
loggedAt:
type: string
description: Timestamp when this log entry was created.
format: date-time
severity:
$ref: '#/components/schemas/JobLogSeverity'
message:
type: string
description: User-facing message describing what happened.
phase:
type:
- string
- 'null'
description: 'Optional phase/stage of job execution.
Examples: "Discovery", "Gathering", "Saving", "Finalizing"'
additionalProperties: false
description: Represents a user-facing log entry for a background job.
ErrorResponse:
required:
- status
- title
- traceId
type: object
properties:
type:
type:
- string
- 'null'
description: A URI reference that identifies the problem type.
title:
type: string
description: A short, human-readable summary of the problem type.
status:
type: integer
description: The HTTP status code.
format: int32
detail:
type:
- string
- 'null'
description: A human-readable explanation specific to this occurrence of the problem.
instance:
type:
- string
- 'null'
description: A URI reference that identifies the specific occurrence of the problem.
errors:
type:
- object
- 'null'
additionalProperties:
type: array
items:
type: string
description: 'Dictionary of field-specific validation errors (only present for validation failures).
Key is the field name, value is an array of error messages for that field.
# --- truncated at 32 KB (47 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/controlup/refs/heads/main/openapi/controlup-jobs-api-openapi.yml