Developer API

Build on BimHR Solutions

Authenticate with API keys, list and create employees, submit leave requests, and receive signed webhook events for payroll, leave, and onboarding workflows.

Authentication

All v1 API requests must include an Authorization: Bearer header with a valid BIMHR API key. Keys are issued by the company owner from Settings → API Keys and have the prefix bimhr_live_.

The full key is shown to the owner exactly once at creation time. Only the SHA-256 hash is stored — if you lose the key, you must revoke and reissue it.

The key's company_id becomes the implicit tenant scope for every request. A key issued for company A can neverread or write company B's data, even if the request URL is identical.

Authorization: Bearer bimhr_live_<your_key>

Scopes

Each API key has a set of scopes that determine which endpoints it can access. An empty scopes array means all scopes — useful for first-party integration keys. Recognized scopes:

  • employees:read
  • employees:write
  • leave:read
  • leave:write
  • payroll:read
  • payroll:write
  • webhooks:read

Endpoints

Employees

List, create, fetch, and update employee records. The API key's company_id becomes the implicit tenant scope — a key issued for company A can NEVER read or write company B's employees.

GET/api/v1/employeesemployees:read

List employees for the API key's company (up to 200, newest first).

POST/api/v1/employeesemployees:write

Create a new employee record (lightweight — no auth invite or compensation profile).

GET/api/v1/employees/{id}employees:read

Fetch a single employee by id. Returns 404 if the employee is in a different company.

PATCH/api/v1/employees/{id}employees:write

Update fields on an employee (first_name, last_name, email, job_title, etc.).

Leave

List leave requests and submit new ones on behalf of an employee. New requests are created with status='pending' so they flow through your normal approval chain.

GET/api/v1/leaveleave:read

List leave requests. Filter with ?employee_id= and/or ?status=.

POST/api/v1/leaveleave:write

Submit a new leave request on behalf of an employee.

Payroll

List payroll runs (metadata only — never individual payslip lines). Use the in-app UI to drill into a specific run.

GET/api/v1/payrollpayroll:read

List payroll runs. Filter with ?status=, paginate with ?limit= (max 200).

Webhooks

List webhook delivery history for the API key's company. Useful for integration monitoring.

GET/api/v1/webhookswebhooks:read

List webhook deliveries. Filter with ?endpoint_id=, ?status=, ?limit=.

Webhooks

When an event happens inside BIMHR (leave approved, payroll completed, employee onboarded, etc.), BIMHR fires an HTTP POST to each registered webhook endpoint. Register endpoints from Settings → Webhooks.

Event types

An endpoint with an empty events array subscribes to ALL event types.

employee.created

Fired when a new employee is onboarded.

employee.terminated

Fired when an employee is marked terminated.

leave.requested

Fired when an employee submits a leave request.

leave.approved

Fired when a leave request is approved.

leave.rejected

Fired when a leave request is rejected.

timesheet.submitted

Fired when an employee submits a timesheet.

timesheet.approved

Fired when a timesheet is approved.

payroll.completed

Fired when a payroll run finishes generating payslips.

payroll.approved

Fired when a payroll run is approved/finalised.

advance.requested

Fired when an employee requests an advance.

advance.approved

Fired when an advance request is approved.

document.uploaded

Fired when a document is uploaded for an employee.

contract.signed

Fired when a contract is fully signed by both parties.

onboarding.completed

Fired when an employee's onboarding checklist is complete.

Payload reference

The POST body is a JSON object with the following shape:

{
  "event": "leave.approved",
  "delivered_at": "2026-07-28T12:34:56.789Z",
  "delivery_id": "uuid",
  "payload": {
    "requestId": "uuid",
    "employeeId": "uuid"
  }
}

Verifying the signature

Every POST includes an X-Webhook-Signatureheader containing the hex-encoded HMAC-SHA256 of the raw request body, keyed by the endpoint's secret. Verify it before processing:

import { createHmac } from "crypto";

// Read raw body BEFORE any JSON parsing.
const rawBody = await request.text(); // or: request.body in Python
const signature = request.headers.get("X-Webhook-Signature");

const expected = createHmac("sha256", WEBHOOK_SECRET)
  .update(rawBody, "utf8")
  .digest("hex");

if (signature !== expected) {
  return new Response("Invalid signature", { status: 401 });
}

// Signature is valid — safe to parse + act on the payload.
const event = JSON.parse(rawBody);
console.log(event.event, event.payload);

Retry policy

Failed deliveries are retried up to 5 times with exponential backoff (1s, 2s, 4s, 8s, 16s). After all attempts fail, the delivery is marked failed and the owner can manually retry it from the Webhooks settings tab.

Rate limits

API requests are rate-limited per IP at 60 requests per minute. When the limit is exceeded, the API responds with HTTP 429 and aRetry-Afterheader indicating when to retry.

For higher limits (batch imports, real-time integrations), contact support to discuss a dedicated rate-limit tier.

Code examples

A minimal example: list the employees for the API key's company.

curl

curl -X GET https://your-bimhr-domain.com/api/v1/employees \
  -H "Authorization: Bearer bimhr_live_<your_key>" \
  -H "Accept: application/json"

javascript

const res = await fetch("https://your-bimhr-domain.com/api/v1/employees", {
  method: "GET",
  headers: {
    "Authorization": "Bearer bimhr_live_<your_key>",
    "Accept": "application/json",
  },
});
const data = await res.json();
console.log(data.employees);

python

import requests

res = requests.get(
    "https://your-bimhr-domain.com/api/v1/employees",
    headers={
        "Authorization": "Bearer bimhr_live_<your_key>",
        "Accept": "application/json",
    },
)
print(res.json()["employees"])

Ready to integrate?

Sign in as the company owner, head to Settings → API Keys, and issue your first key.

Go to Settings →