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

# Update a job

> Update an existing job posting. All fields are optional; only include
the fields you want to change (partial update). Fields not included in
the request remain unchanged. The request body cannot be empty — at
least one field must be provided.

Behavior notes:
- **Status lifecycle**: the documented path is `DRAFT` → `ACTIVE` →
  `INACTIVE` → `DELETED`. Once a job's status moves past `DRAFT` it
  cannot be changed back to `DRAFT` (`INVALID_STATUS_TRANSITION`);
  other reverse transitions are not documented either way.
- **Null clears**: some fields accept `null` to clear their value
  (`teamId`, `contractType`, `degreeLevel`, `jobRole`,
  `potentialAmount`, `potentialAmountCurrency`, `potentialHiresCount`,
  `yearOfExperience`, `description`, `screeningQuestion`,
  `applicationForm`, `criterionDetails`). `title`, `city`, `state`, and
  `country` cannot be set to `null` — omit them instead.
- **applicationForm is merged, not replaced**: provide only the
  `applicationForm` keys you want to change; new values override
  existing ones and the rest are kept. If `expectedCTC`/`currentCTC` is
  set to `MANDATORY` or `OPTIONAL` (not `OFF`), the corresponding
  currency key is required unless the job already has a currency value;
  otherwise the update fails.
- The three salary fields must be provided together if any is
  provided, and `salaryRangeTo` must be greater than
  `salaryRangeFrom`.
- All field validations (type, length, format) are the same as for
  Create Job.

The success response is a bare job object that is smaller than the
create/get response and includes the populated `pipelineStage` array.




## OpenAPI

````yaml /api-reference/openapi.yaml put /jobs/{jobId}
openapi: 3.1.0
info:
  title: TapTalent Partner API
  version: 1.0.0
  summary: Partner API for jobs, candidates, pipelines, custom fields, and webhooks.
  description: >
    The TapTalent Partner API lets partner systems manage jobs, candidates,

    job-candidate relationships, hiring pipelines, and custom fields, and

    receive real-time event notifications via webhooks. All communication is

    JSON over HTTPS.


    ## Authentication


    Every request requires an API key sent as an HTTP bearer token:


    ```

    Authorization: Bearer sk_live_AbCdEfGhIjKlMnOpQrStUv

    ```


    Keys are prefixed `sk_live_` (production) or `sk_test_` (sandbox) followed

    by 22 base62 characters, are scoped to a company, and are generated from

    the TapTalent dashboard (Account Settings → Developers → API Key

    Management). Key management is dashboard-only and not available via this

    API.


    ## Response envelopes


    The API uses three envelope styles, by resource family:


    | Family | Success envelope |

    |---|---|

    | Jobs | Bare object (e.g. `{ "jobs": [...], "totalJobs": 45 }` or the job
    object itself) |

    | Candidates, Job Candidates, Pipelines, Custom Fields | `{ "status":
    "success", "data": ... }` |

    | Bulk resume upload and batch retrieval | `{ "success": true, "data": ...
    }` |


    Each operation in this specification models its family's actual envelope;

    no unified envelope is imposed.


    ## Pagination


    Pagination conventions vary by endpoint and are modeled as documented:


    | Endpoint | Page parameter | First page | Default page size | Page size
    rule |

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

    | `GET /jobs` | `pageNumber` | 1 | 10 | one of 10, 20, 40, 80, 100 |

    | `GET /candidates/list` | `pageNumber` | **0** | 10 | one of 10, 20, 40,
    80, 100 |

    | `GET /candidates/batch/{batchId}` | `pageNumber` | 1 | 10 | one of 10, 20,
    40, 80, 100 |

    | `GET /job-candidates/job/{jobId}/candidates` | `page` | 1 | 20 | one of
    10, 20, 40, 80, 100 |

    | `GET /job-candidates/stage/{stageId}/candidates` | `page` | 1 | 20 | any
    value from 1 to 100 |


    ## Errors


    Most errors use the canonical envelope:


    ```json

    {
      "error": {
        "code": "ERROR_CODE",
        "type": "error_type",
        "message": "Human-readable error message",
        "details": { "field": "Specific validation error message" }
      }
    }

    ```


    Authentication failures use flat shapes instead (`{"message": ...}`,

    `{"code": ..., "message": ...}` or `{"message": ..., "isApiKeyExists":

    false}`); see the shared 401 response. Rate limits are applied at the

    company level; numeric limits and the 429 response body are not yet

    published.


    ## Webhooks


    Event notifications are delivered as HTTP POST requests to a single

    company-level HTTPS endpoint configured in the dashboard. Deliveries carry

    the headers `X-Webhook-Event`, `X-Webhook-Timestamp`, and `X-Webhook-Key`

    (verify by plain equality against the key generated in the dashboard;

    HMAC signatures are not yet available). Endpoints must respond with a 2xx

    status within 5 seconds; failed deliveries are retried at 200 ms, 400 ms,

    and 800 ms before being marked failed. See the `webhooks` section of this

    document for every event payload.


    ## Conventions used in this specification


    - `x-inferred: true` marks schemas or responses whose shape is inferred
      from related endpoints because the source documentation does not include
      an example; verify against the sandbox before relying on exact field
      names.
    - `x-known-quirk` marks fields whose wire format deviates from the API's
      prevailing conventions (for example an epoch timestamp where other
      endpoints return ISO 8601 strings).
    - Where the published documentation shows placeholder string identifiers
      (for example `"pipelineId_1"` or `"companyId_1"`), this specification
      models the underlying integer identifier types used by the API and notes
      the resolution on the affected field.
  contact:
    name: TapTalent Support
    email: support@taptalent.ai
    url: https://docs.taptalent.io
  license:
    name: Proprietary
    url: https://taptalent.ai
