Skip to content

Jobs

Jobs are the fundamental structure for organizing content and data within Vision. Each Job is associated with a single customer, customer location, and work order number. One or more workflows can be assigned to a Job to define the steps to be taken during the process of working that Job. Read about getJobSummary for more information about how multiple workflows are represented when summarizing jobs.

NOTE: There are some technical details about the relationship between jobs and workflows noted below.

API URLs

  • Testing: https://gql-jobs-external.staging.xoeye.com/graphql
  • Production: https://gql-jobs-external.xoi.io/graphql

Creating a Job

Example Request

The following mutation will create a Job and return specific fields about the newly created Job. You'll want to make sure to request the ID of the job as part of your request so that you can store it for later use.

If you cannot persist the Vision Job ID in your system upon creation of the job, you can include an integrationEntityId in your createJob input. Vision Jobs can be retrieved via this external ID (see this query for details), but the external ID must be resolved to a Vision Job ID for the other queries and mutations described here. Details about the fields required are provided here.

If you know that you're going to need a public share immediately upon job creation, you can request to have that share created as part of the createJob process. See additionalActions and additionalActionsResults in the example below.

Note that assigneeIds takes a list of Vision User IDs, but is currently enforced as a single item list. We plan to soon have the ability to have multiple Assignees per Job, so we are ensuring we do not need to change the API when that time comes.

See the CreateJobInput schema for the details of what is required for this request.

mutation CreateJob {
  createJob(
    input: {
      newJob: {
        assigneeIds: ["a-tech@your-org.com"]
        customerName: "Some Customer"
        jobLocation: "Some Location"
        workOrderNumber: "Some Workorder"
        label: "A human-friendly identifier"
        tags: ["tag1", "tag2"]
        tagSuggestions: ["tag3", "tag4"]
        integrationEntityId: {
          namespace: "AtLeast10Characters"
          id: "ShouldBeUniqueInYourSystem"
        }
        internalNote: { text: "A note about the job." }
      }
      additionalActions: { createPublicShare: { enabled: true } }
    }
  ) {
    job {
      id
      createdAt
      createdBy
      assigneeIds
      customerName
      jobLocation
      workOrderNumber
      label
      tags
      tagSuggestions
      deepLinks {
        visionMobile {
          editJob {
            url
          }
          jobLocationActivitySearch {
            url
          }
        }
        integrationEntityId {
          namespace
          id
        }
        internalNote {
          text
        }
      }
    }
    additionalActionsResults {
      createPublicShare {
        shareLink
      }
    }
  }
}

Example Response

The id included in this response is the unique ID created by XOi Cloud, and should be stored in your system for retrieving the job later.

See the JobResult schema for the details of what to expect in your response.

{
  "data": {
    "createJob": {
      "job": {
        "id": "458c-d887fee6358a4daf9ed7c38c14b2c444",
        "createdAt": "2020-02-13T18:23:33.323616Z",
        "createdBy": "some-vision-user-id",
        "assigneeIds": ["a-tech@your-org.com"],
        "customerName": "Some Customer",
        "jobLocation": "Some Location",
        "workOrderNumber": "Some Workorder",
        "label": "A human-friendly identifier",
        "tags": ["tag1", "tag2"],
        "tagSuggestions": ["tag3", "tag4"],
        "deepLinks": {
          "visionMobile": {
            "editJob": {
              "url": "xoi-vision://my-work/edit?payload=%7B%22jobId%22%3A%20%22458c-d887fee6358a4daf9ed7c38c14b2c444%22%2C%20%22jobLocation%22%3A%20%22Some%20Location%22%2C%20%22workOrderNumber%22%3A%20%22Some%20Workorder%22%2C%20%22owner%22%3A%20%22a-tech%40your-org.com%22%2C%20%22customerName%22%3A%20%22Some%20Customer%22%7D"
            },
            "jobLocationActivitySearch": {
              "url": "xoi-vision://activity/search?payload=%7B%22exactMatchAllTags%22%3A%20%5B%22some%20location%22%5D%7D"
            }
          }
        },
        "integrationEntityId": {
          "namespace": "AtLeast10Characters",
          "id": "ShouldBeUniqueInYourSystem"
        },
        "internalNote": {
          "text": "A note about the job."
        }
      },
      "additionalActionsResults": {
        "createPublicShare": {
          "id": "is307a3eb",
          "shareLink": "https://visionshare.xoi.io/?id=is307a3eb"
        }
      }
    }
  }
}

