> ## 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.

# Create a retainer pack

> Creates a pack of `retainer_count` open retainers of `amount_each` for a client company, all on one invoice. Amounts are per retainer. Every retainer shares the pack status, invoice date and currency.

Returns the full pack with its retainers, claims, splits, extra hires, adjustments and summary.

**Access**: Session and OAuth callers need permission to edit CRM records (`org:crm:edit`; `org:admin` always can). API keys need the `fees:write` scope.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /v1/retainer-packs
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.
  - name: Campaigns
    description: >-
      Create and edit email campaigns, enroll people through enrollment batches,
      and manage who is enrolled.
paths:
  /v1/retainer-packs:
    post:
      tags:
        - Retainer Packs
      summary: Create a retainer pack
      description: >-
        Creates a pack of `retainer_count` open retainers of `amount_each` for a
        client company, all on one invoice. Amounts are per retainer. Every
        retainer shares the pack status, invoice date and currency.


        Returns the full pack with its retainers, claims, splits, extra hires,
        adjustments and summary.


        **Access**: Session and OAuth callers need permission to edit CRM
        records (`org:crm:edit`; `org:admin` always can). API keys need the
        `fees:write` scope.
      operationId: createRetainerPack
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRetainerPackBody'
      responses:
        '201':
          description: Retainer pack created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RetainerPackResponse'
              example:
                success: true
                data:
                  id: 0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d
                  organization_company_id: 2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e
                  organization_company_name: Acme Corp
                  name: Q4 2026 GTM pack
                  currency_code: USD
                  invoice_number: INV-1042
                  link_extra_hires: true
                  firm_commission_percent: 10
                  is_closed: false
                  closed_at: null
                  fee_status:
                    id: 5e6f7a8b-9c0d-4e1f-8a3b-4c5d6e7f8a9b
                    name: Paid
                    status_type: paid
                    color: '#22c55e'
                  expected_date: '2026-10-01'
                  actual_payment_date: '2026-10-15'
                  amount_each: 12000
                  default_split:
                    - team_member_id: 6f7a8b9c-0d1e-4f2a-9b4c-5d6e7f8a9b0c
                      team_member_name: Theo Grant
                      role: Sales
                      split_percentage: 70
                    - team_member_id: 7a8b9c0d-1e2f-4a3b-8c5d-6e7f8a9b0c1d
                      team_member_name: Ana Ruiz
                      role: null
                      split_percentage: 30
                  retainers:
                    - id: 1b2c3d4e-5f6a-4b7c-9d8e-0f1a2b3c4d5e
                      position: 1
                      amount: 12000
                      firm_commission_percent: 10
                      claim:
                        is_restricted: false
                        placement_fee_event_id: 9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f
                        job_id: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
                        job_title: VP of Engineering
                        candidate_id: 3c4d5e6f-7a8b-4c9d-8e1f-2a3b4c5d6e7f
                        person_id: 4d5e6f7a-8b9c-4d0e-9f2a-3b4c5d6e7f8a
                        person_name: Jordan Lee
                        start_date: '2026-11-03'
                      splits:
                        - team_member_id: 7a8b9c0d-1e2f-4a3b-8c5d-6e7f8a9b0c1d
                          team_member_name: Ana Ruiz
                          role: Recruiter
                          split_percentage: 60
                          split_amount: 6480
                        - team_member_id: 6f7a8b9c-0d1e-4f2a-9b4c-5d6e7f8a9b0c
                          team_member_name: Theo Grant
                          role: Sales
                          split_percentage: 40
                          split_amount: 4320
                    - id: 2c3d4e5f-6a7b-4c8d-8e9f-1a2b3c4d5e6f
                      position: 2
                      amount: 12000
                      firm_commission_percent: 10
                      claim:
                        is_restricted: true
                        placement_fee_event_id: 0d1e2f3a-4b5c-4d6e-9f7a-8b9c0d1e2f3a
                      splits:
                        - team_member_id: 6f7a8b9c-0d1e-4f2a-9b4c-5d6e7f8a9b0c
                          team_member_name: Theo Grant
                          role: Sales
                          split_percentage: 70
                          split_amount: 7560
                        - team_member_id: 7a8b9c0d-1e2f-4a3b-8c5d-6e7f8a9b0c1d
                          team_member_name: Ana Ruiz
                          role: null
                          split_percentage: 30
                          split_amount: 3240
                    - id: 3d4e5f6a-7b8c-4d9e-8f0a-2b3c4d5e6f7a
                      position: 3
                      amount: 12000
                      firm_commission_percent: 10
                      claim: null
                      splits:
                        - team_member_id: 6f7a8b9c-0d1e-4f2a-9b4c-5d6e7f8a9b0c
                          team_member_name: Theo Grant
                          role: Sales
                          split_percentage: 70
                          split_amount: 7560
                        - team_member_id: 7a8b9c0d-1e2f-4a3b-8c5d-6e7f8a9b0c1d
                          team_member_name: Ana Ruiz
                          role: null
                          split_percentage: 30
                          split_amount: 3240
                  extra_hires: []
                  adjustments: []
                  summary:
                    retainer_count: 3
                    claimed_count: 2
                    open_count: 1
                    extra_hire_count: 0
                    total_amount: 36000
                    remaining_amount: 12000
                    adjustments_total: 0
                    net_retained: 36000
                  created_at: '2026-09-28T09:12:44.000Z'
                  updated_at: '2026-10-15T16:03:10.000Z'
        '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.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '403':
          description: You do not have permission to make this change
          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.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '404':
          description: Company 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.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '422':
          description: >-
            The company is not a client, more than 100 retainers, splits not
            totalling 100%, or an unknown fee status or team member
          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.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    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.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
