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

# Search jobs

> Advanced job search with filtering, sorting, and vector search. Supports all filter types: keywords, location, job status, companies, team members/roles, custom attributes (select, numeric, date, team member), and semantic vector search.

**AI AGENTS — Use `vector_search` if the user is inquiring about roles by title or title and company. Do not use `keywords`.**
Job titles have many equivalent forms ("VP of Engineering", "VP Engineering", "Engineering VP", "Head of Engineering") — keywords will silently miss them . Vector search handles all variants automatically.
The exception: a verbatim job ID/code lookup where you need an exact internal reference (e.g. "find the jobID 1234").

**Vector search**: Pass `vector_search` with a text query (min 5 chars) for AI-powered semantic search.

**Date range filters**: Use `created_at_gte`/`created_at_lte` and `updated_at_gte`/`updated_at_lte` to filter by creation or modification timestamps.

**Custom attribute filters**: Use `select_attribute_filters`, `numeric_attribute_filters`, `date_attribute_filters`, `team_member_attribute_filters` for custom field filtering.

**Include control**: Pass `include: ["custom_fields", "linked_deals", "fees"]` to embed custom field values, linked deals, and/or fee & placement data in each job.AI AGENTS — Result processing: After receiving results, reason and process them before presenting to the user. Only show jobs where the title genuinely matches what the user asked for. For example, if the user asks for "VP of Engineering" roles, exclude results like "VP Consumer Electronics" or "SVP Sales Engineering" — these are not engineering leadership roles. Show relevant results rather than regurgitating everything the vector search returns.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /v1/jobs/search
openapi: 3.1.0
info:
  title: Stardex API (v1)
  version: 1.0.0
  description: >-
    Stardex ATS API — manage candidates, jobs, companies, and recruiting
    workflows.
servers:
  - url: https://api.stardex.ai
    description: Production API server
security:
  - bearerAuth: []
tags:
  - name: Persons
    description: Manage person records — contacts, work history, and custom fields.
  - name: Jobs
    description: Manage job postings — pipeline stages, team members, and custom fields.
  - name: Candidates
    description: Manage candidate records and pipeline stage transitions.
  - name: Companies
    description: Browse and retrieve company records.
  - name: Lists
    description: Create, search, and retrieve saved person and company lists.
  - name: Person Activities
    description: Create and manage activity records (notes, emails, meetings) for persons.
  - name: Team Members
    description: List team members for use in search filters and assignments.
  - name: Custom Fields
    description: Retrieve custom field definitions and tag options for search filters.