Retrieving a Job

Example Request

A Vision Job id can be used to directly retrieve a job.

See the GetJobInput schema for the details of what is required for this request.

query GetJob {
  getJob(input: { id: "a-vision-job-id" }) {
    job {
      id
      createdAt
      createdBy
      assigneeIds
      customerName
      jobLocation
      workOrderNumber
      label
      tags
      tagSuggestions
      deepLinks {
        visionWeb {
          viewJob {
            url
          }
        }
        visionMobile {
          viewJob {
            url
          }
          editJob {
            url
          }
          jobLocationActivitySearch {
            url
          }
        }
      }
    }
  }
}

Special note about retrieving a workflow job

Using a Workflow Job id in the getJob query will return information about a Workflow Job. All returned information is specific to the requested Workflow Job. The customerName, jobLocation, and workOrderNumber fields will be empty because they are set at the Container Job level. We do not support deep links into a Workflow Job, therefore deepLinks will return null. Please see the technical details about Workflow Jobs below for more information.

Example Response

The response here is the same response you get from the createJob mutation.

See the JobResult schema for the details of what to expect in your response.

Note: Although viewJob deepLinks are returned in this example, they will only be present for a completed job.

{
  "data": {
    "getJob": {
      "job": {
        "id": "458c-d887fee6358a4daf9ed7c38c14b2c444",
        "createdAt": "2020-02-13T18:23:33.323616Z",
        "createdBy": "some-vision-user-id",
        "assigneeIds": ["a-tech@your-org.com"],
        "customerName": "Some Customer",
        "jobLocation": "Somewhere, USA",
        "workOrderNumber": "Workorder #123",
        "label": "A human-friendly identifier",
        "tags": ["tag1", "tag2"],
        "tagSuggestions": ["tag3", "tag4"],
        "deepLinks": {
          "visionWeb": {
            "viewJob": {
              "url": "https://visionweb.xoi.io/jobactivity/458c-d887fee6358a4daf9ed7c38c14b2c444"
            }
          },
          "visionMobile": {
            "viewJob": {
              "url": "xoi-vision://activity/view?payload=%7B%22jobId%22%3A%20%22458c-d887fee6358a4daf9ed7c38c14b2c444%22%7D"
            },
            "editJob": {
              "url": "xoi-vision://my-work/edit?payload=%7B%22jobId%22%3A%20%22458c-d887fee6358a4daf9ed7c38c14b2c444%22%2C%20%22jobLocation%22%3A%20%22Some%20Location%22%2C%20%22workOrderNumber%22%3A%20%22Some%20Workorder%22%2C%20%22owner%22%3A%20%22a-tech%40your-org.com%22%2C%20%22customerName%22%3A%20%22Some%20Customer%22%7D"
            },
            "jobLocationActivitySearch": {
              "url": "xoi-vision://activity/search?payload=%7B%22exactMatchAllTags%22%3A%20%5B%22some%20location%22%5D%7D"
            }
          }
        }
      }
    }
  }
}

Updating a Job

Example Request

You can update an existing job using the job's id.

Note that, just as with createJob, assigneeIds takes a list of Vision User IDs, but is currently enforced as a single item list.

See the UpdateJobInput schema for the details of which fields can be updated.

mutation UpdateJob {
  updateJob(
    input: {
      id: "458c-d887fee6358a4daf9ed7c38c14b2c444"
      fieldUpdates: {
        customerName: "Some Customer"
        jobLocation: "Some Location"
        workOrderNumber: "Some Workorder"
        label: "A human-friendly identifier"
        tags: ["tag1", "tag2"]
        tagSuggestions: ["tag3", "tag4"]
        internalNote: { text: "A note about the job." }
        assigneeIds: ["a-different-tech@your-org.com"]
      }
    }
  ) {
    job {
      id
      createdAt
      createdBy
      assigneeIds
      customerName
      jobLocation
      workOrderNumber
      label
      tags
      tagSuggestions
      internalNote {
        text
      }
      deepLinks {
        visionWeb {
          viewJob {
            url
          }
        }
        visionMobile {
          viewJob {
            url
          }
          editJob {
            url
          }
          jobLocationActivitySearch {
            url
          }
        }
      }
    }
  }
}

Example Response

See the UpdateJobResult schema for the details of what to expect in your response.

Note: Although viewJob deepLinks are returned in this example, they will only be present for a completed job.

