> ## Documentation Index
> Fetch the complete documentation index at: https://docs.andteam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# File a promotion, transfer or re-grade

> Needs the Job history field group's Write switch. Filed through andteam's own Change job as the key's requester: the HRIS's fields, the approval chain, the self-approval guard and the audit trail all apply. With the tenant's job change approval chain the answer is 202 and nothing is written to the job until the last step approves; with none, 201. A `pay` block files the pay change with it in one transaction (it also needs Pay's Write switch). A field the HRIS owns is 409 `field-locked`; a change already waiting is 409 `pending-change-exists` with `existingId`; a step nobody can decide is 409 `approval-chain-unresolvable` with `step`. andteam never sends a letter for an API change: HR is shown it as a letter to send.



## OpenAPI

````yaml /openapi.json post /employees/{id}/job-changes
openapi: 3.1.0
info:
  title: andteam API
  version: 1.1.0
  description: >-
    The andteam API: your people, organisation, leave, pay and records, and the
    changes other systems ask for. The key identifies the tenant; its companies
    and field groups decide what it reads and writes.


    ## Authentication


    Send the key as a bearer token on every request:


    ```

    Authorization: Bearer atk_live_…

    ```


    An administrator creates keys in the API keys section of the Integrations
    settings. The secret is shown once, when the key is created or rolled. A key
    holds one or more companies and one or more field groups, and may carry an
    allowed IP range and an expiry date. When a key is rolled, the old secret
    keeps working for 24 hours. A sandbox tenant's keys start `atk_test_` and
    never read special categories, pay, documents or performance.


    An app installed in many tenants uses OAuth client credentials instead: it
    asks `POST /v1/oauth/token` for a one-hour `ato_…` token for one tenant and
    sends it the same way. A tenant's admin installs the app and chooses what it
    may read and write.


    ## Rate limits


    Each key may make 300 requests a minute, with a burst of at most 50 in any
    10 seconds. All the keys of one tenant together may make 1,200 a minute.
    Every response carries:


    - `RateLimit-Limit`: the key's requests a minute.

    - `RateLimit-Remaining`: what is left in the tightest window.

    - `RateLimit-Reset`: seconds until that window resets.


    Writes have their own bucket inside those: 60 a minute per key.


    Over the limit, the answer is 429 with `Retry-After` (seconds). A refused
    request still counts, so wait for `Retry-After` instead of retrying at once.


    ## Pagination


    Every list takes `limit` (1 to 500, default 100) and `cursor`, and answers
    `{ "data": [...], "next_cursor": "..." }`. Pass `next_cursor` as `cursor` to
    read the next page; it is null on the last page. There is no total and no
    offset. The cursor is opaque: do not build or parse one. Lists that change
    (employees, positions, time off, events) are read in the order records last
    changed, so a record that changes while you page moves to the end and is
    read again there: nothing is skipped. Small configuration lists (companies,
    locations, lookups, org units) page by id.


    To stay in step, read everything once, then read again with `updated_since`
    (or `since` for events) set to the time your last full read began.


    ## Errors


    Every refusal is `application/problem+json` (RFC 9457). Branch on `type`, a
    stable URL, never on `title` or `detail`. Each type has a page at its URL.


    | Status | Type | Meaning |

    | --- | --- | --- |

    | 401 | [`missing-key`](https://docs.andteam.com/api/problems/missing-key) |
    No API key was sent |

    | 401 | [`invalid-key`](https://docs.andteam.com/api/problems/invalid-key) |
    The API key is not valid |

    | 401 | [`revoked-key`](https://docs.andteam.com/api/problems/revoked-key) |
    The API key has been revoked |

    | 401 | [`expired-key`](https://docs.andteam.com/api/problems/expired-key) |
    The API key has expired |

    | 401 |
    [`rolled-key-expired`](https://docs.andteam.com/api/problems/rolled-key-expired)
    | The API key was rolled and its 24 hours are over |

    | 403 |
    [`pending-approval`](https://docs.andteam.com/api/problems/pending-approval)
    | The API key is waiting for the Information Officer's approval |

    | 403 |
    [`ip-not-allowed`](https://docs.andteam.com/api/problems/ip-not-allowed) |
    The request did not come from the key's allowed addresses |

    | 403 |
    [`field-group-required`](https://docs.andteam.com/api/problems/field-group-required)
    | The API key may not read this resource |

    | 403 |
    [`company-not-allowed`](https://docs.andteam.com/api/problems/company-not-allowed)
    | The API key may not read this company |

    | 429 | [`rate-limited`](https://docs.andteam.com/api/problems/rate-limited)
    | Too many requests |

    | 400 |
    [`invalid-parameter`](https://docs.andteam.com/api/problems/invalid-parameter)
    | A query parameter is not valid |

    | 404 | [`not-found`](https://docs.andteam.com/api/problems/not-found) | Not
    found |

    | 409 | [`ambiguous-id`](https://docs.andteam.com/api/problems/ambiguous-id)
    | More than one of the key's companies holds this id |

    | 500 |
    [`internal-error`](https://docs.andteam.com/api/problems/internal-error) |
    Something went wrong |

    | 422 |
    [`validation-failed`](https://docs.andteam.com/api/problems/validation-failed)
    | The request body is not valid |

    | 409 | [`field-locked`](https://docs.andteam.com/api/problems/field-locked)
    | A field is owned by the HRIS for this person |

    | 403 |
    [`write-not-allowed`](https://docs.andteam.com/api/problems/write-not-allowed)
    | The API key may read this group but not write it |

    | 403 |
    [`requester-not-allowed`](https://docs.andteam.com/api/problems/requester-not-allowed)
    | The requester may not make this change |

    | 409 |
    [`approval-chain-unresolvable`](https://docs.andteam.com/api/problems/approval-chain-unresolvable)
    | A step of the approval chain resolves to nobody |

    | 409 |
    [`pending-change-exists`](https://docs.andteam.com/api/problems/pending-change-exists)
    | The person already has a change of this kind waiting |

    | 409 |
    [`duplicate-hire`](https://docs.andteam.com/api/problems/duplicate-hire) | A
    hire with this external reference already exists |

    | 409 |
    [`possible-rehire`](https://docs.andteam.com/api/problems/possible-rehire) |
    The candidate's personal email matches a current employee |

    | 400 |
    [`idempotency-key-missing`](https://docs.andteam.com/api/problems/idempotency-key-missing)
    | An Idempotency-Key header is required |

    | 422 |
    [`idempotency-key-reused`](https://docs.andteam.com/api/problems/idempotency-key-reused)
    | The Idempotency-Key was used with a different body |

    | 409 |
    [`idempotency-in-progress`](https://docs.andteam.com/api/problems/idempotency-in-progress)
    | A request with this Idempotency-Key is still running |

    | 428 |
    [`precondition-required`](https://docs.andteam.com/api/problems/precondition-required)
    | An If-Match header is required |

    | 412 |
    [`precondition-failed`](https://docs.andteam.com/api/problems/precondition-failed)
    | The record changed since the ETag was read |

    | 409 |
    [`not-withdrawable`](https://docs.andteam.com/api/problems/not-withdrawable)
    | The request can no longer be withdrawn |

    | 405 |
    [`method-not-allowed`](https://docs.andteam.com/api/problems/method-not-allowed)
    | The method is not allowed on this resource |

    | 415 |
    [`unsupported-media-type`](https://docs.andteam.com/api/problems/unsupported-media-type)
    | The body must be application/json |

    | 403 |
    [`test-key-not-allowed`](https://docs.andteam.com/api/problems/test-key-not-allowed)
    | A test key may not use this field group |


    ## Field groups


    What a key reads is set by its field groups: Directory, Organisation,
    Positions, Time off, Personal contact, Personal details, Special categories,
    Job history, Pay, Documents, Leave, Performance and Certifications. A new
    key has Directory and Organisation. A field the key may not read is left
    out, not sent as null: a missing field means "not for you", a null field
    means "no value".


    Four groups need a written reason and a named approver, and are excluded
    until approved: Special categories and Documents (the Information Officer),
    Pay (whoever signs off payroll) and Performance (a performance admin).
    People in protected groups are left out of Pay and Performance unless the
    approver includes them. Health documents and sick notes are never served,
    and neither are ID numbers, tax numbers, bank details or help questions:
    there is nothing to switch on.


    An approval is for the scope it was given for. Widening a key's or
    endpoint's companies takes every approved group back to waiting for its
    approver, widening its document types does the same for Documents, and
    moving a webhook endpoint to a new address does the same for all of them;
    narrowing keeps the approval. A webhook delivery stored under an approval
    that has since changed is not sent: a retry fails with `approval_changed`,
    and Resend and Replay build the body again under the current approvals when
    the event is still one the endpoint takes.


    ## Writes


    A group with a write has a Write switch beside its Read switch: Personal
    contact, Personal details, Job history, Pay and Leave, and Hires, which is
    write-only. Every write is made for a named person, the key's requester (or
    `requestedBy` on the request, who is checked the same way), and runs through
    the same path as the console: the tenant's HRIS locks, approval chains,
    notifications and audit apply. A write never approves itself:


    - With an approval chain for the action, the answer is 202 with the pending
    request, and a `*.decided` webhook follows when the chain ends.

    - With no chain, the change applies at once (201), exactly as in the
    console.


    Every POST needs an `Idempotency-Key` header: a retry with the same key and
    body gets the first answer again (`Idempotent-Replayed: true`). Every PATCH
    needs `If-Match` with the record's `ETag`. Every create takes
    `?validate_only=true` to see what would happen, writing nothing. A body that
    is wrong is one 422 `validation-failed`, with every field's error in
    `errors`. The API never sends a letter: after an approved change, HR is
    asked to send it.


    ## Time off


    `/time-off` returns approved absences as dates, shown as **Away**. The leave
    type is never exposed, because a sick-leave day says something about health.
    An absence that was approved and then withdrawn or cancelled is returned
    with status `cancelled`, inside the `updated_since` window of its change, so
    you can remove it.


    ## Versioning


    This is version 1.1, at `/v1`. New fields, endpoints and event types are
    added without notice: ignore what you do not know. A breaking change is a
    new version, `/v2`, and `/v1` then answers with `Deprecation` (RFC 9745) and
    `Sunset` (RFC 8594) headers and keeps working for at least 12 more months.
    Every change is in the dated changelog:
    https://docs.andteam.com/api/changelog.


    ## Webhooks


    andteam can also push events to your endpoint: the employee events, and the
    request and record events (hires, job and pay changes, leave requests,
    released ratings, documents), each heard only with its group. See the
    `webhooks` section of this document and the guide:
    https://docs.andteam.com/guides/webhooks.
servers:
  - url: https://api.v3.andteam.com/v1
security:
  - apiKey: []
  - oauth: []
tags:
  - name: Directory
    description: Employees and the events about them. Needs the Directory field group.
  - name: Organisation
    description: >-
      Companies, structure levels, locations and lookups. Needs the Organisation
      field group.
  - name: Positions
    description: Positions and who they report to. Needs the Positions field group.
  - name: Time off
    description: Approved absences as dates, shown as Away. Needs the Time off field group.
  - name: Job history
    description: A person's dated positions and terms. Needs the Job history field group.
  - name: Leave
    description: >-
      Leave types, balances and requests, named by type. A sick type is only
      ever `category: "sick"`, has no balance and no requests here. Needs the
      Leave field group.
  - name: Certifications
    description: >-
      Current certificates and qualifications. Needs the Certifications field
      group.
  - name: Hires
    description: >-
      New hires from an ATS, as draft offers HR completes. Needs the Hires field
      group's Write switch, which is write-only: it also reads the hires back.
  - name: Authentication
    description: OAuth client credentials for apps installed in many tenants.
  - name: Reference
    description: The API's own description.
  - name: Webhooks
    description: >-
      Events andteam POSTs to your endpoint. Signing, retries and verification:
      https://docs.andteam.com/guides/webhooks.
paths:
  /employees/{id}/job-changes:
    post:
      tags:
        - Job history
      summary: File a promotion, transfer or re-grade
      description: >-
        Needs the Job history field group's Write switch. Filed through
        andteam's own Change job as the key's requester: the HRIS's fields, the
        approval chain, the self-approval guard and the audit trail all apply.
        With the tenant's job change approval chain the answer is 202 and
        nothing is written to the job until the last step approves; with none,
        201. A `pay` block files the pay change with it in one transaction (it
        also needs Pay's Write switch). A field the HRIS owns is 409
        `field-locked`; a change already waiting is 409 `pending-change-exists`
        with `existingId`; a step nobody can decide is 409
        `approval-chain-unresolvable` with `step`. andteam never sends a letter
        for an API change: HR is shown it as a letter to send.
      operationId: postEmployeesIdJobChanges
      parameters:
        - name: id
          in: path
          required: true
          description: The employee id.
          schema:
            type: string
        - name: company_id
          in: query
          description: One of the key's companies.
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          required: true
          description: >-
            Unique per request; reuse it only to retry the same request with the
            same body. Remembered 24 hours.
          schema:
            type: string
            maxLength: 255
        - name: If-Match
          in: header
          description: >-
            Optional: the employee's `ETag`, to refuse early when the record
            changed since you read it.
          schema:
            type: string
        - name: validate_only
          in: query
          description: >-
            `true`: answer 200 with what would happen (the approval steps and
            who they resolve to, the knock-ons), and write nothing.
          schema:
            type: boolean
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobChangeRequest'
      responses:
        '200':
          description: '`validate_only=true`: what would happen. Nothing was written.'
          headers:
            RateLimit-Limit:
              description: Requests a minute allowed for the key.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests left in the tightest window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            Deprecation:
              description: Present once this version is deprecated (RFC 9745).
              schema:
                type: string
            Sunset:
              description: Present once this version has a shutdown date (RFC 8594).
              schema:
                type: string
            Idempotent-Replayed:
              description: >-
                `true` when this is the stored answer to an earlier request with
                the same `Idempotency-Key`.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobChangePreview'
        '201':
          description: >-
            No approval chain: written at once, `applied` (its date has come) or
            `scheduled`.
          headers:
            RateLimit-Limit:
              description: Requests a minute allowed for the key.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests left in the tightest window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            Deprecation:
              description: Present once this version is deprecated (RFC 9745).
              schema:
                type: string
            Sunset:
              description: Present once this version has a shutdown date (RFC 8594).
              schema:
                type: string
            Idempotent-Replayed:
              description: >-
                `true` when this is the stored answer to an earlier request with
                the same `Idempotency-Key`.
              schema:
                type: string
            Location:
              description: The created resource.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobChange'
        '202':
          description: >-
            Filed for approval: `awaiting_approval`, with the steps. Nothing is
            written to the job until the last step approves.
          headers:
            RateLimit-Limit:
              description: Requests a minute allowed for the key.
              schema:
                type: integer
            RateLimit-Remaining:
              description: Requests left in the tightest window.
              schema:
                type: integer
            RateLimit-Reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            Deprecation:
              description: Present once this version is deprecated (RFC 9745).
              schema:
                type: string
            Sunset:
              description: Present once this version has a shutdown date (RFC 8594).
              schema:
                type: string
            Idempotent-Replayed:
              description: >-
                `true` when this is the stored answer to an earlier request with
                the same `Idempotency-Key`.
              schema:
                type: string
            Location:
              description: The created resource.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobChange'
        '401':
          description: >-
            No valid key. Problem types: `missing-key`, `invalid-key`,
            `revoked-key`, `expired-key`, `rolled-key-expired`.
          headers:
            WWW-Authenticate:
              description: Bearer realm="andteam"
              schema:
                type: string
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: >-
            Not allowed. Problem types: `pending-approval`, `ip-not-allowed`,
            `field-group-required`, `company-not-allowed`, `write-not-allowed`,
            `requester-not-allowed`, `test-key-not-allowed`.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: 'Not found. Problem types: `not-found`.'
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: >-
            Conflict. Problem types: `ambiguous-id`, `field-locked`,
            `approval-chain-unresolvable`, `pending-change-exists`,
            `duplicate-hire`, `possible-rehire`, `idempotency-in-progress`,
            `not-withdrawable`.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '412':
          description: 'Precondition failed. Problem types: `precondition-failed`.'
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '415':
          description: 'Unsupported media type. Problem types: `unsupported-media-type`.'
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: >-
            Not valid. Problem types: `validation-failed`,
            `idempotency-key-reused`.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '429':
          description: 'Rate limited. Problem types: `rate-limited`.'
          headers:
            Retry-After:
              description: Seconds to wait before the next request.
              schema:
                type: integer
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: 'Server error. Problem types: `internal-error`.'
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
components:
  schemas:
    JobChangeRequest:
      type: object
      properties:
        type:
          type: string
          enum:
            - promotion
            - transfer
            - regrade
          description: >-
            Promotion, transfer or re-grade. A correction or a change of terms
            is made in andteam (422, code `not-supported`).
        effectiveDate:
          type: string
          format: date
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$
          description: >-
            The day the new job starts, after the current position began. Past
            or today: applied at once when the tenant has no approval chain;
            later: scheduled.
        jobTitleId:
          description: A value id from `/v1/lookups/job-titles`.
          type: string
          minLength: 1
          maxLength: 128
        departmentId:
          description: A value id from `/v1/lookups/departments`.
          type: string
          minLength: 1
          maxLength: 128
        costCentreId:
          description: A value id from `/v1/lookups/cost-centres`.
          type: string
          minLength: 1
          maxLength: 128
        gradeId:
          description: A value id from `/v1/lookups/grades`.
          type: string
          minLength: 1
          maxLength: 128
        locationId:
          description: A location id from `/v1/locations`.
          type: string
          minLength: 1
          maxLength: 128
        orgUnitIds:
          description: Org unit ids from `/v1/org-units`, at most one per level.
          maxItems: 10
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 260
        managerId:
          description: >-
            Who they report to from that date: an employee id, or null for no
            one. Left out: their current manager.
          anyOf:
            - type: string
              minLength: 1
              maxLength: 128
            - type: 'null'
        pay:
          description: >-
            The pay change that comes with the job, filed with it in one
            transaction (a promotion's pay is a `promotion`, a transfer's or
            re-grade's an `adjustment`). Needs the Pay field group's Write
            switch.
          type: object
          properties:
            components:
              minItems: 1
              maxItems: 200
              type: array
              items:
                $ref: '#/components/schemas/PayComponentInput'
            note:
              type: string
              maxLength: 500
          required:
            - components
          additionalProperties: false
        requestedBy:
          type: string
          minLength: 1
          maxLength: 320
          description: >-
            Optional: the andteam user id or work email of the person this is
            requested by (the hiring manager in your ATS, say), instead of the
            key's requester. They are checked for the same permission over this
            employee; if the check fails the request is refused
            (requester-not-allowed), never put back on the key's requester.
      required:
        - type
        - effectiveDate
      additionalProperties: false
    JobChangePreview:
      type: object
      properties:
        wouldBe:
          type: object
          properties:
            status:
              type: string
              enum:
                - awaiting_approval
                - applied
                - scheduled
          required:
            - status
          additionalProperties: false
        steps:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalStep'
        knockOns:
          type: object
          properties:
            reportsMove:
              type: integer
              minimum: 0
              maximum: 9007199254740991
              description: How many of their reports move with them to the new position.
          required:
            - reportsMove
          additionalProperties: false
        pay:
          anyOf:
            - type: object
              properties:
                wouldBe:
                  type: object
                  properties:
                    status:
                      type: string
                      enum:
                        - awaiting_approval
                        - applied
                        - scheduled
                  required:
                    - status
                  additionalProperties: false
                steps:
                  type: array
                  items:
                    $ref: '#/components/schemas/ApprovalStep'
              required:
                - wouldBe
                - steps
              additionalProperties: false
            - type: 'null'
      required:
        - wouldBe
        - steps
        - knockOns
      additionalProperties: false
    JobChange:
      type: object
      properties:
        id:
          type: string
        employeeId:
          type: string
        companyId:
          type: string
        type:
          type: string
          enum:
            - promotion
            - transfer
            - regrade
        effectiveDate:
          type: string
          format: date
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$
        status:
          type: string
          enum:
            - awaiting_approval
            - approved
            - declined
            - withdrawn
            - applied
            - scheduled
        changes:
          $ref: '#/components/schemas/JobChangeChanges'
        steps:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalStep'
          description: The approval chain it waits on; empty when it was applied at once.
        payChangeId:
          description: The pay change filed with it. Present only for a key that reads Pay.
          type:
            - string
            - 'null'
        requestedVia:
          anyOf:
            - type: object
              properties:
                keyId:
                  type: string
              required:
                - keyId
              additionalProperties: false
            - type: 'null'
          description: The API key that filed it; null when it was made in andteam.
        createdAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
        decidedAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
            - type: 'null'
      required:
        - id
        - employeeId
        - companyId
        - type
        - effectiveDate
        - status
        - changes
        - steps
        - requestedVia
        - createdAt
        - decidedAt
      additionalProperties: false
    Problem:
      type: object
      properties:
        type:
          type: string
          description: >-
            A stable URL for the kind of problem:
            https://docs.andteam.com/api/problems/{slug}.
        title:
          type: string
        status:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        detail:
          type: string
        instance:
          type: string
        errors:
          description: 'validation-failed: every field that is wrong, at once.'
          type: array
          items:
            type: object
            properties:
              pointer:
                type: string
                description: >-
                  A JSON Pointer (RFC 6901) to the field in the request body,
                  such as /candidate/personalEmail.
              code:
                type: string
                description: >-
                  A stable code for the error, such as required, invalid,
                  insufficient-balance.
              detail:
                type: string
            required:
              - pointer
              - code
              - detail
            additionalProperties: false
        fields:
          description: >-
            field-locked: every field in the request the HRIS owns for this
            person.
          type: array
          items:
            type: string
        existingId:
          description: >-
            pending-change-exists, duplicate-hire, possible-rehire: the id of
            the existing record.
          type: string
        step:
          description: 'approval-chain-unresolvable: the step that resolves to nobody.'
          type: string
      required:
        - type
        - title
        - status
      additionalProperties: false
    PayComponentInput:
      type: object
      properties:
        componentId:
          type: string
          minLength: 1
          maxLength: 128
          description: A component of the tenant's compensation catalogue.
        values:
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
          description: >-
            The component's values, as its catalogue entry defines them (for
            example `amount` and `frequency`).
      required:
        - componentId
        - values
      additionalProperties: false
    ApprovalStep:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        approvers:
          type: array
          items:
            type: string
        status:
          type: string
          enum:
            - waiting
            - current
            - approved
            - declined
      required:
        - id
        - label
        - approvers
        - status
      additionalProperties: false
    JobChangeChanges:
      type: object
      properties:
        jobTitleId:
          description: A value id from `/v1/lookups/job-titles`.
          type: string
          minLength: 1
          maxLength: 128
        departmentId:
          description: A value id from `/v1/lookups/departments`.
          type: string
          minLength: 1
          maxLength: 128
        costCentreId:
          description: A value id from `/v1/lookups/cost-centres`.
          type: string
          minLength: 1
          maxLength: 128
        gradeId:
          description: A value id from `/v1/lookups/grades`.
          type: string
          minLength: 1
          maxLength: 128
        locationId:
          description: A location id from `/v1/locations`.
          type: string
          minLength: 1
          maxLength: 128
        orgUnitIds:
          description: Org unit ids from `/v1/org-units`, at most one per level.
          maxItems: 10
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 260
        managerId:
          type:
            - string
            - 'null'
      additionalProperties: false
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: atk_live_…
      description: >-
        `Authorization: Bearer atk_live_…` (a sandbox's keys are `atk_test_…`).
        Created in the API keys section of the Integrations settings; the secret
        is shown once.
    oauth:
      type: oauth2
      description: >-
        For an app installed in many tenants: client credentials, a one-hour
        `ato_…` token per tenant.
      flows:
        clientCredentials:
          tokenUrl: https://api.v3.andteam.com/v1/oauth/token
          scopes: {}

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.