HollyHR Custom Fields API

Custom field definitions and person custom-field values for provider and partner mappings.

GitHub OpenAPI

Operations 3

GET /custom-fields List API-visible custom-field definitions #
GET /people/{personId}/custom-fields Fetch a person's custom-field values #
PATCH /people/{personId}/custom-fields Update a person's custom-field values #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/hollyhr-com:hollyhr-com-custom-fields-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

hollyhr-com-custom-fields-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: HollyHR API Reference Custom Fields API
  version: 1.0.0-foundation
  description: Governed Public Preview API with organisation-scoped reads and bounded signed-webhook management available on every plan, and governed programmatic writes included on Standard and above through explicitly selected scopes. This version covers API-key context, people directory sync, safe people setup, conditional setup-field updates, safe lifecycle actions, safe employment writes, canonical org-unit reads and person org links, working-pattern reads and writes, safe time-off writes, time-off sync, public holidays, document metadata sync, reference data, and outbound webhook management. Responses use explicit deny-by-default projections and opaque public ids; person ids are stored random tenant-person identifiers while other resource ids remain encrypted. orgId is always resolved from the bearer key and is never accepted from request input.
servers:
- url: /api/v1
  description: Public API path on the current HollyHR app origin.
- url: https://sandbox.hollyhr.com/api/v1
  description: Seeded HollyHR sandbox tenant for hhr_test_ API keys.
security:
- ApiKeyAuth: []
tags:
- name: Custom Fields
  description: Custom field definitions and person custom-field values for provider and partner mappings.
