Introduction

The Job Management APIs give programmatic access to your organisation's job structure: the jobs themselves, the job functions and job levels they are classified against, the job-related custom OUs they belong to, and the assignment of jobs to users.

All endpoints sit under https://{corpname}.csod.com/services/api/x/chr-jobmgmt-app/v1/.

Resource model

The API is organised into five families, each with its own section in the reference.

FamilyManages
JobsJob records, plus their status, job function, job level and custom OU assignments, next jobs, and the users assigned to them
Job FunctionsJob function records, their status timeline and their position in the job function hierarchy
Job LevelsJob level records, their status timeline and their position in the job level hierarchy
Job-related Custom OUsCustom OU types, the custom OUs within a type, and their status and parent timelines
User Job AssignmentsWhich job a user holds, over time

Hierarchies are read one level at a time. Ask a record for its children to walk down, or for its parents timeline to see where it has sat over time. See Hierarchies.

Effective dating

This is the concept that most distinguishes the API from a plain CRUD surface. Status changes, hierarchy changes and assignments are not overwritten, they are recorded as timelines. Every entry carries the dates it applies for, so history and future-dated changes are both preserved and readable.

A timeline entry looks like this:

{
  "assignmentId": "7c1f2d4e-9a3b-4c5d-8e6f-0a1b2c3d4e5f",
  "active": true,
  "dateEffective": "2026-01-01",
  "dateUnassign": null,
  "endDate": null,
  "isCurrent": true,
  "isHistoric": false,
  "isFuture": false,
  "notes": "Approved by HR."
}

Read isCurrent, isHistoric and isFuture rather than comparing dates yourself. At most one entry on a timeline is current.

See Effective dating for how supersession works, how to schedule and correct changes, and the date rules the API enforces.

All dates are calendar dates, YYYY-MM-DD, in the portal's time zone.

Reading data

Collections are token-paged. Pass pageSize to set the page length and pageToken to continue:

GET /services/api/x/chr-jobmgmt-app/v1/jobs?pageSize=100
{
  "results": [],
  "paging": { "tokens": { "next": "opaque-or-null" } }
}

Pass paging.tokens.next back as pageToken to fetch the next page. An absent token means you have reached the last page.

A short page is not the end

Only the absence of a next token indicates the last page. A page with fewer than pageSize records does not.

Use fields to limit the representation, either repeated or comma-separated:

GET .../v1/jobs?fields=jobId&fields=displayTitle

Some collections exclude expensive members such as titles, descriptions and customFields by default; request them explicitly through fields when you need a full export. An unrecognised name returns 400 INVALID_FIELDS and names every field it did not recognise.

The job, job function, job level and custom OU collections also double as their own search endpoints. Filter with titleOrCode, narrow with activeOnly or rootsOnly, and sort with orderBy and orderDirection. Archived records are never returned.

Writing data

Create with POST, and update with PATCH using a JSON Merge Patch document:

PATCH /services/api/x/chr-jobmgmt-app/v1/jobs/{jobId}
Content-Type: application/merge-patch+json

Send only the members you are changing. A member that is absent keeps its current value, a member with a value replaces it, and a nullable member sent explicitly as null is cleared. There is no lost-update guard, so concurrent writes to the same record are last-write-wins.

Archiving is a soft delete that cannot be undone

DELETE archives a record. It is retained for reporting but stops appearing in reads and lists, and there is no endpoint to restore it. Records still in use cannot be archived, so remove the assignments first.

Errors

Every failure uses the standard Cornerstone error envelope. The code is what your integration should branch on; the messages are for humans.

{
  "errors": [
    {
      "code": "DATE_UNASSIGN_BEFORE_DATE_EFFECTIVE",
      "details": [
        { "message": "dateUnassign must not fall before dateEffective.",
          "field": "dateUnassign",
          "value": "2025-12-31" }
      ]
    }
  ]
}

field names the part of the request at fault, either a body member or a query parameter, and is null when the error concerns the request as a whole. Each endpoint documents the codes it can return in its reference entry.

Scopes and permissions

Every request needs an OAuth 2.0 scope on the application and a security permission on the linked user account. Scopes follow a <resource>:<operation> shape:

ResourceScopes
Jobsjob:read, job:create, job:update, job:delete
Job functionsjob-function:read, job-function:create, job-function:update, job-function:delete
Job levelsjob-level:read, job-level:create, job-level:update, job-level:delete
Job-related custom OUsjob-custom-ou:read, job-custom-ou:create, job-custom-ou:update, job-custom-ou:delete
User job assignmentsjob-assignment:read, job-assignment:create, job-assignment:update, job-assignment:delete

The matching security permissions are Job Management API - Jobs - View and - Manage, Job Management API - Job Structure - View and - Manage, and for user assignments Job Management API - Assignment - View (User), - Manage (User) and - Manage (Job). Assigning a job to a user needs both the user-side and job-side Manage permissions.

Reads are constrained to the records the caller's permission covers. Each endpoint lists the exact scope and permission it requires in its reference entry, and every endpoint is listed individually in List of Scopes and Security Permissions for APIsopen in new window.