HollyHR Employers API

The employer register: your own companies and any employer-of-record contracting entities. Dated employer, employment country and payroll handling live on employment and employment history.

GitHub OpenAPI

Operations 4

GET /employers List employers #
POST /employers Add an employer #
GET /employers/{employerId} Fetch one employer #
PATCH /employers/{employerId} Correct or archive an employer #

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-employers-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-employers-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: HollyHR API Reference Employers 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: Employers
  description: 'The employer register: your own companies and any employer-of-record contracting entities. Dated employer, employment country and payroll handling live on employment and employment history.'
paths:
  /employers:
    get:
      operationId: listEmployers
      tags:
      - Employers
      summary: List employers
      description: 'Lists every company in the employer register, including archived ones so dated employment references always resolve. Every workspace has its own company (`is_default`), created automatically. An employer of record (`category: eor`) is the actual local contracting entity; `provider_brand` alone is never the employer. Contains no people, payroll account, tax, bank or salary data; an employer read never lists employees.'
      security:
      - ApiKeyAuth: []
      x-required-scope: employers:read
      responses:
        '200':
          description: The employer register.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployerList'
        '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:
      - organisation.employers.view
    post:
      operationId: createEmployer
      tags:
      - Employers
      summary: Add an employer
      description: 'Adds another of your companies or an EOR''s local contracting entity. Requires an Idempotency-Key header. Adding a company assigns nobody: people''s employers change only through dated employment writes, which need confirmed employer setup.'
      security:
      - ApiKeyAuth: []
      x-required-scope: employers:write
      parameters:
      - 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
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEmployerRequest'
      responses:
        '201':
          description: The created employer.
          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/EmployerResponse'
        '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'
        '409':
          description: Conflict, such as additional employers not yet available for this workspace or an idempotency mismatch.
          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:
      - organisation.employers.manage
  /employers/{employerId}:
    get:
      operationId: getEmployer
      tags:
      - Employers
      summary: Fetch one employer
      description: Fetches one employer, including archived ones. Cross-tenant, malformed or wrong-resource ids return 404.
      security:
      - ApiKeyAuth: []
      x-required-scope: employers:read
      parameters:
      - schema:
          type: string
          maxLength: 1024
          pattern: ^employer_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
          description: Opaque tenant-bound employer id.
        required: true
        description: Opaque tenant-bound employer id.
        name: employerId
        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: An employer.
          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/EmployerResponse'
        '304':
          description: The supplied If-None-Match value matches the current employer version.
        '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: Employer 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:
      - organisation.employers.view
    patch:
      operationId: updateEmployer
      tags:
      - Employers
      summary: Correct or archive an employer
      description: Corrects employer details or archives a company. Requires Idempotency-Key and If-Match headers. Category never changes (record a new company instead), your own default company cannot be archived, and once employer setup is confirmed a `correction_reason` is required. Old and new details are audited.
      security:
      - ApiKeyAuth: []
      x-required-scope: employers:write
      parameters:
      - schema:
          type: string
          maxLength: 1024
          pattern: ^employer_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
          description: Opaque tenant-bound employer id.
        required: true
        description: Opaque tenant-bound employer id.
        name: employerId
        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/UpdateEmployerRequest'
      responses:
        '200':
          description: The updated employer.
          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/EmployerResponse'
        '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: Employer not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: Conflict, such as a category change or archiving your own company.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '412':
          description: If-Match does not match the current employer version.
          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:
      - organisation.employers.manage
components:
  schemas:
    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
    CreateEmployerRequest:
      type: object
      properties:
        legal_name:
          type: string
          minLength: 1
          maxLength: 255
        display_name:
          type: string
          minLength: 1
          maxLength: 255
        registration_country_code:
          type:
          - string
          - 'null'
          pattern: ^[A-Z]{2}$
        registration_number:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 128
        provider_brand:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 128
        category:
          type: string
          enum:
          - own
          - eor
      required:
      - legal_name
      - display_name
      - category
      additionalProperties: false
    EmployerResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              maxLength: 1024
              pattern: ^employer_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
            legal_name:
              type: string
              description: The company name on the employment contract.
            display_name:
              type: string
            category:
              type: string
              enum:
              - own
              - eor
              description: 'own: one of your companies. eor: an external employer of record. Never changes.'
            is_default:
              type: boolean
              description: Your workspace's own company, created automatically from organisation details.
            registration_country_code:
              type:
              - string
              - 'null'
              pattern: ^[A-Z]{2}$
            registration_number:
              type:
              - string
              - 'null'
            provider_brand:
              type:
              - string
              - 'null'
              description: For an EOR, the provider brand (for example Remote). Not the legal employer.
            is_archived:
              type: boolean
            archived_at:
              type:
              - string
              - 'null'
              format: date-time
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
          required:
          - id
          - legal_name
          - display_name
          - category
          - is_default
          - registration_country_code
          - registration_number
          - provider_brand
          - is_archived
          - archived_at
          - created_at
          - updated_at
          additionalProperties: false
      required:
      - data
      additionalProperties: false
    EmployerList:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                maxLength: 1024
                pattern: ^employer_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
              legal_name:
                type: string
                description: The company name on the employment contract.
              display_name:
                type: string
              category:
                type: string
                enum:
                - own
                - eor
                description: 'own: one of your companies. eor: an external employer of record. Never changes.'
              is_default:
                type: boolean
                description: Your workspace's own company, created automatically from organisation details.
              registration_country_code:
                type:
                - string
                - 'null'
                pattern: ^[A-Z]{2}$
              registration_number:
                type:
                - string
                - 'null'
              provider_brand:
                type:
                - string
                - 'null'
                description: For an EOR, the provider brand (for example Remote). Not the legal employer.
              is_archived:
                type: boolean
              archived_at:
                type:
                - string
                - 'null'
                format: date-time
              created_at:
                type: string
                format: date-time
              updated_at:
                type: string
                format: date-time
            required:
            - id
            - legal_name
            - display_name
            - category
            - is_default
            - registration_country_code
            - registration_number
            - provider_brand
            - is_archived
            - archived_at
            - created_at
            - updated_at
            additionalProperties: false
      required:
      - data
      additionalProperties: false
    UpdateEmployerRequest:
      type: object
      properties:
        legal_name:
          type: string
          minLength: 1
          maxLength: 255
        display_name:
          type: string
          minLength: 1
          maxLength: 255
        registration_country_code:
          type:
          - string
          - 'null'
          pattern: ^[A-Z]{2}$
        registration_number:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 128
        provider_brand:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 128
        is_archived:
          type: boolean
        correction_reason:
          type: string
          minLength: 1
          maxLength: 255
          description: Required once employer setup is confirmed. Recorded in the audit log.
      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)