{
  "data": {
    "updateJob": {
      "job": {
        "id": "458c-d887fee6358a4daf9ed7c38c14b2c444",
        "createdAt": "2020-02-13T18:23:33.323616Z",
        "createdBy": "some-vision-user-id",
        "assigneeIds": ["a-different-tech@your-org.com"],
        "customerName": "Some Customer",
        "jobLocation": "Some Location",
        "workOrderNumber": "Some Workorder",
        "label": "A human-friendly identifier",
        "tags": ["tag1", "tag2"],
        "tagSuggestions": ["tag3", "tag4"],
        "internalNote": {
          "text": "A note about the jobs."
        },
        "deepLinks": {
          "visionWeb": {
            "viewJob": {
              "url": "https://visionweb.xoi.io/jobactivity/458c-d887fee6358a4daf9ed7c38c14b2c444"
            }
          },
          "visionMobile": {
            "viewJob": {
              "url": "xoi-vision://activity/view?payload=%7B%22jobId%22%3A%20%22458c-d887fee6358a4daf9ed7c38c14b2c444%22%7D"
            },
            "editJob": {
              "url": "xoi-vision://my-work/edit?payload=%7B%22jobId%22%3A%20%22458c-d887fee6358a4daf9ed7c38c14b2c444%22%2C%20%22jobLocation%22%3A%20%22Some%20Location%22%2C%20%22workOrderNumber%22%3A%20%22Some%20Workorder%22%2C%20%22owner%22%3A%20%22a-tech%40your-org.com%22%2C%20%22customerName%22%3A%20%22Some%20Customer%22%7D"
            },
            "jobLocationActivitySearch": {
              "url": "xoi-vision://activity/search?payload=%7B%22exactMatchAllTags%22%3A%20%5B%22some%20location%22%5D%7D"
            }
          }
        }
      }
    }
  }
}

Getting a List of Jobs

A list of jobs can be retrieved using the listJobs query. This list can be filtered using the dateQuery parameters to limit responses to those jobs either created or completed within the specified timespan. Additionally, by specifying a workOrderNumber in the filter input, jobs can be limited to those associated with a given work order.

For backward compatibility, until the multiple workflows per job feature is enabled for a given API user account, Container Jobs will be excluded from the listing. Since the createJob mutation is similarly restricted from creating Container Jobs until that setting is changed, this should never result in any jobs created via the API being excluded.

The limit parameter determines the maximum number of results to be returned in a single request. If additional results are present, a nextToken will be returned and can be passed into a subsequent request to retrieve the next page of results. Due to how filtering is implemented (especially Container Job filtering), it is possible that fewer results may be returned in a given page than the specified limit value. Rely on the presence of a nextToken to determine if additional pages are present.

NOTE: There are some additional technical details about Container Jobs at the end of this document.

See the ListJobsInput schema for the details of what is required for this request.

Listing Jobs Example (without a dateQuery filter)

Without submitting any dateQuery input, you're going to receive Jobs in descending order by the createdAt datetime field.

query ListJobs {
  listJobs(input: { limit: 2 }) {
    jobConnection {
      nextToken
      items {
        id
      }
    }
  }
}

Listing Completed Jobs Example

If you need to get only completed jobs, you can add dateQuery to your input, and set the type as shown below. You can also then choose to return the results in either ascending or descending order.

query ListJobs {
  listJobs(
    input: {
      dateQuery: { type: COMPLETED_AT, ascending: true }
      limit: 2
      nextToken: ""
    }
  ) {
    jobConnection {
      nextToken
      items {
        id
      }
    }
  }
}

Filtering Jobs returned Example

You can use the filter input either by itself, or in conjunction with dateQuery. The following example uses filter by itself. The available filter values can be found in the FilterInput documentation.

Note the current available filters are workOrderNumber, jobLocation, customerName.

query ListJobs {
  listJobs(
    input: {
      filter: { workOrderNumber: "workorder number 1" }
      limit: 10
      nextToken: ""
    }
  ) {
    jobConnection {
      nextToken
      items {
        id
      }
    }
  }
}

Example Response

Since the above query only requested the id for each job, the items below only contain the id. Feel free to add more fields to your query. Each entry in the items list is a Job, so all Job fields are available.

See the ListJobsResult schema for the details of what to expect in your response.

