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: 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)