paths:
  /custom-fields:
    get:
      operationId: listCustomFieldDefinitions
      tags:
      - Custom Fields
      summary: List API-visible custom-field definitions
      description: Lists person custom-field definitions explicitly marked API read or API read/write. Definitions hidden from the API are excluded, and the response includes only field metadata and configured options.
      security:
      - ApiKeyAuth: []
      x-required-scope: custom_fields:read
      parameters:
      - schema:
          type: string
          enum:
          - person
          default: person
        required: false
        name: target
        in: query
      responses:
        '200':
          description: API-visible custom-field definitions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomFieldDefinitionList'
        '400':
          description: Invalid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: Missing, malformed, unknown, revoked, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Missing scope or plan entitlement.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limited. Responses include Retry-After and rate-limit metadata where available.
          headers:
            Retry-After:
              schema:
                type: string
              description: Seconds to wait before retrying the request.
            RateLimit-Limit:
              schema:
                type: string
              description: Current route bucket limit.
            RateLimit-Remaining:
              schema:
                type: string
              description: Requests remaining in the current route bucket window.
            RateLimit-Reset:
              schema:
                type: string
              description: Seconds until the current route bucket resets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      x-hollyhr-domain-capabilities:
      - settings.custom-fields.manage
  /people/{personId}/custom-fields:
    get:
      operationId: getPersonCustomFields
      tags:
      - Custom Fields
      summary: Fetch a person's custom-field values
      description: Fetches values for API-visible person custom fields. Missing values are returned as null so integrators can distinguish unset fields from missing definitions.
      security:
      - ApiKeyAuth: []
      x-required-scope: custom_fields:read
      parameters:
      - schema:
          type: string
          pattern: ^[0123456789abcdefghjkmnpqrstvwxyz]{12}$
          description: Stable opaque 12-character tenant-person id.
        required: true
        description: Stable opaque 12-character tenant-person id.
        name: personId
        in: path
      - schema:
          type: string
          description: Optional cache validator. Returns 304 when it matches the current ETag.
        required: false
        description: Optional cache validator. Returns 304 when it matches the current ETag.
        name: If-None-Match
        in: header
      responses:
        '200':
          description: Person custom-field values.
          headers:
            ETag:
              schema:
                type: string
              description: Strong version tag for conditional updates.
            HollyHR-Resource-ETag:
              schema:
                type: string
              description: Strong resource validator for If-Match conditional writes. Unlike the standard ETag cache validator, hosting layers must preserve this value unchanged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonCustomFieldValuesResponse'
        '304':
          description: The supplied If-None-Match value matches the current custom-field values.
          headers:
            ETag:
              schema:
                type: string
              description: Current strong version tag.
            HollyHR-Resource-ETag:
              schema:
                type: string
              description: Strong resource validator for If-Match conditional writes. Unlike the standard ETag cache validator, hosting layers must preserve this value unchanged.
        '400':
          description: Invalid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: Missing, malformed, unknown, revoked, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Missing scope or plan entitlement.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Person not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limited. Responses include Retry-After and rate-limit metadata where available.
          headers:
            Retry-After:
              schema:
                type: string
              description: Seconds to wait before retrying the request.
            RateLimit-Limit:
              schema:
                type: string
              description: Current route bucket limit.
            RateLimit-Remaining:
              schema:
                type: string
              description: Requests remaining in the current route bucket window.
            RateLimit-Reset:
              schema:
                type: string
              description: Seconds until the current route bucket resets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      x-hollyhr-domain-capabilities:
      - people.custom-fields.view
    patch:
      operationId: updatePersonCustomFields
      tags:
      - Custom Fields
      summary: Update a person's custom-field values
      description: Updates values for custom-field definitions explicitly marked API read/write. Requires Idempotency-Key and If-Match headers. Send null or an empty string to clear a value.
      security:
      - ApiKeyAuth: []
      x-required-scope: custom_fields:write
      parameters:
      - schema:
          type: string
          pattern: ^[0123456789abcdefghjkmnpqrstvwxyz]{12}$
          description: Stable opaque 12-character tenant-person id.
        required: true
        description: Stable opaque 12-character tenant-person id.
        name: personId
        in: path
      - schema:
          type: string
          minLength: 8
          maxLength: 255
          pattern: ^[\x20-\x7E]+$
          description: Required for mutation requests. Reuse the same key only when retrying the exact same request.
        required: true
        description: Required for mutation requests. Reuse the same key only when retrying the exact same request.
        name: Idempotency-Key
        in: header
      - schema:
          type: string
          description: Required for conditional updates. Use the exact HollyHR-Resource-ETag returned by the corresponding resource GET endpoint. The standard ETag remains available for HTTP cache validation and may be weakened by a hosting layer.
        required: true
        description: Required for conditional updates. Use the exact HollyHR-Resource-ETag returned by the corresponding resource GET endpoint. The standard ETag remains available for HTTP cache validation and may be weakened by a hosting layer.
        name: If-Match
        in: header
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePersonCustomFieldsRequest'
      responses:
        '200':
          description: Updated person custom-field values.
          headers:
            ETag:
              schema:
                type: string
              description: New strong version tag after the update.
            HollyHR-Resource-ETag:
              schema:
                type: string
              description: Strong resource validator for If-Match conditional writes. Unlike the standard ETag cache validator, hosting layers must preserve this value unchanged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonCustomFieldValuesResponse'
        '400':
          description: Invalid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: Missing, malformed, unknown, revoked, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Missing scope or plan entitlement.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Person not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: Conflict, such as an idempotency mismatch.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '412':
          description: If-Match does not match the current resource version.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '428':
          description: If-Match header is required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limited. Responses include Retry-After and rate-limit metadata where available.
          headers:
            Retry-After:
              schema:
                type: string
              description: Seconds to wait before retrying the request.
            RateLimit-Limit:
              schema:
                type: string
              description: Current route bucket limit.
            RateLimit-Remaining:
              schema:
                type: string
              description: Requests remaining in the current route bucket window.
            RateLimit-Reset:
              schema:
                type: string
              description: Seconds until the current route bucket resets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      x-hollyhr-domain-capabilities:
      - people.custom-fields.update