{
  "data": {
    "listJobs": {
      "jobConnection": {
        "nextToken": "eyJGcm9tIjogMjB9",
        "items": [
          { "id": "job-383fa6f1-4529-an26-bf0643febebe-ua78-d2b63615af99" },
          { "id": "job-66390d23-4529-an26-27d949279aa1-ua78-5f5648207a75" }
        ]
      }
    }
  }
}

Getting Summary Information About a Job

Due to the complex nature of a Job within XOi Cloud, we provide the ability to retrieve aggregated summary data about a Job. The information available through this query will be augmented as needs arise from integration partners.

The getJobSummary's documentation list contains content uploaded to any step within the workflows associated with the request job. Additionally, responses to any step types that collection information (such as short text entry, numeric entry, or date entry) are included.

For these step responses, a trait is added to the documentation list item to indicate the type of the step and can be used to determine which sub-structures on the entry contain relevant data. For example, if a note is present, a note trait will be included and the note can be retrieved via the note property. The various other step types will contain specific properties and a matching trait. See the schema for more information on these properties and traits:

  • note -- a textual note
  • choice -- chosen option for a Yes/No or multiple choice step
  • text_entry -- a short textual answer
  • number_entry -- a numeric entry and an associated unit
  • date_entry -- a calendar date value

By default, only items that include a trait will be returned. By setting includeAllSteps to true when retrieving the job summary, even empty steps will be included in the results.

The documentation list returned will include documentation from all workflows when multiple workflows are assigned to the requested job. Each documentation item will contain information about the workflow with which it is associated. Any documentation items that have both a content summary and transcript will utilize the content summary as the transcript. If no content summary is found then the transcribed transcript will be returned.

The XOi mobile app allows a technician to either use AI to generate a work summary based on questions and answers from the workflow, or to write up a work summary on their own if they'd rather not use AI. Either way the work summary is generated, it will be available through getJobSummary as a documentation item. We will use traits to distinguish work summaries that are AI generated from ones the technician generates on their own. If the technician generated the summary, there will be a trait of user_generated present. If the summary was generated by AI, then the trait will be ai_generated. If the summary was generated by AI, but the technician edited the summary, then user_edited will be present along with ai_generated. Since a work summary is provided at the workflow level as opposed to the step, these documentation items will not have values for stepIndex or stepName. Similarly, they are not related to a content record, so they will not have a contentId value either.

It is possible to filter the results to a single workflow within a job. To do so, pass both the job's ID (as id) and the Workflow's ID (as workflowJobId) when making the request. See the schema for more details.

The supportStatuses field provides visibility into the current support status of any workflows associated with the job being viewed. Support Status must be enabled in a given workflow to enable this particular field. supportStatus contains a list of such statuses, identified using a workflowJobId. Each entry in the list contains the status along with information about how the status was last set. If an agent was responsible for setting the status, an agentInfo entry with information about that agent (currently just their email) will be present. In some situations, such as when the system sets the default status of NEW, no agent is responsible for the change and therefore none is supplied. See the schema for more details on how this list is structured.

If more documentation items are present than can be returned in a single page of results, nextToken will be returned along with the results. Passing this nextToken value into an additional request will return the next page of results. To retrieve all values, continue passing in the returned nextToken until no nextToken is returned, which will occur on the final page.

NOTE: There are some technical details about the relationship between jobs and workflows noted below.

Example Requests

Retrieving a Job Summary

The following query will return all of the dataplates and transcripts available for a given Job as well as traits that help describe the state of data. If multiple workflows are assigned to the job, data from all of them will be summarized.

In addition to information about the content associated with a given job, information about the assignee can also be returned. See the schema for details.

See the GetJobSummaryInput schema for the details of what is required for this request.

query GetJobSummary {
  getJobSummary(input: { jobId: "a-vision-job-id" }) {
    nextToken
    jobSummary {
      jobId
      documentation {
        workflowName
        traits
        tags
        note {
          text
        }
        choice {
          chosen
        }
        derivedData {
          make
          model
          serial
          transcript
          manufacture_date
        }
        workSummary
      }
      assignees {
        id
        email
        given_name
        family_name
      }
    }
  }
}

Filtering a Job Summary by Workorder

The following query will return the same data as the prior example, but will only do so for information assocated with the specified workflow.

See the GetJobSummaryInput schema for the details of what is required for this request.