components:
  schemas:
    CreateRetainerPackBody:
      type: object
      properties:
        organization_company_id:
          type: string
          format: uuid
          description: >-
            Client company the pack is sold to. The company must be marked as a
            client.
        name:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            Pack name shown on the company page, 1 to 200 characters (e.g. "Q4
            2026 GTM pack").
        currency_code:
          type: string
          minLength: 3
          maxLength: 3
          description: >-
            ISO 4217 currency code of every retainer in the pack (e.g. USD).
            Can't change once a retainer is claimed.
        invoice_number:
          type:
            - string
            - 'null'
          description: >-
            Invoice number for the whole pack (one invoice per pack), at most
            100 characters. Send null on update to clear it.
        fee_status_id:
          type: string
          format: uuid
          description: >-
            Status of the pack invoice, shared by every retainer in the pack.
            Get IDs from GET /v1/fee-statuses. Only admins can move a paid pack
            back to an unpaid status.
        expected_date:
          type:
            - string
            - 'null'
          format: date
          description: >-
            Invoice date (YYYY-MM-DD), shared by every retainer in the pack.
            Send null on update to clear it.
        link_extra_hires:
          type: boolean
          description: >-
            When every paid retainer is claimed, new hires at this client still
            link to the pack with a 0 retainer and are billed the full fee.
            Defaults to true.
        firm_commission_percent:
          type: number
          description: >-
            Percent of each open retainer the firm keeps before team credit is
            split, 0 to 100. Defaults to 0.
        retainer_count:
          type: integer
          minimum: 1
          maximum: 100
          description: >-
            Number of retainers in the pack, 1 to 100. To top up an existing
            pack, send add_retainers instead. Lowering it removes open retainers
            from the end and can't go below the claimed retainers.
        amount_each:
          type: number
          description: >-
            Amount of each retainer, 0 or more. A change applies to open
            retainers; claimed retainers keep their amount.
        default_split:
          type: array
          items:
            type: object
            properties:
              team_member_id:
                type: string
                format: uuid
                description: Team member to credit. Get IDs from GET /v1/team-members.
              role:
                type:
                  - string
                  - 'null'
                description: Optional label for why this person is credited (e.g. "Sales").
              split_percentage:
                type: number
                exclusiveMinimum: 0
                maximum: 100
                description: Share of the retainer credit, above 0 and at most 100.
            required:
              - team_member_id
              - split_percentage
          description: >-
            Who gets credit for each retainer. Send an empty list for no split,
            otherwise the percentages must total 100. Credit per retainer is the
            retainer amount minus the firm commission, times each person's
            percentage. Applies to open retainers; a claimed retainer keeps the
            split it was claimed with. Only admins can change the split of a
            paid pack. Defaults to an empty list.
      required:
        - organization_company_id
        - name
        - currency_code
        - fee_status_id
        - retainer_count
        - amount_each
    RetainerPackResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: '#/components/schemas/RetainerPack'
      required:
        - success
        - data
    RetainerPack:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Retainer pack UUID.
        organization_company_id:
          type: string
          format: uuid
          description: Client company the pack belongs to.
        organization_company_name:
          type:
            - string
            - 'null'
          description: Client company name.
        name:
          type: string
          description: Pack name.
        currency_code:
          type: string
          description: ISO 4217 currency code.
        invoice_number:
          type:
            - string
            - 'null'
          description: Invoice number of the pack.
        link_extra_hires:
          type: boolean
          description: >-
            Whether hires after the last claimed retainer still link to the pack
            at 0.
        firm_commission_percent:
          type: number
          description: Percent of each open retainer the firm keeps.
        is_closed:
          type: boolean
          description: Closed packs are no longer offered when logging placements.
        closed_at:
          type:
            - string
            - 'null'
          description: ISO 8601 time the pack was closed.
        fee_status:
          type: object
          properties:
            id:
              type: string
              format: uuid
              description: Fee status UUID.
            name:
              type: string
              description: Status name (e.g. "Paid").
            status_type:
              type: string
              enum:
                - pending
                - invoiced
                - paid
                - cancelled
              description: >-
                Lifecycle category of the status: `pending`, `invoiced`, `paid`
                or `cancelled`. Revenue reports count `paid` fees as collected.
            color:
              type: string
              description: Hex color code of the status badge.
          required:
            - id
            - name
            - status_type
            - color
          description: Status of the pack invoice, shared by every retainer.
        expected_date:
          type:
            - string
            - 'null'
          format: date
          description: Invoice date.
        actual_payment_date:
          type:
            - string
            - 'null'
          format: date
          description: Date the pack was marked paid.
        amount_each:
          type: number
          description: >-
            Amount of each open retainer (the pack's current per-retainer
            amount).
        default_split:
          type: array
          items:
            type: object
            properties:
              team_member_id:
                type: string
                format: uuid
                description: Credited team member UUID.
              team_member_name:
                type:
                  - string
                  - 'null'
                description: Team member full name.
              role:
                type:
                  - string
                  - 'null'
                description: Why this person is credited, if set.
              split_percentage:
                type: number
                description: Share of the credit in percent.
            required:
              - team_member_id
              - team_member_name
              - role
              - split_percentage
          description: The pack's retainer split, used by its open retainers.
        retainers:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
                description: Retainer UUID.
              position:
                type: number
                description: '1-based position for display (#1, #2, ...).'
              amount:
                type: number
                description: Retainer amount in the pack currency.
              firm_commission_percent:
                type: number
                description: Percent of this retainer the firm keeps.
              claim:
                oneOf:
                  - type: object
                    properties:
                      is_restricted:
                        type: boolean
                        enum:
                          - false
                        description: The placement is visible to you.
                      placement_fee_event_id:
                        type: string
                        format: uuid
                        description: Placement UUID.
                      job_id:
                        type: string
                        format: uuid
                        description: Job the placement was logged on.
                      job_title:
                        type: string
                        description: Job title.
                      candidate_id:
                        type:
                          - string
                          - 'null'
                        format: uuid
                        description: Candidate record (the person on that job).
                      person_id:
                        type:
                          - string
                          - 'null'
                        format: uuid
                        description: Placed person UUID.
                      person_name:
                        type:
                          - string
                          - 'null'
                        description: Placed person name.
                      start_date:
                        type:
                          - string
                          - 'null'
                        format: date
                        description: Placement start date.
                    required:
                      - is_restricted
                      - placement_fee_event_id
                      - job_id
                      - job_title
                      - candidate_id
                      - person_id
                      - person_name
                      - start_date
                  - type: object
                    properties:
                      is_restricted:
                        type: boolean
                        enum:
                          - true
                        description: >-
                          The placement is on a confidential job you cannot see;
                          only its ID is returned.
                      placement_fee_event_id:
                        type: string
                        format: uuid
                        description: Placement UUID.
                    required:
                      - is_restricted
                      - placement_fee_event_id
                  - type: 'null'
                description: >-
                  The placement that used this retainer, or null while it is
                  open.
              splits:
                type: array
                items:
                  type: object
                  properties:
                    team_member_id:
                      type: string
                      format: uuid
                      description: Credited team member UUID.
                    team_member_name:
                      type:
                        - string
                        - 'null'
                      description: Team member full name.
                    role:
                      type:
                        - string
                        - 'null'
                      description: Why this person is credited, if set.
                    split_percentage:
                      type: number
                      description: Share of the credit in percent.
                    split_amount:
                      type: number
                      description: >-
                        This person's credit for the retainer, after the firm
                        commission.
                  required:
                    - team_member_id
                    - team_member_name
                    - role
                    - split_percentage
                    - split_amount
                description: >-
                  Credit for this retainer. Open retainers follow the pack's
                  split; claimed ones keep the split they were claimed with.
            required:
              - id
              - position
              - amount
              - firm_commission_percent
              - claim
              - splits
          description: Every retainer in the pack, in order.
        extra_hires:
          type: array
          items:
            type: object
            properties:
              placement_fee_event_id:
                type: string
                format: uuid
                description: Placement UUID.
              job_id:
                type: string
                format: uuid
                description: Job the placement was logged on.
              job_title:
                type: string
                description: Job title.
              candidate_id:
                type:
                  - string
                  - 'null'
                format: uuid
                description: Candidate record (the person on that job).
              person_id:
                type:
                  - string
                  - 'null'
                format: uuid
                description: Placed person UUID.
              person_name:
                type:
                  - string
                  - 'null'
                description: Placed person name.
              start_date:
                type:
                  - string
                  - 'null'
                format: date
                description: Placement start date.
            required:
              - placement_fee_event_id
              - job_id
              - job_title
              - candidate_id
              - person_id
              - person_name
              - start_date
            description: >-
              A placement linked to the pack after every paid retainer was
              claimed, at a 0 retainer and billed the full fee.
          description: Placements linked to the pack at a 0 retainer.
        adjustments:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
                description: Adjustment UUID.
              amount:
                type: number
                description: Money returned, stored positive.
              comment:
                type:
                  - string
                  - 'null'
                description: Note on the adjustment.
              adjusted_on:
                type: string
                format: date
                description: Date of the adjustment.
              created_at:
                type: string
                description: ISO 8601 creation timestamp.
            required:
              - id
              - amount
              - comment
              - adjusted_on
              - created_at
          description: Refunds and other money returned on the pack, oldest first.
        summary:
          type: object
          properties:
            retainer_count:
              type: number
              description: Number of retainers in the pack.
            claimed_count:
              type: number
              description: Retainers used by a placement.
            open_count:
              type: number
              description: Retainers not used yet.
            extra_hire_count:
              type: number
              description: Placements linked after every retainer was claimed.
            total_amount:
              type: number
              description: Sum of every retainer amount.
            remaining_amount:
              type: number
              description: Sum of the open retainer amounts.
            adjustments_total:
              type: number
              description: Sum of the adjustments.
            net_retained:
              type: number
              description: Total amount minus adjustments.
          required:
            - retainer_count
            - claimed_count
            - open_count
            - extra_hire_count
            - total_amount
            - remaining_amount
            - adjustments_total
            - net_retained
        created_at:
          type: string
          description: ISO 8601 creation timestamp.
        updated_at:
          type: string
          description: ISO 8601 last update timestamp.
      required:
        - id
        - organization_company_id
        - organization_company_name
        - name
        - currency_code
        - invoice_number
        - link_extra_hires
        - firm_commission_percent
        - is_closed
        - closed_at
        - fee_status
        - expected_date
        - actual_payment_date
        - amount_each
        - default_split
        - retainers
        - extra_hires
        - adjustments
        - summary
        - created_at
        - updated_at
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Authenticate with a Bearer token: API key, OAuth token, or session
        token.

````

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