servers:
  - url: https://partner-api.taptalent.io/v1/partner
    description: Production (use `sk_live_` keys)
  - url: https://sandbox.partner-api.taptalent.io/v1/partner
    description: Sandbox / staging (use `sk_test_` keys)
security:
  - bearerAuth: []
tags:
  - name: Jobs
    description: Create, read, update, and list jobs.
  - name: Candidates
    description: >-
      Create and retrieve candidates, upload resumes in bulk, and fetch
      candidates by batch or id list.
  - name: Job Candidates
    description: >-
      Manage the relationship between candidates and jobs, including stage
      placement and per-job resume ingestion.
  - name: Pipelines
    description: Manage hiring pipelines and their stages.
  - name: Custom Fields
    description: Define custom field templates for candidates and jobs.
  - name: Custom Field Values
    description: Read and write custom field values attached to candidates and jobs.
  - name: Webhooks
    description: >-
      Event notifications delivered to your configured webhook endpoint. See the
      top-level `webhooks` section for payloads.
paths:
  /jobs/{jobId}:
    parameters:
      - name: jobId
        in: path
        required: true
        description: The unique identifier of the job.
        schema:
          type: integer
        example: 12345
    put:
      tags:
        - Jobs
      summary: Update a job
      description: |
        Update an existing job posting. All fields are optional; only include
        the fields you want to change (partial update). Fields not included in
        the request remain unchanged. The request body cannot be empty — at
        least one field must be provided.

        Behavior notes:
        - **Status lifecycle**: the documented path is `DRAFT` → `ACTIVE` →
          `INACTIVE` → `DELETED`. Once a job's status moves past `DRAFT` it
          cannot be changed back to `DRAFT` (`INVALID_STATUS_TRANSITION`);
          other reverse transitions are not documented either way.
        - **Null clears**: some fields accept `null` to clear their value
          (`teamId`, `contractType`, `degreeLevel`, `jobRole`,
          `potentialAmount`, `potentialAmountCurrency`, `potentialHiresCount`,
          `yearOfExperience`, `description`, `screeningQuestion`,
          `applicationForm`, `criterionDetails`). `title`, `city`, `state`, and
          `country` cannot be set to `null` — omit them instead.
        - **applicationForm is merged, not replaced**: provide only the
          `applicationForm` keys you want to change; new values override
          existing ones and the rest are kept. If `expectedCTC`/`currentCTC` is
          set to `MANDATORY` or `OPTIONAL` (not `OFF`), the corresponding
          currency key is required unless the job already has a currency value;
          otherwise the update fails.
        - The three salary fields must be provided together if any is
          provided, and `salaryRangeTo` must be greater than
          `salaryRangeFrom`.
        - All field validations (type, length, format) are the same as for
          Create Job.

        The success response is a bare job object that is smaller than the
        create/get response and includes the populated `pipelineStage` array.
      operationId: updateJob
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateJobRequest'
            examples:
              basicTitleUpdate:
                summary: Update a single field
                value:
                  title: Updated Senior Software Engineer Position
              multipleFieldsUpdate:
                summary: Update multiple fields
                value:
                  title: Senior Full Stack Developer
                  description: We are looking for an experienced full stack developer...
                  city: San Francisco
                  state: California
                  country: United States
                  workMode: REMOTE
                  status: ACTIVE
                  contractType: Permanent
                  degreeLevel: Bachelor's
                  jobRole: Engineering
              applicationFormUpdate:
                summary: Update the application form (merged with existing values)
                value:
                  applicationForm:
                    phone: MANDATORY
                    resume: MANDATORY
                    currentJobTitle: OPTIONAL
                    company: 'OFF'
                    isWillingToRelocate: MANDATORY
                    noticePeriod: OPTIONAL
                    expectedCTC: MANDATORY
                    currencyExpectedCTC: USD
                    expectedCTCPeriod: ANNUALLY
                    currentCTC: OPTIONAL
                    currencyCurrentCTC: USD
                    currentCTCPeriod: MONTHLY
                    gender: 'OFF'
                    dateOfBirth: OPTIONAL
                    nationality: MANDATORY
              statusUpdate:
                summary: Update the job status
                value:
                  status: INACTIVE
              salaryRangeUpdate:
                summary: Update the salary range (all three fields together)
                value:
                  salaryRangeFrom: 120000
                  salaryRangeTo: 180000
                  salaryCurrency: USD
              screeningQuestionsUpdate:
                summary: Replace the screening questions
                value:
                  screeningQuestion:
                    - type: text
                      question: Why are you interested in this position?
                    - type: text
                      question: What is your experience with React?
              criterionDetailsUpdate:
                summary: Replace the criterion details
                value:
                  criterionDetails:
                    - priority: Must Have
                      criterion_text: 5+ years of experience in JavaScript
                    - priority: Nice to Have
                      criterion_text: Experience with TypeScript
      responses:
        '200':
          description: |
            The updated job. This shape is smaller than the create/get job
            response and includes the populated `pipelineStage` array.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobUpdateResult'
              examples:
                updatedJob:
                  summary: Updated job
                  value:
                    id: 12345
                    title: Updated Senior Software Engineer Position
                    description: We are looking for an experienced software engineer...
                    city: San Francisco
                    state: California
                    country: United States
                    pipelineId: 181
                    status: ACTIVE
                    workMode: REMOTE
                    screeningQuestion:
                      - type: text
                        question: Why are you interested in this position?
                    applicationForm:
                      phone: MANDATORY
                      resume: MANDATORY
                      currentJobTitle: OPTIONAL
                      company: 'OFF'
                      isWillingToRelocate: MANDATORY
                      noticePeriod: OPTIONAL
                      expectedCTC: MANDATORY
                      currencyExpectedCTC: USD
                      expectedCTCPeriod: ANNUALLY
                      currentCTC: OPTIONAL
                      currencyCurrentCTC: USD
                      currentCTCPeriod: MONTHLY
                      gender: 'OFF'
                      dateOfBirth: OPTIONAL
                      nationality: MANDATORY
                    clientId: 301
                    companyId: 12001
                    teamId: null
                    contractType: Permanent
                    degreeLevel: Bachelor's
                    jobRole: Engineering
                    salaryRangeFrom: 120000
                    salaryRangeTo: 180000
                    salaryCurrency: USD
                    criterionDetails:
                      - priority: Must Have
                        criterion_text: 5+ years of experience in JavaScript
                    pipelineStage:
                      - name: Applied
                        type: APPLIED
                        totalCandidate: 5
        '400':
          description: >
            Validation error.

            HTTP status inferred from the error category; the source
            documentation specifies the body but not the status code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                emptyBody:
                  summary: Empty request body
                  value:
                    error:
                      code: INVALID_REQUEST
                      type: validation_error
                      message: >-
                        Request body cannot be empty. At least one field must be
                        provided for update.
                invalidStatusTransition:
                  summary: Attempt to revert status to DRAFT
                  value:
                    error:
                      code: INVALID_STATUS_TRANSITION
                      type: validation_error
                      message: >-
                        Cannot change job status back to DRAFT. Current status
                        is ACTIVE. Once a job moves from DRAFT, it cannot be
                        reverted.
                missingCurrencyForCtc:
                  summary: Missing currency for CTC field
                  value:
                    error:
                      code: INVALID_REQUEST
                      type: validation_error
                      message: >-
                        currencyExpectedCTC is required when expectedCTC is not
                        OFF
                invalidSalaryRange:
                  summary: Invalid salary range
                  value:
                    error:
                      code: INVALID_REQUEST
                      type: validation_error
                      message: One or more fields are invalid.
                      details:
                        salaryRangeTo: salaryRangeTo must be greater than salaryRangeFrom
                partialSalaryFields:
                  summary: Partial salary fields (missing one of the trio)
                  value:
                    error:
                      code: INVALID_REQUEST
                      type: validation_error
                      message: One or more fields are invalid.
                      details:
                        salaryCurrency: >-
                          salaryRangeFrom, salaryRangeTo, and salaryCurrency
                          must be provided together
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >
            The job does not belong to your company.

            HTTP status inferred from the error category; the source
            documentation specifies the body but not the status code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                permissionDenied:
                  summary: Permission denied
                  value:
                    error:
                      code: PERMISSION_DENIED
                      type: authorization_error
                      message: >-
                        You are not authorized to update this job. The job does
                        not belong to your company.
        '404':
          description: >
            Job not found.

            HTTP status inferred from the error category; the source
            documentation specifies the body but not the status code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                jobNotFound:
                  summary: Job not found
                  value:
                    error:
                      code: NOT_FOUND
                      type: not_found
                      message: Job not found
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    UpdateJobRequest:
      type: object
      description: |
        Request body for updating a job. All fields are optional — include only
        the fields you want to change; omitted fields remain unchanged. The
        body cannot be empty: at least one field must be provided. Field
        validations (type, length, format) are the same as for Create Job.

        Fields that accept `null` to clear their value: `teamId`,
        `contractType`, `degreeLevel`, `jobRole`, `potentialAmount`,
        `potentialAmountCurrency`, `potentialHiresCount`, `yearOfExperience`,
        `description`, `screeningQuestion`, `applicationForm`, and
        `criterionDetails`. `title`, `city`, `state`, and `country` cannot be
        set to `null`.
      minProperties: 1
      dependentRequired:
        salaryRangeFrom:
          - salaryRangeTo
          - salaryCurrency
        salaryRangeTo:
          - salaryRangeFrom
          - salaryCurrency
        salaryCurrency:
          - salaryRangeFrom
          - salaryRangeTo
        potentialAmount:
          - potentialAmountCurrency
      properties:
        title:
          type: string
          description: The job title displayed to candidates. Cannot be set to `null`.
          minLength: 3
          maxLength: 500
        city:
          type: string
          description: >-
            The city where the job is located. Cannot be set to `null` — omit to
            leave unchanged.
          maxLength: 200
        state:
          type: string
          description: >-
            The state or province where the job is located. Cannot be set to
            `null` — omit to leave unchanged.
          maxLength: 200
        country:
          type: string
          description: >-
            The country where the job is located. Cannot be set to `null` — omit
            to leave unchanged.
          maxLength: 200
        description:
          type:
            - string
            - 'null'
          description: Detailed job description. May be set to `null` to clear it.
          maxLength: 10000
        status:
          $ref: '#/components/schemas/JobStatus'
          description: |
            New job status. Unlike creation, all four values are allowed here.
            The documented lifecycle path is
            `DRAFT` → `ACTIVE` → `INACTIVE` → `DELETED`; once a job's status
            moves past `DRAFT`, it cannot be changed back to `DRAFT`
            (`INVALID_STATUS_TRANSITION`). Other reverse transitions are not
            documented either way.
        workMode:
          $ref: '#/components/schemas/WorkMode'
          description: Work arrangement for the position.
        screeningQuestion:
          type:
            - array
            - 'null'
          description: |
            Replaces the job's pre-screening questions (maximum 15). May be set
            to `null` to clear them.
          maxItems: 15
          items:
            $ref: '#/components/schemas/ScreeningQuestion'
        teamId:
          type:
            - string
            - 'null'
          format: uuid
          description: Team assignment. May be set to `null` to clear it.
        contractType:
          description: Employment contract type. May be set to `null` to clear it.
          anyOf:
            - $ref: '#/components/schemas/ContractType'
            - type: 'null'
        degreeLevel:
          description: Minimum education level required. May be set to `null` to clear it.
          anyOf:
            - $ref: '#/components/schemas/DegreeLevel'
            - type: 'null'
        jobRole:
          description: Job role category. May be set to `null` to clear it.
          anyOf:
            - $ref: '#/components/schemas/JobRole'
            - type: 'null'
        salaryRangeFrom:
          type: integer
          description: |
            Minimum annual salary. If any salary field is provided, all three
            (`salaryRangeFrom`, `salaryRangeTo`, `salaryCurrency`) must be
            provided together.
          minimum: 0
          maximum: 9999999999
        salaryRangeTo:
          type: integer
          description: |
            Maximum annual salary. Must be greater than `salaryRangeFrom`. If
            any salary field is provided, all three must be provided together.
          minimum: 0
          maximum: 9999999999
        salaryCurrency:
          $ref: '#/components/schemas/SalaryCurrency'
          description: |
            Currency for the salary range. If any salary field is provided, all
            three must be provided together.
        potentialAmount:
          type:
            - number
            - 'null'
          description: |
            Potential revenue or value associated with filling this position.
            `potentialAmountCurrency` is required when this is provided. May be
            set to `null` to clear it.
          minimum: 0
        potentialAmountCurrency:
          type:
            - string
            - 'null'
          description: |
            Currency for the potential amount (3-character uppercase code).
            May be set to `null` to clear it.
          pattern: ^[A-Z]{3}$
        potentialHiresCount:
          type:
            - integer
            - 'null'
          description: Number of people you plan to hire. May be set to `null` to clear it.
          minimum: 1
        yearOfExperience:
          type:
            - number
            - 'null'
          description: >-
            Minimum years of professional experience required (0-50). May be set
            to `null` to clear it.
          minimum: 0
          maximum: 50
        applicationForm:
          description: |
            Candidate application form configuration. The submitted object is
            MERGED with the job's existing `applicationForm` — provide only the
            keys you want to change; new values override existing ones. If
            `expectedCTC`/`currentCTC` is set to `MANDATORY` or `OPTIONAL`, the
            corresponding currency key is required unless the job already has an
            existing currency value. May be set to `null` to clear the
            configuration.
          anyOf:
            - $ref: '#/components/schemas/ApplicationForm'
            - type: 'null'
        criterionDetails:
          type:
            - array
            - 'null'
          description: |
            Replaces the job's criterion details (maximum 7). May be set to
            `null` to clear them.
          maxItems: 7
          items:
            $ref: '#/components/schemas/CriterionDetail'
    JobUpdateResult:
      type: object
      description: |
        Job object returned by the update endpoint. This shape is smaller than
        the create/get `Job` response — it omits `skills`, `careerLevel`,
        `publishType`, `companyClientId`, `potentialAmount`,
        `potentialAmountCurrency`, `potentialHiresCount`, `closingStatus`,
        `closingReason`, `referralTemplateId`, and `jobType` — and includes the
        populated `pipelineStage` array.
      required:
        - id
        - title
        - city
        - state
        - country
        - pipelineId
        - status
        - workMode
      properties:
        id:
          type: integer
          description: Unique identifier of the job.
        title:
          type: string
          description: Job title displayed to candidates.
        description:
          type: string
          description: Detailed job description.
        city:
          type: string
          description: Job location city.
        state:
          type: string
          description: Job location state/province.
        country:
          type: string
          description: Job location country.
        pipelineId:
          type: integer
          description: |
            Identifier of the hiring pipeline attached to the job. The published
            documentation shows the placeholder string "pipelineId_1"; the API
            uses the integer pipeline id (as in the Pipelines API).
          examples:
            - 181
        status:
          $ref: '#/components/schemas/JobStatus'
        workMode:
          $ref: '#/components/schemas/WorkMode'
        screeningQuestion:
          type: array
          description: Pre-screening questions candidates must answer when applying.
          items:
            $ref: '#/components/schemas/ScreeningQuestion'
        applicationForm:
          $ref: '#/components/schemas/ApplicationForm'
        clientId:
          type: integer
          description: |
            Undocumented; type observed from examples. The documentation shows
            the placeholder string "clientId_1"; modeled as the underlying
            integer client id.
          examples:
            - 301
        companyId:
          type: integer
          description: |
            Undocumented; type observed from examples. The documentation shows
            the placeholder string "companyId_1"; modeled as the underlying
            integer company id.
          examples:
            - 12001
        teamId:
          type:
            - string
            - 'null'
          format: uuid
          description: Team the job is assigned to, or `null` if unassigned.
        contractType:
          $ref: '#/components/schemas/ContractType'
        degreeLevel:
          $ref: '#/components/schemas/DegreeLevel'
        jobRole:
          $ref: '#/components/schemas/JobRole'
        salaryRangeFrom:
          type: integer
          description: Minimum annual salary.
        salaryRangeTo:
          type: integer
          description: Maximum annual salary.
        salaryCurrency:
          $ref: '#/components/schemas/SalaryCurrency'
        criterionDetails:
          type: array
          description: Job requirements used for AI candidate matching.
          items:
            $ref: '#/components/schemas/CriterionDetail'
        pipelineStage:
          type: array
          description: >-
            Pipeline stages of the job with per-stage candidate counts
            (populated in the update response).
          items:
            $ref: '#/components/schemas/JobPipelineStage'
    ApiError:
      type: object
      description: Canonical error envelope used by most non-authentication errors.
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ApiErrorBody'
    JobStatus:
      type: string
      description: |
        Job lifecycle status. The documented lifecycle path is
        `DRAFT` → `ACTIVE` → `INACTIVE` → `DELETED`. The only documented
        restriction is that once a job leaves `DRAFT` it can never return to
        `DRAFT`; other reverse transitions (e.g. reactivation) are not
        documented either way. When creating a job only `DRAFT` and
        `ACTIVE` are allowed (see `JobStatusCreate`).
      enum:
        - DRAFT
        - ACTIVE
        - INACTIVE
        - DELETED
    WorkMode:
      type: string
      description: |
        Work arrangement for the position. `ONSITE` (default at creation): work
        at a physical office location; `REMOTE`: work from anywhere; `HYBRID`:
        a combination of onsite and remote work.
      enum:
        - ONSITE
        - REMOTE
        - HYBRID
    ScreeningQuestion:
      type: object
      description: A pre-screening question candidates must answer when applying.
      required:
        - type
        - question
      properties:
        type:
          type: string
          description: Question type. Only text questions are supported.
          enum:
            - text
        question:
          type: string
          description: The question text.
          minLength: 1
          maxLength: 3000
    ContractType:
      type: string
      description: Employment contract type.
      enum:
        - Permanent
        - Freelance / Consultant
        - Fixed term contract
        - Internship
        - Student
    DegreeLevel:
      type: string
      description: Minimum education level required for the position.
      enum:
        - High School
        - Bachelor's
        - Master's
        - M.B.A.
        - Ph.D.
        - Other
    JobRole:
      type: string
      description: Job role category, used for job organization and candidate matching.
      enum:
        - Accounting
        - Administrative
        - Customer Service
        - Design
        - Education
        - Engineering
        - Finance
        - Healthcare
        - Hospitality & Tourism
        - Human Resources (HR)
        - Information Technology (IT)
        - Legal
        - Marketing
        - Media & Public Relations (PR)
        - Pharmaceuticals
        - Production
        - Property Management
        - Public Service & Security
        - Real Estate
        - Retail
        - Sales
        - Supply Chain & Logistics
    SalaryCurrency:
      type: string
      description: Currency code for the salary range.
      enum:
        - USD
        - PHP
        - SGD
        - IDR
        - EUR
        - INR
        - GBP
        - AED
        - MYR
        - AUD
        - CAD
        - JPY
        - CNY
        - CHF
        - ZAR
        - KRW
        - THB
        - VND
        - BRL
        - MXN
        - RUB
        - TRY
        - SEK
        - NOK
        - DKK
        - PLN
        - HKD
        - MAD
    ApplicationForm:
      type: object
      description: |
        Configuration of the candidate application form: which fields are
        required, optional, or hidden when a candidate applies to the job. All
        keys are optional — specify only the fields you want to configure. If
        the object is omitted at creation, the system sets default values
        automatically. When updating a job, the submitted object is MERGED with
        the job's existing `applicationForm` (new values override existing
        ones); it is not replaced wholesale.
      properties:
        phone:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Phone number field requirement.
        currentJobTitle:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Current job title field requirement.
        resume:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Resume/CV upload requirement.
        otherFiles:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Other documents upload requirement.
        company:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Current company field requirement.
        isWillingToRelocate:
          type: string
          description: |
            Willingness-to-relocate question. Unlike the other form fields this
            one has no `OPTIONAL` value — it is either `MANDATORY` or `OFF`.
          enum:
            - MANDATORY
            - 'OFF'
        noticePeriod:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Notice period field requirement.
        expectedCTC:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: |
            Expected compensation requirement. If set to `MANDATORY` or
            `OPTIONAL` (i.e. not `OFF`), `currencyExpectedCTC` is required
            (on update: unless the job already has an existing currency value).
        currentCTC:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: |
            Current compensation requirement. If set to `MANDATORY` or
            `OPTIONAL` (i.e. not `OFF`), `currencyCurrentCTC` is required
            (on update: unless the job already has an existing currency value).
        currencyExpectedCTC:
          type: string
          description: |
            Currency code for the expected CTC (e.g. `USD`). Required if
            `expectedCTC` is not `OFF` (on update: and the job has no existing
            currency value).
          examples:
            - USD
        currencyCurrentCTC:
          type: string
          description: |
            Currency code for the current CTC (e.g. `USD`). Required if
            `currentCTC` is not `OFF` (on update: and the job has no existing
            currency value).
          examples:
            - USD
        expectedCTCPeriod:
          type: string
          description: Period for the expected CTC.
          enum:
            - ANNUALLY
            - MONTHLY
        currentCTCPeriod:
          type: string
          description: Period for the current CTC.
          enum:
            - ANNUALLY
            - MONTHLY
        gender:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Gender field requirement.
        dateOfBirth:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Date of birth field requirement.
        nationality:
          $ref: '#/components/schemas/ApplicationFormRequirement'
          description: Nationality field requirement.
    CriterionDetail:
      type: object
      description: |
        A job requirement/qualification used by TapTalent's AI to evaluate and
        score candidates. "Must Have" criteria carry more weight in match
        scoring than "Nice to Have" or "Bonus" criteria.
      required:
        - criterion_text
      properties:
        priority:
          type: string
          description: |
            Priority level of the criterion. Defaults to "Nice to Have" when
            omitted.
          enum:
            - Must Have
            - Nice to Have
            - Bonus
          default: Nice to Have
        criterion_text:
          type: string
          description: The requirement description.
          minLength: 1
          maxLength: 3000
    JobPipelineStage:
      type: object
      description: >-
        A pipeline stage of a job, with the number of candidates currently in
        it.
      required:
        - name
        - type
        - totalCandidate
      properties:
        name:
          type: string
          description: Stage display name.
          examples:
            - Applied
        type:
          type: string
          description: Stage type identifier (e.g. `APPLIED`, `INTERVIEW`).
          examples:
            - APPLIED
        totalCandidate:
          type: integer
          description: Number of candidates currently in this stage.
    ApiErrorBody:
      type: object
      description: Canonical error object carried under the `error` key.
      required:
        - code
        - type
        - message
      properties:
        code:
          type: string
          description: Machine-readable error code, e.g. `INVALID_REQUEST`.
          examples:
            - INVALID_REQUEST
        type:
          type: string
          description: Error category.
          enum:
            - validation_error
            - internal_error
            - not_found
            - authorization_error
            - resource_error
            - payment_error
            - subscription_error
        message:
          type: string
          description: Human-readable error message.
        details:
          type: object
          description: Optional per-field validation messages or structured error context.
          additionalProperties: true
    AuthMessageError:
      type: object
      description: >-
        Flat authentication error shape (does not use the canonical `error`
        envelope).
      required:
        - message
      properties:
        message:
          type: string
          examples:
            - Invalid API key
    AuthCodeMessageError:
      type: object
      description: >-
        Flat authentication error shape returned when the account subscription
        is inactive.
      required:
        - code
        - message
      properties:
        code:
          type: string
          examples:
            - ACCOUNT_INACTIVE
        message:
          type: string
          examples:
            - >-
              Your subscription is inactive. Please renew your plan to continue
              using this feature.
    AuthApiKeyError:
      type: object
      description: >-
        Flat authentication error shape returned when the API key does not
        exist.
      required:
        - message
        - isApiKeyExists
      properties:
        message:
          type: string
          examples:
            - API key not found
        isApiKeyExists:
          type: boolean
    ApplicationFormRequirement:
      type: string
      description: |
        Requirement level for a candidate application form field: `OPTIONAL`
        (shown, not required), `MANDATORY` (shown and required), or `OFF`
        (hidden).
      enum:
        - OPTIONAL
        - MANDATORY
        - 'OFF'
  responses:
    Unauthorized:
      description: |
        Authentication failed. Note that authentication errors use flat body
        shapes rather than the canonical `error` envelope.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: '#/components/schemas/AuthMessageError'
              - $ref: '#/components/schemas/AuthCodeMessageError'
              - $ref: '#/components/schemas/AuthApiKeyError'
          examples:
            invalidApiKey:
              summary: Invalid API key
              value:
                message: Invalid API key
            accountInactive:
              summary: Subscription inactive
              value:
                code: ACCOUNT_INACTIVE
                message: >-
                  Your subscription is inactive. Please renew your plan to
                  continue using this feature.
            apiKeyNotFound:
              summary: API key not found
              value:
                message: API key not found
                isApiKeyExists: false
    TooManyRequests:
      x-inferred: true
      description: |
        Rate limit exceeded. Rate limits are applied at the company level; the
        response body below is inferred because the current documentation
        mentions handling 429 responses but does not publish a body. Retry
        with exponential backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            rateLimited:
              summary: Rate limit exceeded (inferred example)
              value:
                error:
                  code: RATE_LIMIT_EXCEEDED
                  type: validation_error
                  message: Too many requests. Please retry with exponential backoff.
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            internalError:
              summary: Internal error
              value:
                error:
                  code: INTERNAL_ERROR
                  type: internal_error
                  message: Something went wrong.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: |
        Company-scoped API key. Production keys are prefixed `sk_live_`,
        sandbox keys `sk_test_`, each followed by 22 base62 characters
        (pattern `^sk_(live|test)_[0-9A-Za-z]{22}$`). Generate keys in the
        TapTalent dashboard under Account Settings → Developers → API Key
        Management; a key is shown once at generation and old keys are
        invalidated immediately on regeneration.

````