ControlUp Jobs API
The Jobs API from ControlUp — 8 operation(s) for jobs.
The Jobs API from ControlUp — 8 operation(s) for jobs.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/controlup-jobs-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
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:
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.
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.'
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.
JobCreatedDto:
required:
- action
- id
- jobType
- jobUrl
- logsUrl
- message
- statusUrl
type: object
properties:
id:
type: string
description: Unique identifier for the created job.
format: uuid
jobType:
$ref: '#/components/schemas/JobType'
action:
type: string
description: 'Job action identifier.
For standard jobs, this matches the JobType formatted with spaces (e.g., "Cloud Resource Import").
For action jobs, this is the specific action name formatted with spaces (e.g., "Start", "Stop").'
jobUrl:
type: string
description: URL to get full job details (includes parameters).
statusUrl:
type: string
description: 'URL to poll for lightweight status updates (no parameters).
Poll this endpoint every 2-5 seconds while job is running.'
logsUrl:
type: string
description: URL to get job logs in JSON format.
message:
type: string
description: 'Human-readable message about job creation.
Example: "Import job created successfully. Poll statusUrl for progress updates."'
additionalProperties: false
description: 'Lightweight response returned when a job is created.
Contains only essential information needed to track the job.
Use the statusUrl to poll for updates and jobUrl to get full details.'
JobDto:
required:
- action
- cancellationRequested
- canRetry
- createdAt
- errors
- id
- initiatedBy
- initiationType
- jobType
- progress
- status
type: object
properties:
id:
type: string
description: Unique identifier for the job.
format: uuid
jobType:
$ref: '#/components/schemas/JobType'
action:
type: string
description: 'Job action identifier.
For standard jobs, this matches the JobType formatted with spaces (e.g., "Cloud Resource Import").
For action jobs, this is the specific action name formatted with spaces (e.g., "Start", "Stop").'
status:
# --- 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