components:
  schemas:
    CustomFieldDefinitionList:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                pattern: ^cfd_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
              key:
                type: string
                minLength: 2
                maxLength: 64
                pattern: ^[a-z][a-z0-9_]{1,63}$
              label:
                type: string
              description:
                type:
                - string
                - 'null'
              target_resource:
                type: string
                enum:
                - person
              field_type:
                type: string
                enum:
                - text
                - number
                - date
                - boolean
                - single_select
              sensitivity:
                type: string
                enum:
                - operational
                - personal
                - demographic
                - payroll
              api_access:
                type: string
                enum:
                - read
                - read_write
              display_order:
                type: integer
                minimum: 0
              options:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      pattern: ^cfo_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
                    value:
                      type: string
                    label:
                      type: string
                    display_order:
                      type: integer
                      minimum: 0
                  required:
                  - id
                  - value
                  - label
                  - display_order
                  additionalProperties: false
              created_at:
                type: string
                format: date-time
              updated_at:
                type: string
                format: date-time
            required:
            - id
            - key
            - label
            - description
            - target_resource
            - field_type
            - sensitivity
            - api_access
            - display_order
            - options
            - created_at
            - updated_at
            additionalProperties: false
      required:
      - data
      additionalProperties: false
    UpdatePersonCustomFieldsRequest:
      type: object
      properties:
        values:
          type: object
          additionalProperties:
            anyOf:
            - type: string
              maxLength: 4000
            - type: number
            - type: boolean
            - type: 'null'
      required:
      - values
      additionalProperties: false
    ErrorEnvelope:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
              - invalid_request
              - authentication_required
              - permission_denied
              - not_found
              - rate_limited
              - idempotency_required
              - idempotency_conflict
              - conflict
              - precondition_required
              - precondition_failed
              - internal_error
            message:
              type: string
            request_id:
              type: string
              pattern: ^[a-zA-Z0-9._:-]{8,64}$
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  issue:
                    type: string
                required:
                - field
                - issue
                additionalProperties: false
          required:
          - code
          - message
          - request_id
          additionalProperties: false
      required:
      - error
      additionalProperties: false
    PersonCustomFieldValuesResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            person_id:
              type: string
              pattern: ^[0123456789abcdefghjkmnpqrstvwxyz]{12}$
            values:
              type: array
              items:
                type: object
                properties:
                  field_id:
                    type: string
                    pattern: ^cfd_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
                  key:
                    type: string
                    minLength: 2
                    maxLength: 64
                    pattern: ^[a-z][a-z0-9_]{1,63}$
                  label:
                    type: string
                  description:
                    type:
                    - string
                    - 'null'
                  field_type:
                    type: string
                    enum:
                    - text
                    - number
                    - date
                    - boolean
                    - single_select
                  sensitivity:
                    type: string
                    enum:
                    - operational
                    - personal
                    - demographic
                    - payroll
                  value:
                    anyOf:
                    - type: string
                    - type: number
                    - type: boolean
                    - type: 'null'
                  option:
                    type:
                    - object
                    - 'null'
                    properties:
                      id:
                        type: string
                        pattern: ^cfo_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
                      value:
                        type: string
                      label:
                        type: string
                    required:
                    - id
                    - value
                    - label
                    additionalProperties: false
                  updated_at:
                    type:
                    - string
                    - 'null'
                    format: date-time
                required:
                - field_id
                - key
                - label
                - description
                - field_type
                - sensitivity
                - value
                - option
                - updated_at
                additionalProperties: false
          required:
          - person_id
          - values
          additionalProperties: false
      required:
      - data
      additionalProperties: false
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: HollyHR API-key bearer token. Each credential is attached to one stable organisation-bound programmatic principal, so rotation does not change the actor or its audit identity. Effective access remains the intersection of the key scopes, current principal grant, plan entitlement and runtime controls.
x-provenance:
  method: harvested
  publisher: HollyHR
  source: https://developers.hollyhr.com/openapi.v1.yaml
  note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
    stamped by stamp-openapi-provenance.py (roadmap#793)