Purple ATS API Documentation

Machine-readable OpenAPI 3.0 specification: https://marketplace.moveworks.com/api/purple-suite/ats/openapi.json

The consolidated all-apps document at https://marketplace.moveworks.com/api/purple-suite/openapi.json can be narrowed to this app with ?apps=ats, or combined with other apps comma-separated (e.g. ?apps=ats,itsm).

Overview

--- **Acting as a user (`X-PS-Impersonate-User`).** Every endpoint accepts an optional `X-PS-Impersonate-User` request header whose value is the email of the instance user to act as. The effective user resolves in this order: the header if present, else the instance's configured default MCP user, else none. User-scoped paths additionally accept the literal `me` in place of an email, and Graph-style apps also serve `/me/…` twins of their `/users/{email}/…` paths that resolve the same way. This header is honored by all operations but is intentionally omitted from each operation's parameter list so it is not surfaced as a per-tool argument by MCP clients; see the `ImpersonateUser` entry under `components.parameters`.

Endpoints

GET /api/purple-suite/ats/requisitions

List Purple ATS job requisitions

Approved openings to hire against in Purple ATS — title, department, headcount, hiring manager, required skills and status (open → in_progress/on_hold → filled/closed/cancelled). Candidates and job postings link back to a requisition by requisitionId. Supports server-side querying with _filter/_search/_orderby/_select/_top/_skip/_count (OData $-params, renamed with a leading underscore for MCP).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Requisition

    • id string
    • title string
    • department string
    • status string
    • headcount integer
    • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
    • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
    • responsibilities stringShort prose description of what the role does.
    • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
      Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

      array of:

      • skill string
      • proficiency string
    • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
    • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
      IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

      array of:

      string (example: "REQ-0001")

    • openedAt string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/ats/requisitions

Open a job requisition

Creates a new requisition (a request to hire) in Purple ATS. This opens headcount only — it does not publish an advert (create a job posting for that) and does not add applicants.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Requisition

  • id string
  • title string
  • department string
  • status string
  • headcount integer
  • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
  • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
  • responsibilities stringShort prose description of what the role does.
  • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
    Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

    array of:

    • skill string
    • proficiency string
  • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
  • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
    IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

    array of:

    string (example: "REQ-0001")

  • openedAt string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Requisition

  • id string
  • title string
  • department string
  • status string
  • headcount integer
  • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
  • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
  • responsibilities stringShort prose description of what the role does.
  • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
    Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

    array of:

    • skill string
    • proficiency string
  • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
  • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
    IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

    array of:

    string (example: "REQ-0001")

  • openedAt string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/ats/requisitions/{id}

Get requisition

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Requisition

  • id string
  • title string
  • department string
  • status string
  • headcount integer
  • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
  • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
  • responsibilities stringShort prose description of what the role does.
  • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
    Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

    array of:

    • skill string
    • proficiency string
  • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
  • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
    IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

    array of:

    string (example: "REQ-0001")

  • openedAt string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/ats/requisitions/{id}

Delete requisition

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/ats/requisitions/{id}

Update requisition

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Requisition

  • id string
  • title string
  • department string
  • status string
  • headcount integer
  • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
  • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
  • responsibilities stringShort prose description of what the role does.
  • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
    Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

    array of:

    • skill string
    • proficiency string
  • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
  • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
    IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

    array of:

    string (example: "REQ-0001")

  • openedAt string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Requisition

  • id string
  • title string
  • department string
  • status string
  • headcount integer
  • hiringManager stringHiring manager email. Alias: hiring_manager (snake_case accepted).
  • createdBy stringEmail of the user who created this requisition. Alias: created_by (snake_case accepted).
  • responsibilities stringShort prose description of what the role does.
  • required_skills arraySkills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).
    Skills the role requires, each with a target proficiency. Alias: requiredSkills (camelCase accepted).

    array of:

    • skill string
    • proficiency string
  • level stringSeniority label — e.g. IC1/IC2/IC3/Sr/Manager/Director, or any free-text level.
  • target_role_for arrayIDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).
    IDs of requisitions/roles this one is a common next step from (career pathing). Alias: targetRoleFor (camelCase accepted).

    array of:

    string (example: "REQ-0001")

  • openedAt string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/ats/candidates

List Purple ATS job applicants