query GetJobSummary {
  getJobSummary(
    input: {
      jobId: "a-vision-job-id"
      workflowJobId: "a-vision-workflow-job-id"
    }
  ) {
    nextToken
    jobSummary {
      jobId
      documentation {
        workflowName
        traits
        tags
        derivedData {
          make
          model
          serial
          transcript
          manufacture_date
        }
      }
    }
  }
}

Example Responses

See the GetJobSummaryResult schema for the details of what to expect in your response.

The dataplate and all transcripts are currently in-process. Notes were requested and were present on one step.

{
  "data": {
    "getJobSummary": {
      "nextToken": "",
      "jobSummary": {
        "jobId": "a-vision-job-id",
        "documentation": [
          {
            "workflowName": "Gather Information",
            "traits": ["dataplate", "pending"],
            "tags": ["tag1", "tag2"],
            "derivedData": null,
            "note": null
          },
          {
            "workflowName": "Gather Information",
            "traits": ["transcript", "pending"],
            "derivedData": null,
            "note": null
          },
          {
            "workflowName": "Install Equipment",
            "traits": ["note"],
            "derivedData": null,
            "note": { "text": "Some comments related to the installation." }
          },
          {
            "workflowName": "Install Equipment",
            "traits": ["transcript", "pending"],
            "derivedData": null,
            "note": null
          }
        ]
      }
    }
  }
}

There are partial results for the dataplate.

{
  "data": {
    "getJobSummary": {
      "nextToken": "",
      "jobSummary": {
        "jobId": "a-vision-job-id",
        "documentation": [
          {
            "workflowName": "Gather Information",
            "traits": ["dataplate", "pending", "partial_dataplate"],
            "tags": ["tag1", "tag2"],
            "derivedData": {
              "make": "Carrier",
              "model": "Some Model",
              "serial": "",
              "transcript": "",
              "manufacture_date": ""
            }
          },
          {
            "workflowName": "Gather Information",
            "traits": ["transcript", "pending"],
            "derivedData": null
          },
          {
            "workflowName": "Install Equipment",
            "traits": ["transcript", "pending"],
            "derivedData": null
          }
        ]
      }
    }
  }
}

The dataplate has been processed, but not all transcripts have been.

{
  "data": {
    "getJobSummary": {
      "nextToken": "",
      "jobSummary": {
        "jobId": "a-vision-job-id",
        "documentation": [
          {
            "workflowName": "Gather Information",
            "traits": ["dataplate", "processed"],
            "tags": ["tag1", "tag2"],
            "derivedData": {
              "make": "Carrier",
              "model": "Some Model",
              "serial": "ABC12345",
              "transcript": "",
              "manufacture_date": "2020-01-01"
            }
          },
          {
            "workflowName": "Gather Information",
            "traits": ["transcript", "processed"],
            "derivedData": {
              "make": "",
              "model": "",
              "serial": "",
              "transcript": "The text extracted from a video.",
              "manufacture_date": ""
            }
          },
          {
            "workflowName": "Install Equipment",
            "traits": ["transcript", "pending"],
            "derivedData": null
          }
        ]
      }
    }
  }
}

All dataplates and transcripts are fully processed.

{
  "data": {
    "getJobSummary": {
      "nextToken": "",
      "jobSummary": {
        "jobId": "a-vision-job-id",
        "documentation": [
          {
            "workflowName": "Gather Information",
            "traits": ["dataplate", "processed"],
            "tags": ["tag1", "tag2"],
            "derivedData": {
              "make": "Carrier",
              "model": "Some Model",
              "serial": "ABC12345",
              "transcript": "",
              "manufacture_date": "2020-01-01"
            }
          },
          {
            "workflowName": "Gather Information",
            "traits": ["transcript", "processed"],
            "derivedData": {
              "make": "",
              "model": "",
              "serial": "",
              "transcript": "The text extracted from a video.",
              "manufacture_date": ""
            }
          },
          {
            "workflowName": "Install Equipment",
            "traits": ["transcript", "processed"],
            "derivedData": {
              "make": "",
              "model": "",
              "serial": "",
              "transcript": "The text extracted from a different video.",
              "manufacture_date": ""
            }
          }
        ]
      }
    }
  }
}

An image was uploaded that was expected to be a dataplate, but was not identified as such. No transcripts are expected.

{
  "data": {
    "getJobSummary": {
      "nextToken": "",
      "jobSummary": {
        "jobId": "a-vision-job-id",
        "documentation": [
          {
            "workflowName": "Gather Information",
            "traits": ["dataplate", "processed", "not_a_dataplate"],
            "tags": ["tag1", "tag2"],
            "derivedData": {
              "make": "",
              "model": "",
              "serial": "",
              "transcript": "",
              "manufacture_date": ""
            }
          }
        ]
      }
    }
  }
}

