FactorialHR (factorial_hr v0.2.0)

Copy Markdown View Source

Generic Elixir client for the public Factorial HR REST API.

This package intentionally stays below any product/domain mapping layer. It knows how to authenticate, build versioned resource URLs, follow Factorial's cursor pagination and call common HR endpoints, returning Factorial payloads as maps.

Quick start

opts = [
  api_key: System.fetch_env!("FACTORIAL_API_KEY"),
  api_version: "2026-04-01"
]

{:ok, employees} = FactorialHR.list_employees([only_active: true], opts)

The client also accepts bearer access tokens for applications that implement their own OAuth flow.

Telemetry

When :telemetry is available, requests emit:

  • [:factorial_hr, :request, :start]
  • [:factorial_hr, :request, :stop]
  • [:factorial_hr, :request, :exception]

Request metadata includes the HTTP method, resource path and resolved URL.

Summary

Functions

Fetches every page from a cursor-paginated Factorial collection.

Creates several shifts in Factorial shift management.

Creates one shift in Factorial shift management.

Executes a DELETE request against a versioned Factorial resource path.

Deletes one shift by Factorial shift-management ID.

Executes a GET request against a versioned Factorial resource path.

Lists Factorial attendance shifts for a date range.

Lists Factorial contract compensations.

Lists Factorial contract versions.

Lists Factorial employees.

Lists Factorial workplace locations.

Lists Factorial shift-management shifts.

Lists unique employee IDs from the Factorial teams endpoint.

Lists Factorial teams.

Lists Factorial work areas.

Executes a POST request against a versioned Factorial resource path.

Types

client_opts()

@type client_opts() :: keyword() | map() | FactorialHR.Config.t()

params()

@type params() :: keyword() | map()

response_result()

@type response_result() :: {:ok, Req.Response.t()} | {:error, FactorialHR.Error.t()}

result()

@type result() :: {:ok, term()} | {:error, FactorialHR.Error.t()}

Functions

all(path, params \\ [], collection_name \\ nil, opts \\ [])

@spec all(String.t(), params(), String.t() | nil, client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Fetches every page from a cursor-paginated Factorial collection.

bulk_create_shifts(shifts, opts \\ [])

@spec bulk_create_shifts([map()], client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Creates several shifts in Factorial shift management.

bulk_delete_shifts(ids_or_params, opts \\ [])

@spec bulk_delete_shifts([integer()] | params(), client_opts()) ::
  :ok | {:error, FactorialHR.Error.t()}

Bulk-deletes shifts.

Pass a list of IDs or a map/keyword list matching Factorial's bulk delete filters. author_id is read from params first, then from client config. Empty ID lists are rejected before making an API request.

create_shift(params, opts \\ [])

@spec create_shift(map(), client_opts()) ::
  {:ok, map()} | {:error, FactorialHR.Error.t()}

Creates one shift in Factorial shift management.

company_id can be passed per shift or configured once in the client opts.

FactorialHR.create_shift(
  %{
    employee_id: 42,
    start_at: "2026-06-01T08:00:00Z",
    end_at: "2026-06-01T16:00:00Z",
    location_id: 7,
    work_area_id: 8
  },
  Keyword.put(opts, :company_id, 123)
)

delete(path, opts \\ [])

@spec delete(String.t(), client_opts()) :: response_result()

Executes a DELETE request against a versioned Factorial resource path.

delete_shift(shift_id, opts \\ [])

@spec delete_shift(integer() | String.t(), client_opts()) ::
  :ok | {:error, FactorialHR.Error.t()}

Deletes one shift by Factorial shift-management ID.

A 404 is treated as success to make delete operations idempotent.

get(path, params \\ [], opts \\ [])

@spec get(String.t(), params(), client_opts()) :: response_result()

Executes a GET request against a versioned Factorial resource path.

Pass a resource path such as "/employees/employees". The client adds the /api/:version/resources prefix from the configured API version.

Returns the raw %Req.Response{} for successful 2xx responses and a structured %FactorialHR.Error{} for non-2xx HTTP responses or request failures.

list_attendance_shifts(start_on, end_on, params \\ [], opts \\ [])

@spec list_attendance_shifts(
  Date.t() | String.t(),
  Date.t() | String.t(),
  params(),
  client_opts()
) :: {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial attendance shifts for a date range.

list_compensations(params \\ [], opts \\ [])

@spec list_compensations(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial contract compensations.

list_contract_versions(params \\ [], opts \\ [])

@spec list_contract_versions(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial contract versions.

list_employees(params \\ [], opts \\ [])

@spec list_employees(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial employees.

list_locations(params \\ [], opts \\ [])

@spec list_locations(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial workplace locations.

list_shifts(params \\ [], opts \\ [])

@spec list_shifts(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial shift-management shifts.

Recognized convenience params include :employee_ids, :location_ids, :start_at, :end_at, :only_published, :only_states and :split_overnight_shifts. Other params are passed through unchanged.

FactorialHR.list_shifts(
  [
    employee_ids: [123, 456],
    start_at: "2026-06-01",
    end_at: "2026-06-30",
    only_states: ["published"]
  ],
  opts
)

list_team_employee_ids(opts \\ [])

@spec list_team_employee_ids(client_opts()) ::
  {:ok, [integer()]} | {:error, FactorialHR.Error.t()}

Lists unique employee IDs from the Factorial teams endpoint.

Factorial team payloads can expose employee_ids or expanded employees. This helper is generic and performs no tenant-specific filtering.

list_teams(params \\ [], opts \\ [])

@spec list_teams(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial teams.

list_work_areas(params \\ [], opts \\ [])

@spec list_work_areas(params(), client_opts()) ::
  {:ok, [map()]} | {:error, FactorialHR.Error.t()}

Lists Factorial work areas.

post(path, body, opts \\ [])

@spec post(String.t(), map(), client_opts()) :: response_result()

Executes a POST request against a versioned Factorial resource path.