External people who applied to a Purple ATS requisition, with their pipeline stage (applied → screening → phone_screen → interview → offer → hired, or rejected/withdrawn), source and resume link. These are applicants, not employees (see the hris app) or chat/identity users. Supports server-side querying with _filter/_search/_orderby/_select/_top/_skip/_count (OData $-params, renamed with a leading underscore for MCP).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Candidate

    • id string
    • firstName stringAlias: first_name (snake_case accepted).
    • lastName stringAlias: last_name (snake_case accepted).
    • email string
    • phone string
    • requisitionId stringAlias: requisition_id (snake_case accepted).
    • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
    • source string
    • resumeUrl stringAlias: resume_url (snake_case accepted).
    • appliedAt string
    • stageHistory array

      array of:

      • status string
      • notes string
      • recordedAt string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/ats/candidates

Add an applicant to the hiring pipeline

Registers a new candidate against a Purple ATS requisition, starting at the 'applied' stage unless a status is supplied.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/ats/candidates/{id}

Get candidate

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/ats/candidates/{id}

Delete candidate

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/ats/candidates/{id}

Update a candidate record

Partially updates an applicant in Purple ATS (contact details, source, resume). This is also how a candidate is rejected or withdrawn — set status accordingly. Forward pipeline moves should use the candidate advance tool, which validates the transition and records stage history.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/ats/candidates/{id}/advance

Advance a candidate to the next hiring stage

Moves a Purple ATS candidate forward through applied → screening → phone_screen → interview → offer → hired (auto-picks the next stage when no target is given) and appends an entry to stageHistory. Forward-only: it refuses backwards moves and candidates who are rejected, withdrawn or already hired — use the candidate update tool to reject or withdraw someone.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json

  • status stringTarget stage to advance to. Omit to auto-advance to the next stage. Alias: stage (snake_case/legacy accepted).
  • notes string

Responses

200
Candidate advanced

application/json

Candidate

  • id string
  • firstName stringAlias: first_name (snake_case accepted).
  • lastName stringAlias: last_name (snake_case accepted).
  • email string
  • phone string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • status stringCurrent pipeline stage. Alias: stage (accepted on create/update).
  • source string
  • resumeUrl stringAlias: resume_url (snake_case accepted).
  • appliedAt string
  • stageHistory array

    array of:

    • status string
    • notes string
    • recordedAt string
  • createdAt string
  • updatedAt string
400
Invalid stage value
404
Candidate not found
422
Stage transition not allowed (rejected/withdrawn/hired/backwards move)

POST /api/purple-suite/ats/candidates/{id}/generate-offer

Generate a draft offer for a candidate

Creates an Offer record in draft status for a Purple ATS candidate and moves that candidate to the 'offer' stage in one step — prefer this over creating an offer record directly. Rejected if the candidate is already hired or already has a draft/sent offer.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json

  • salary numberBase salary. Alias: baseSalary (camelCase accepted). Stored as baseSalary on the created Offer document.
  • equity stringEquity grant string (e.g. '0.25%').
  • start_date stringProposed start date. Alias: startDate (camelCase accepted).
  • expires_at stringOffer expiry date. Alias: expiresAt (camelCase accepted).
  • sentAt stringTimestamp when offer was sent, if already dispatched.

Responses

201
Offer created

application/json

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string
404
Candidate not found
422
Candidate already hired or already has an active offer

GET /api/purple-suite/ats/interviews

List Purple ATS candidate interviews

Interview sessions booked or completed for Purple ATS candidates — interviewer email, type (phone_screen | technical | behavioral | panel | final), scheduledAt, status and the written feedback plus 1–5 rating. These are hiring loops, not general calendar meetings (see the calendar app). Supports server-side querying with _filter/_search/_orderby/_select/_top/_skip/_count (OData $-params, renamed with a leading underscore for MCP).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Interview

    • id string
    • candidateId stringAlias: candidate_id (snake_case accepted).
    • requisitionId stringAlias: requisition_id (snake_case accepted).
    • interviewer string
    • scheduledAt stringAlias: scheduled_at (snake_case accepted).
    • type string
    • status string
    • feedback string
    • rating integer
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/ats/interviews

Create interview

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Interview

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • interviewer string
  • scheduledAt stringAlias: scheduled_at (snake_case accepted).
  • type string
  • status string
  • feedback string
  • rating integer
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Interview

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • interviewer string
  • scheduledAt stringAlias: scheduled_at (snake_case accepted).
  • type string
  • status string
  • feedback string
  • rating integer
  • createdAt string
  • updatedAt string

GET /api/purple-suite/ats/interviews/{id}

Get interview

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Interview

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • interviewer string
  • scheduledAt stringAlias: scheduled_at (snake_case accepted).
  • type string
  • status string
  • feedback string
  • rating integer
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/ats/interviews/{id}

Delete interview

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/ats/interviews/{id}