Getting Documentation from Multiple Jobs

Similar to a combination of getJobSummary and listJobs, this query returns a list of documentation items based on filter criteria that are applied to the parent jobs. See the notes for those queries to learn more about supplying filters to the request (see listJobs) or the traits and properties of the response (see getJobSummary).

Note: includeAllSteps functions here as it does for getJobSummary.

query ListDocumentation {
  listDocumentation(
    input: { nextToken: "", filter: { jobLocation: "wisconsin" } }
  ) {
    documentationConnection {
      items {
        jobId
        workflowJobId
        derivedData {
          make
          model
        }
      }
      nextToken
    }
  }
}

Example Response

{
  "data": {
    "listDocumentation": {
      "documentationConnection": {
        "items": [
          {
            "jobId": "cjob-68b7bfda-cb57-44136fa3-32e0485abf42-C095-943ccb2e2061",
            "workflowJobId": "wjob-3dc06f0c-cb57-44136fa3-20a5454e88cc-C095-3bb88d3b0eb5",
            "derivedData": null
          },
          {
            "jobId": "cjob-68b7bfda-cb57-44136fa3-32e0485abf42-C095-943ccb2e2061",
            "workflowJobId": "wjob-3dc06f0c-cb57-44136fa3-20a5454e88cc-C095-3bb88d3b0eb5",
            "derivedData": null
          },
          {
            "jobId": "cjob-7031ff0b-cb57-44136fa3-a8894fb0953f-C095-6a96f7ebe2cc",
            "workflowJobId": "wjob-5804b376-cb57-44136fa3-e506465ea0b9-C095-9163a7251dd2",
            "derivedData": {
              "make": "trane",
              "model": "test"
            }
          }
        ],
        "nextToken": ""
      }
    }
  }
}

Deleting a Job

Example Request

The following mutation will delete the job with the given ID, if that job exists. There are no extra input parameters for this mutation. An id is all that is required.

mutation {
  deleteJob(input: { id: "a-vision-job-id" }) {
    id
  }
}

Example Response

This is the response shape you will get, even if you attempt to delete a job that doesn't exist. You will not get any NotFound error with a non-existent job.

{
  "data": {
    "deleteJob": {
      "id": "a-vision-job-id"
    }
  }
}

Getting a List of Job IDs for an Integration Entity ID

If an integrationEntityId was set when a job was created (such a when a job is created via a Deep Link) , then that job can be retrieved using the getJobIdsByIntegrationEntityId query.

Since we do not enforce uniqueness on that field, this query returns a list to account for more than one job having been created with the same integrationEntityId.

We recommend that you store our Job IDs in your system so that you can do a simple getJob in the future whenever you need to access a job from our API.

Example Request

See the GetJobIdsInput schema for the full details.

query GetJobIdsByIntegrationEntityId {
  getJobIdsByIntegrationEntityId(
    input: {
      integrationEntityId: {
        namespace: "AtLeast10Characters"
        id: "UniqueWithinYourSystem"
      }
    }
  ) {
    jobIds
  }
}

Example Response

Note that the response here, as described above, is an array of job IDs.

Although the most common scenario should be that you get a single-item array, your code should account for cases where more than one job ID is return.

{
  "data": {
    "getJobIdsByIntegrationEntityId": {
      "jobIds": ["job-id9406b85d48c45b4808c8566197f905f"]
    }
  }
}

Technical Details About Workflows

Internally, workflows are referred to as Workflow Jobs while the outer, organizing job is referred to as a Container Job. The workflowJobId field returned by getJobSummary reveals this naming convention.

All of the actions described in this document operate on Container Jobs. Some details about Workflow Jobs can can be retrieved via getJobSummary and getJob, but they cannot be created or modified via this API. As a result, only Container Job IDs are valid to be used in mutations. Any attempt to modify a Workflow Job will result in a "Not Found" error -- use the Container Job ID instead.

Prior to the introduction of the multiple workflow feature, a single job filled both the container and workflow roles. As a result, on records that predate the introduction of this feature the top level id returned by getJobSummary may be identical to the workflowJobId values returned for any documentation it contains. This represents the dual-role nature of those older records. These older records can only ever have a single workflow.