paths:
  /v1/jobs/search:
    post:
      tags:
        - Jobs
      summary: Search jobs
      description: >-
        Advanced job search with filtering, sorting, and vector search. Supports
        all filter types: keywords, location, job status, companies, team
        members/roles, custom attributes (select, numeric, date, team member),
        and semantic vector search.


        **AI AGENTS — Use `vector_search` if the user is inquiring about roles
        by title or title and company. Do not use `keywords`.**

        Job titles have many equivalent forms ("VP of Engineering", "VP
        Engineering", "Engineering VP", "Head of Engineering") — keywords will
        silently miss them . Vector search handles all variants automatically.

        The exception: a verbatim job ID/code lookup where you need an exact
        internal reference (e.g. "find the jobID 1234").


        **Vector search**: Pass `vector_search` with a text query (min 5 chars)
        for AI-powered semantic search.


        **Date range filters**: Use `created_at_gte`/`created_at_lte` and
        `updated_at_gte`/`updated_at_lte` to filter by creation or modification
        timestamps.


        **Custom attribute filters**: Use `select_attribute_filters`,
        `numeric_attribute_filters`, `date_attribute_filters`,
        `team_member_attribute_filters` for custom field filtering.


        **Include control**: Pass `include: ["custom_fields", "linked_deals",
        "fees"]` to embed custom field values, linked deals, and/or fee &
        placement data in each job.AI AGENTS — Result processing: After
        receiving results, reason and process them before presenting to the
        user. Only show jobs where the title genuinely matches what the user
        asked for. For example, if the user asks for "VP of Engineering" roles,
        exclude results like "VP Consumer Electronics" or "SVP Sales
        Engineering" — these are not engineering leadership roles. Show relevant
        results rather than regurgitating everything the vector search returns.
      operationId: searchJobs
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobsSearchBody'
      responses:
        '200':
          description: Jobs found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobsSearchResponse'
              example:
                success: true
                data:
                  - id: 123e4567-e89b-12d3-a456-426614174000
                    name: Senior Software Engineer
                    created_at: '2024-01-10T09:00:00Z'
                    is_archived: false
                    client_company_name: StartupXYZ
                    client_company_id: 456e7890-e12b-34d5-a678-901234567890
                    client_company_domain: startupxyz.com
                    client_company_linkedin_url: https://www.linkedin.com/company/startupxyz
                    job_status_name: Active
                    job_status_id: 789e0123-e45f-67a8-b901-234567890123
                    candidate_count: 12
                    location: San Francisco, CA
                    primary_url: https://startupxyz.com/careers/senior-swe
                    job_function: Engineering
                    open_date: '2024-01-01'
                    end_date: null
                    currency_code: USD
                    salary_range: '[150000,200000]'
                    salary_min: 150000
                    salary_max: 200000
                    salary_details: + 0.5% equity, signing bonus negotiable
                    billing_contact_name: Sarah Chen
                    billing_contact_email: sarah.chen@startupxyz.com
                    fee: 25000
                    description: >-
                      We are looking for a Senior Software Engineer to join our
                      platform team...
                    team_members:
                      - team_member_id: 234e5678-e90a-12b3-c456-789012345678
                        email: jane@company.com
                        first_name: Jane
                        last_name: Smith
                        role_id: 345e6789-e01b-23c4-d567-890123456789
                        role_name: Team Lead
                      - team_member_id: 345e6789-f01b-23c4-d567-890123456789
                        email: bob@company.com
                        first_name: Bob
                        last_name: Johnson
                        role_id: 456e7890-f12b-34d5-e678-901234567890
                        role_name: Executive Sponsor
                    linked_deals:
                      - deal_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                        deal_job_id: b2c3d4e5-f6a7-8901-bcde-f12345678901
                        name: StartupXYZ — Senior SWE retained search
                        amount: 35000
                        currency_code: USD
                        deal_status_id: 7201a0b8-e63c-4d8f-899d-78cdd62b5c38
                        deal_status_name: Qualified
                        deal_status_color: '#10B981'
                    fees:
                      retainer:
                        id: e5f6a7b8-c9d0-1234-ef01-345678901234
                        fee_type: percentage
                        fee_base: first_year_salary
                        fee_percentage: 25
                        projected_fee: 50000
                        estimated_compensation: 200000
                        installment_count: 3
                        final_payment_type: on_placement
                        currency_code: USD
                      fee_events:
                        - id: f6a7b8c9-d0e1-2345-f012-456789012345
                          type: retainer
                          label: Engagement fee
                          amount: 16666.67
                          total_fee: 50000
                          currency_code: USD
                          fee_type: percentage
                          fee_percentage: 25
                          compensation: 200000
                          firm_commission_percent: 100
                          is_placeholder: false
                          sequence: 1
                          start_date: '2024-01-05'
                          expected_date: '2024-01-10'
                          actual_payment_date: '2024-01-11'
                          candidate_id: null
                          offer_id: null
                          retainer_id: e5f6a7b8-c9d0-1234-ef01-345678901234
                          fee_status_id: a7b8c9d0-e1f2-3456-0123-567890123456
                          fee_status_name: Paid
                          fee_status_color: '#10B981'
                          fee_status_type: paid
                        - id: b8c9d0e1-f2a3-4567-1234-678901234567
                          type: placement
                          label: Placement — Jane Smith
                          amount: 50000
                          total_fee: 50000
                          currency_code: USD
                          fee_type: percentage
                          fee_percentage: 25
                          compensation: 200000
                          firm_commission_percent: 100
                          is_placeholder: false
                          sequence: null
                          start_date: null
                          expected_date: '2024-03-15'
                          actual_payment_date: null
                          candidate_id: 234e5678-e90a-12b3-c456-789012345678
                          offer_id: c9d0e1f2-a3b4-5678-2345-789012345678
                          retainer_id: null
                          fee_status_id: d0e1f2a3-b4c5-6789-3456-890123456789
                          fee_status_name: Invoiced
                          fee_status_color: '#3B82F6'
                          fee_status_type: invoiced
                      total_placement_fee: 50000
                    custom_fields:
                      - attribute_id: c3d4e5f6-a7b8-9012-cdef-123456789012
                        attribute_name: Priority
                        data_type: single-select
                        value: null
                        tag:
                          id: d4e5f6a7-b8c9-0123-defg-234567890123
                          name: High
                        team_member: null
                meta:
                  total: 25
                  offset: 0
                  limit: 200
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
components:
  schemas:
    JobsSearchBody:
      type: object
      properties:
        offset:
          type: integer
          minimum: 0
          default: 0
          description: Records to skip for pagination. Defaults to 0.
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 200
          description: Max records to return (1–200). Defaults to 200.
        sort_by:
          type: string
          description: >-
            Sort column. Values: title, company, status, fee, created_at,
            days_since_opened, location, total_candidates, or
            custom_<attribute_id>. Defaults to created_at.
        sort_order:
          type: string
          enum:
            - asc
            - desc
          default: desc
          description: Sort direction. Defaults to desc (newest first).
        keywords:
          type: array
          items:
            type: string
          description: >-
            Full-text search across job title, description, location, and
            company name/domain.
        location_keywords:
          type: array
          items:
            type: string
          description: Search specifically in the job location field.
        vector_search:
          type: string
          minLength: 5
          description: >-
            AI semantic search query (min 5 chars). Uses vector embeddings for
            contextual matching.
        is_archived:
          type: boolean
          default: false
          description: Filter by archive status. Defaults to false (active jobs only).
        job_status_ids_included:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Include only jobs with these status IDs. Status IDs are returned in
            job list/detail responses as job_status_id.
        job_status_ids_excluded:
          type: array
          items:
            type: string
            format: uuid
          description: Exclude jobs with these status IDs.
        company_ids_included:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Include only jobs for these client companies. Get IDs from GET
            /v1/companies.
        company_ids_excluded:
          type: array
          items:
            type: string
            format: uuid
          description: Exclude jobs for these client companies.
        owner_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Filter to jobs owned by these team members (owner role). Get IDs
            from GET /v1/team-members.
        team_member_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Filter to jobs with any of these team members assigned. Get IDs from
            GET /v1/team-members.
        team_member_role_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Filter to jobs that have members with these roles. Get role IDs from
            GET /v1/jobs/team-member-roles.
        is_public:
          type: boolean
          description: Filter for publicly posted jobs only.
        created_at_gte:
          type: string
          format: date-time
          description: >-
            Filter jobs created on or after this ISO 8601 datetime (e.g.
            "2024-01-01T00:00:00Z").
        created_at_lte:
          type: string
          format: date-time
          description: >-
            Filter jobs created on or before this ISO 8601 datetime (e.g.
            "2024-12-31T23:59:59Z").
        updated_at_gte:
          type: string
          format: date-time
          description: >-
            Filter jobs updated on or after this ISO 8601 datetime (e.g.
            "2024-01-01T00:00:00Z").
        updated_at_lte:
          type: string
          format: date-time
          description: >-
            Filter jobs updated on or before this ISO 8601 datetime (e.g.
            "2024-12-31T23:59:59Z").
        list_id:
          type: string
          format: uuid
          description: Filter to jobs in this saved list.
        select_attribute_filters:
          type: array
          items:
            type: object
            properties:
              attribute_id:
                type: string
                format: uuid
                description: >-
                  Attribute definition UUID. Get from GET
                  /v1/custom-fields/{entity}.
              values:
                type: array
                items:
                  type: string
                default: []
                description: >-
                  Tag option UUIDs to include. Get tag IDs from the attribute's
                  tags array in custom field definitions.
              excluded_values:
                type: array
                items:
                  type: string
                default: []
                description: Tag option UUIDs to exclude.
              require_all:
                type: boolean
                default: false
                description: >-
                  When true, record must have ALL specified tags (AND logic).
                  When false, any tag matches (OR logic).
              include_empty:
                type: boolean
                default: false
                description: >-
                  When true, also include records with no value set for this
                  attribute.
            required:
              - attribute_id
          description: >-
            Filter by select/multi-select custom fields. Get attribute_id and
            tag IDs from GET /v1/custom-fields/jobs.
        numeric_attribute_filters:
          type: array
          items:
            type: object
            properties:
              attribute_id:
                type: string
                format: uuid
                description: >-
                  Attribute definition UUID (integer or decimal type). Get from
                  GET /v1/custom-fields/{entity}.
              min:
                type:
                  - number
                  - 'null'
                description: Minimum value (inclusive). Null for no lower bound.
              max:
                type:
                  - number
                  - 'null'
                description: Maximum value (inclusive). Null for no upper bound.
              include_empty:
                type: boolean
                default: false
                description: When true, also include records with no value set.
            required:
              - attribute_id
          description: >-
            Filter by numeric custom fields (min/max range). Get attribute_id
            from GET /v1/custom-fields/jobs.
        date_attribute_filters:
          type: array
          items:
            type: object
            properties:
              attribute_id:
                type: string
                format: uuid
                description: >-
                  Attribute definition UUID (date type). Get from GET
                  /v1/custom-fields/{entity}.
              start_date:
                type:
                  - string
                  - 'null'
                description: Start of date range (ISO 8601). Null for no lower bound.
              end_date:
                type:
                  - string
                  - 'null'
                description: End of date range (ISO 8601). Null for no upper bound.
              include_empty:
                type: boolean
                default: false
                description: When true, also include records with no value set.
            required:
              - attribute_id
          description: >-
            Filter by date custom fields (date range). Get attribute_id from GET
            /v1/custom-fields/jobs.
        team_member_attribute_filters:
          type: array
          items:
            type: object
            properties:
              attribute_id:
                type: string
                format: uuid
                description: >-
                  Attribute definition UUID (multi-team-member type). Get from
                  GET /v1/custom-fields/{entity}.
              values:
                type: array
                items:
                  type: string
                  format: uuid
                default: []
                description: >-
                  Team member UUIDs to include. Get IDs from GET
                  /v1/team-members.
              excluded_values:
                type: array
                items:
                  type: string
                  format: uuid
                default: []
                description: Team member UUIDs to exclude.
              require_all:
                type: boolean
                default: false
                description: >-
                  When true, record must have ALL specified team members (AND
                  logic).
              include_empty:
                type: boolean
                default: false
                description: >-
                  When true, also include records with no team member assigned
                  for this attribute.
            required:
              - attribute_id
          description: >-
            Filter by team-member custom fields. Get attribute_id from GET
            /v1/custom-fields/jobs, team member IDs from GET /v1/team-members.
        include:
          type: array
          items:
            type: string
            enum:
              - custom_fields
              - linked_deals
              - fees
          description: >-
            Extra sections to embed. Values: custom_fields, linked_deals, fees.
            Omit for base fields only.
    JobsSearchResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          type: array
          items:
            $ref: '#/components/schemas/JobBase'
        meta:
          type: object
          properties:
            total:
              type: number
              description: Total matching records across all pages.
            offset:
              type: number
              description: Current pagination offset.
            limit:
              type: number
              description: Page size used for this request.
          required:
            - total
            - offset
            - limit
      required:
        - success
        - data
        - meta
    JobBase:
      type: object
      properties:
        id:
          type: string
          description: >-
            Unique job UUID. Use in GET /v1/jobs/{id} for full details with
            pipeline stages.
        name:
          type: string
          description: Job title.
        created_at:
          type: string
          description: ISO 8601 creation timestamp.
        is_archived:
          type: boolean
          description: True if the job has been archived.
        client_company_name:
          type:
            - string
            - 'null'
          description: Client company name.
        client_company_id:
          type:
            - string
            - 'null'
          description: Client company UUID. Matches IDs from GET /v1/companies.
        client_company_domain:
          type:
            - string
            - 'null'
          description: Client company website domain (e.g. "acme.com").
        client_company_linkedin_url:
          type:
            - string
            - 'null'
          description: Client company LinkedIn URL.
        job_status_name:
          type:
            - string
            - 'null'
          description: Current job status label (e.g. "Active", "On Hold", "Closed").
        job_status_id:
          type:
            - string
            - 'null'
          description: >-
            Job status UUID. Use in job_status_ids_included/excluded filters in
            POST /v1/jobs/search.
        candidate_count:
          type: number
          description: Total number of active (non-archived) candidates in this job.
        location:
          type:
            - string
            - 'null'
          description: Job location (e.g. "New York, NY" or "Remote").
        primary_url:
          type:
            - string
            - 'null'
          description: Primary job posting URL.
        job_function:
          type:
            - string
            - 'null'
          description: Department or function (e.g. "Engineering", "Sales", "Marketing").
        open_date:
          type:
            - string
            - 'null'
          description: Date job opened (YYYY-MM-DD).
        end_date:
          type:
            - string
            - 'null'
          description: Target close date (YYYY-MM-DD). Null if open-ended.
        currency_code:
          type:
            - string
            - 'null'
          description: ISO 4217 currency code (e.g. "USD", "EUR").
        salary_range:
          type:
            - string
            - 'null'
          description: >-
            Salary range as PostgreSQL int4range string (e.g.
            "[150000,200000]"). Parsed numeric bounds are available on
            salary_min and salary_max.
        salary_min:
          type:
            - integer
            - 'null'
          description: >-
            Minimum annual salary parsed from salary_range. Null when no range
            is set.
        salary_max:
          type:
            - integer
            - 'null'
          description: >-
            Maximum annual salary parsed from salary_range. Null when no range
            is set.
        salary_details:
          type:
            - string
            - 'null'
          description: >-
            Free-text salary details that complement the structured range (e.g.
            "+ 0.5% equity, signing bonus negotiable").
        billing_contact_name:
          type:
            - string
            - 'null'
          description: >-
            Name of the client-side billing contact for this job (used on
            invoices).
        billing_contact_email:
          type:
            - string
            - 'null'
          description: >-
            Email of the client-side billing contact for this job. Validated as
            an email on write.
        fee:
          type:
            - number
            - 'null'
          description: >-
            Manually entered forecasting fee stored on the job (used for
            pipeline/BD forecasting). This is NOT the fee tracked in the "Fees
            and Placements" section — for that, use the "fees" section (see
            fees.total_placement_fee).
        description:
          type:
            - string
            - 'null'
          description: Plain-text job description.
        team_members:
          type: array
          items:
            $ref: '#/components/schemas/JobTeamMember'
          description: Team members assigned to this job with their roles.
        linked_deals:
          type: array
          items:
            $ref: '#/components/schemas/LinkedJobDeal'
          description: >-
            CRM deals linked to this job via the deal_jobs join table. This is
            separate from the "Fees and Placements" section — logging a
            placement or retainer does NOT create a linked deal. Always included
            on GET /v1/jobs/{id}. On list/search endpoints, included only when
            "linked_deals" is in the include parameter.
        fees:
          allOf:
            - $ref: '#/components/schemas/JobFees'
            - description: >-
                Fee and placement data from the "Fees and Placements" section
                (retainer structure, placement/retainer/milestone billing
                events, and total placement fee). Always included on GET
                /v1/jobs/{id}. On list/search endpoints, included only when
                "fees" is in the include parameter.
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/CustomFieldValue'
          description: >-
            Custom attribute values. Included when include contains
            "custom_fields". Definitions from GET /v1/custom-fields/jobs.
      required:
        - id
        - name
        - created_at
        - is_archived
        - client_company_name
        - client_company_id
        - client_company_domain
        - client_company_linkedin_url
        - job_status_name
        - job_status_id
        - candidate_count
        - location
        - primary_url
        - job_function
        - open_date
        - end_date
        - currency_code
        - salary_range
        - salary_min
        - salary_max
        - salary_details
        - billing_contact_name
        - billing_contact_email
        - fee
        - description
        - team_members
    JobTeamMember:
      type: object
      properties:
        team_member_id:
          type: string
          description: Team member UUID. Matches IDs from GET /v1/team-members.
        email:
          type:
            - string
            - 'null'
          description: Team member email address.
        first_name:
          type:
            - string
            - 'null'
          description: First name.
        last_name:
          type:
            - string
            - 'null'
          description: Last name.
        role_id:
          type:
            - string
            - 'null'
          description: >-
            Job team member role UUID. Get available roles from GET
            /v1/jobs/team-member-roles.
        role_name:
          type:
            - string
            - 'null'
          description: Role display name (e.g. "Team Lead", "Executive Sponsor").
      required:
        - team_member_id
        - email
        - first_name
        - last_name
        - role_id
        - role_name
    LinkedJobDeal:
      type: object
      properties:
        deal_id:
          type: string
          format: uuid
          description: >-
            Deal UUID. Matches IDs from GET /v1/deals/{id} or POST
            /v1/deals/search.
        deal_job_id:
          type: string
          format: uuid
          description: >-
            UUID of the join row in the deal_jobs table linking this job to the
            deal.
        name:
          type: string
          description: Deal name.
        amount:
          type:
            - number
            - 'null'
          description: Deal amount (fee invoiced to the client). Null if unset.
        currency_code:
          type:
            - string
            - 'null'
          description: ISO 4217 currency code for the deal amount (e.g. "USD").
        deal_status_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Current deal status UUID, if any.
        deal_status_name:
          type:
            - string
            - 'null'
          description: Current deal status display name (e.g. "Qualified", "Won", "Lost").
        deal_status_color:
          type:
            - string
            - 'null'
          description: Hex color of the deal status badge (e.g. "#10B981").
      required:
        - deal_id
        - deal_job_id
        - name
        - amount
        - currency_code
        - deal_status_id
        - deal_status_name
        - deal_status_color
    JobFees:
      type: object
      properties:
        retainer:
          allOf:
            - $ref: '#/components/schemas/JobRetainer'
            - type:
                - object
                - 'null'
              description: >-
                Retainer fee structure for this job, or null if the job is not a
                retained engagement.
        fee_events:
          type: array
          items:
            $ref: '#/components/schemas/JobFeeEvent'
          description: >-
            All billing events for this job — placements plus retainer
            installments/milestones. Filter by the "type" field.
        total_placement_fee:
          type:
            - number
            - 'null'
          description: >-
            Sum of total_fee across all non-placeholder, non-cancelled placement
            events. Null when there are no such placements. This reflects the
            fees entered in the "Fees and Placements" section, unlike the
            top-level "fee" field which is a manually entered forecasting value
            on the job.
      required:
        - retainer
        - fee_events
        - total_placement_fee
    CustomFieldValue:
      type: object
      properties:
        attribute_id:
          type: string
          format: uuid
          description: >-
            Attribute definition UUID. Get definitions from GET
            /v1/custom-fields/{entity}.
        attribute_name:
          type: string
          description: Attribute display name.
        data_type:
          type: string
          enum:
            - string
            - integer
            - decimal
            - multi-select
            - single-select
            - boolean
            - date
            - multi-team-member
            - url
          description: Attribute data type. Determines which value field contains the data.
        job_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Job UUID this attribute is scoped to. Null for global person-level
            attributes. Present when this custom field is specific to a job
            (candidate-level field).
        list_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            List UUID this attribute is scoped to. Null for global person-level
            attributes.
        value:
          anyOf:
            - type: string
            - type: number
            - type: boolean
            - type: 'null'
            - type: 'null'
          description: >-
            Scalar value for string, integer, decimal, date, url, boolean types.
            Null for select/team-member types.
        tag:
          type:
            - object
            - 'null'
          properties:
            id:
              type: string
              format: uuid
              description: Tag option UUID.
            name:
              type: string
              description: Tag display name.
          required:
            - id
            - name
          description: >-
            Tag value for single-select and multi-select types. Null for other
            types. For multi-select, one CustomFieldValue row per tag.
        team_member:
          type:
            - object
            - 'null'
          properties:
            id:
              type: string
              format: uuid
              description: Team member UUID.
            name:
              type:
                - string
                - 'null'
              description: Team member full name.
          required:
            - id
            - name
          description: >-
            Team member value for multi-team-member type. Null for other types.
            One CustomFieldValue row per team member.
      required:
        - attribute_id
        - attribute_name
        - data_type
        - job_id
        - list_id
        - value
        - tag
        - team_member
    JobRetainer:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Retainer UUID.
        fee_type:
          type: string
          description: How the projected fee is calculated ("percentage", "fixed").
        fee_base:
          type:
            - string
            - 'null'
          description: Basis the percentage applies to (e.g. "first_year_salary").
        fee_percentage:
          type:
            - number
            - 'null'
          description: Fee percentage used when fee_type is percentage-based.
        projected_fee:
          type: number
          description: Total projected engagement value for the retainer.
        estimated_compensation:
          type:
            - number
            - 'null'
          description: Estimated candidate compensation the fee is based on.
        installment_count:
          type: number
          description: Number of installments the retainer is split into.
        final_payment_type:
          type: string
          description: How the final payment is handled (e.g. "on_placement").
        currency_code:
          type:
            - string
            - 'null'
          description: ISO 4217 currency code for the retainer.
      required:
        - id
        - fee_type
        - fee_base
        - fee_percentage
        - projected_fee
        - estimated_compensation
        - installment_count
        - final_payment_type
        - currency_code
    JobFeeEvent:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Fee event UUID.
        type:
          type: string
          enum:
            - retainer
            - milestone
            - placement
          description: >-
            Fee event type. "placement" is a completed placement fee; "retainer"
            and "milestone" are retained-search billing events.
        label:
          type:
            - string
            - 'null'
          description: Optional label for the fee event.
        amount:
          type:
            - number
            - 'null'
          description: Billable amount for this fee event. Null if unset.
        total_fee:
          type:
            - number
            - 'null'
          description: >-
            Full fee for the event (for placements, the commission base before
            splits). Null if unset.
        currency_code:
          type:
            - string
            - 'null'
          description: >-
            ISO 4217 currency code for the fee amounts (e.g. "USD"). Null if
            unset.
        fee_type:
          type:
            - string
            - 'null'
          description: How the fee is calculated (e.g. "percentage", "fixed").
        fee_percentage:
          type:
            - number
            - 'null'
          description: Fee percentage used when fee_type is percentage-based.
        compensation:
          type:
            - number
            - 'null'
          description: Candidate compensation the fee percentage is applied to.
        firm_commission_percent:
          type:
            - number
            - 'null'
          description: Firm's commission percentage for this event (0–100).
        is_placeholder:
          type: boolean
          description: >-
            True if this is a projected/placeholder event rather than a
            confirmed one.
        sequence:
          type:
            - number
            - 'null'
          description: Ordering position within the fee schedule.
        start_date:
          type:
            - string
            - 'null'
          description: Start date (YYYY-MM-DD), if any.
        expected_date:
          type:
            - string
            - 'null'
          description: Expected billing/payment date (YYYY-MM-DD).
        actual_payment_date:
          type:
            - string
            - 'null'
          description: Actual payment date (YYYY-MM-DD), once paid.
        candidate_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Placed candidate UUID for placement events. Matches IDs from GET
            /v1/candidates/{id}.
        offer_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Associated job offer UUID, if any.
        retainer_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Parent retainer UUID for retainer installment events, if any.
        fee_status_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Fee status UUID, if any.
        fee_status_name:
          type:
            - string
            - 'null'
          description: Fee status display name (e.g. "Invoiced", "Paid").
        fee_status_color:
          type:
            - string
            - 'null'
          description: Hex color of the fee status badge.
        fee_status_type:
          type:
            - string
            - 'null'
          enum:
            - pending
            - invoiced
            - paid
            - cancelled
          description: Underlying fee status category.
      required:
        - id
        - type
        - label
        - amount
        - total_fee
        - currency_code
        - fee_type
        - fee_percentage
        - compensation
        - firm_commission_percent
        - is_placeholder
        - sequence
        - start_date
        - expected_date
        - actual_payment_date
        - candidate_id
        - offer_id
        - retainer_id
        - fee_status_id
        - fee_status_name
        - fee_status_color
        - fee_status_type
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Authenticate with a Bearer token: API key, OAuth token, or session
        token.

````