Update interview

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Interview

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • interviewer string
  • scheduledAt stringAlias: scheduled_at (snake_case accepted).
  • type string
  • status string
  • feedback string
  • rating integer
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Interview

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • interviewer string
  • scheduledAt stringAlias: scheduled_at (snake_case accepted).
  • type string
  • status string
  • feedback string
  • rating integer
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/ats/offers

List Purple ATS job offers

Employment offers extended to Purple ATS candidates — base salary, equity, start date, expiry and status (draft → sent → accepted/declined/expired/withdrawn). Check here for an existing draft/sent offer before generating another for the same candidate. Supports server-side querying with _filter/_search/_orderby/_select/_top/_skip/_count (OData $-params, renamed with a leading underscore for MCP).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Offer

    • id string
    • candidateId stringAlias: candidate_id (snake_case accepted).
    • requisitionId stringAlias: requisition_id (snake_case accepted).
    • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
    • equity string
    • startDate stringAlias: start_date (snake_case accepted).
    • status string
    • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
    • expiresAt stringAlias: expires_at (snake_case accepted).
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/ats/offers

Create offer

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string

GET /api/purple-suite/ats/offers/{id}

Get offer

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/ats/offers/{id}

Delete offer

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/ats/offers/{id}

Update offer

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Offer

  • id string
  • candidateId stringAlias: candidate_id (snake_case accepted).
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • baseSalary numberBase salary amount. Alias: salary (accepted on create/update).
  • equity string
  • startDate stringAlias: start_date (snake_case accepted).
  • status string
  • sentAt stringTimestamp when the offer was dispatched to the candidate. Client-settable.
  • expiresAt stringAlias: expires_at (snake_case accepted).
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/ats/job-postings

List Purple ATS job postings

Externally-facing job adverts in Purple ATS — title, location, employment type, applicant count and status (draft | active | paused | closed) — usually linked to a requisition. The posting is the advert; the requisition is the approved headcount behind it. Supports server-side querying with _filter/_search/_orderby/_select/_top/_skip/_count (OData $-params, renamed with a leading underscore for MCP).

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    JobPosting

    • id string
    • requisitionId stringAlias: requisition_id (snake_case accepted).
    • title string
    • department string
    • description string
    • location string
    • type string
    • status string
    • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
    • postedAt stringAlias: posted_at (snake_case accepted).
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/ats/job-postings

Create job posting

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

JobPosting

  • id string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • title string
  • department string
  • description string
  • location string
  • type string
  • status string
  • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
  • postedAt stringAlias: posted_at (snake_case accepted).
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

JobPosting

  • id string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • title string
  • department string
  • description string
  • location string
  • type string
  • status string
  • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
  • postedAt stringAlias: posted_at (snake_case accepted).
  • createdAt string
  • updatedAt string

GET /api/purple-suite/ats/job-postings/{id}

Get job posting

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

JobPosting

  • id string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • title string
  • department string
  • description string
  • location string
  • type string
  • status string
  • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
  • postedAt stringAlias: posted_at (snake_case accepted).
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/ats/job-postings/{id}

Delete job posting

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/ats/job-postings/{id}

Update job posting

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

JobPosting

  • id string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • title string
  • department string
  • description string
  • location string
  • type string
  • status string
  • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
  • postedAt stringAlias: posted_at (snake_case accepted).
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

JobPosting

  • id string
  • requisitionId stringAlias: requisition_id (snake_case accepted).
  • title string
  • department string
  • description string
  • location string
  • type string
  • status string
  • applicantCount integerRunning applicant count. Defaults to 0 on create; may be set by the client and is not server-managed.
  • postedAt stringAlias: posted_at (snake_case accepted).
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/ats/referrals

List Purple ATS employee referrals

Candidates put forward by existing employees, with a per-status tally. Each referral records who referred whom (referrer_email → candidate_name/candidate_email), the position, and its status (pending | reviewing | hired | rejected). A referral is a lead, not yet a candidate in the pipeline — see ats__list__candidates for candidates under active consideration. Returns the whole collection with counts; it does not take OData query params.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Responses

200
Referral list

application/json

  • referrals array

    array of:

    object

  • totalCount integer
  • statusCounts object

POST /api/purple-suite/ats/referrals

Submit an employee referral

Records a candidate referred by an existing employee and stores it in the instance's referrals collection with status `pending`. referrer_email, candidate_name and candidate_email are required. This creates a referral lead only — it does not add anyone to the hiring pipeline; use ats__create__candidates for that.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

  • referrer_email string required
  • candidate_name string required
  • candidate_email string required
  • position string

Responses

200
Referral submitted

application/json

  • success boolean
  • referral object
    • id string
    • referrer_email string
    • candidate_name string
    • candidate_email string
    • position string
    • status string
    • created_at string
400
Missing required fields