staffora
Home Features About Architecture Docs API Contact GitHub
REST API Documentation

API Reference

Complete REST API documentation. All endpoints are under /api/v1/ and require authentication unless noted. Swagger UI available at /docs in development mode.

Cursor-based pagination on all collections
Idempotency-Key header on all mutations
6
Core API Groups
REST
JSON API
v1
API Version
2
Auth Methods
Filter:
GET/health

Full health check (DB + Redis status, uptime, version)

Auth: None

GET/ready

Kubernetes readiness probe

Auth: None

GET/live

Kubernetes liveness probe

Auth: None

GET/

API root info (name, version, links)

Auth: None

GET/docs

Swagger UI (dev only)

Auth: None

GET/metrics

Prometheus metrics

Auth: None

GET/api/v1/auth/me

Current user with session and tenant info

Auth: Required

GET/api/v1/auth/tenants

List user's accessible tenants

Auth: Required

POST/api/v1/auth/switch-tenant

Switch active tenant context

Auth: Required

GET/api/v1/auth/mfa/backup-codes/status

MFA backup code count

Auth: Required

POST/api/v1/auth/mfa/backup-codes/regenerate

Regenerate 10 MFA backup codes

Auth: Required

Note: Better Auth handles standard auth routes (sign-in, sign-up, sign-out, MFA setup, password reset) at /api/auth/*

GET/api/v1/hr/stats

Dashboard statistics

employees:read

GET/api/v1/hr/org-units

List org units (paginated)

org:read

GET/api/v1/hr/org-units/hierarchy

Full org unit tree

org:read

GET/api/v1/hr/org-units/:id

Get org unit

org:read

POST/api/v1/hr/org-units

Create org unit

org:write

PUT/api/v1/hr/org-units/:id

Update org unit

org:write

DELETE/api/v1/hr/org-units/:id

Soft-delete org unit

org:write

GET/api/v1/hr/positions

List positions

positions:read

GET/api/v1/hr/positions/:id

Get position

positions:read

POST/api/v1/hr/positions

Create position

positions:write

PUT/api/v1/hr/positions/:id

Update position

positions:write

DELETE/api/v1/hr/positions/:id

Delete position

positions:write

GET/api/v1/hr/employees

List employees (paginated)

employees:read

GET/api/v1/hr/employees/by-number/:num

Get by employee number

employees:read

GET/api/v1/hr/employees/:id

Get employee

employees:read

POST/api/v1/hr/employees

Hire employee

employees:write

PUT/api/v1/hr/employees/:id/personal

Update personal info

employees:write

PUT/api/v1/hr/employees/:id/contract

Update contract

employees:write

PUT/api/v1/hr/employees/:id/position

Transfer/promote

employees:write

PUT/api/v1/hr/employees/:id/compensation

Change compensation

compensation:write

PUT/api/v1/hr/employees/:id/manager

Change manager

employees:write

POST/api/v1/hr/employees/:id/status

Status transition

employees:write

POST/api/v1/hr/employees/:id/terminate

Terminate employee

employees:delete

POST/api/v1/hr/employees/:id/rehire

Rehire terminated employee

employees:write

PATCH/api/v1/hr/employees/:id/ni-category

Update NI category

employees:write

GET/api/v1/hr/employees/:id/history/:dimension

Effective-dated history

employees:read

GET/api/v1/hr/employees/:id/statutory-notice

UK ERA s.86 notice period

employees:read

GET/api/v1/hr/employees/:id/addresses

Current addresses

employees:read

GET/api/v1/hr/employees/:id/addresses/history

Address history

employees:read

POST/api/v1/hr/employees/:id/addresses

Create address

employees:write

PUT/api/v1/hr/employees/:id/addresses/:addressId

Update address

employees:write

DELETE/api/v1/hr/employees/:id/addresses/:addressId

Close address

employees:write

GET/api/v1/hr/employees/:id/positions

Concurrent position assignments

employees:read

POST/api/v1/hr/employees/:id/positions

Assign additional position

employees:write

DELETE/api/v1/hr/employees/:id/positions/:id

End position assignment

employees:write

GET/api/v1/hr/org-chart

Org chart (nodes + edges)

org:read

GET/api/v1/hr/org-chart/direct-reports/:id

Direct reports

employees:read

GET/api/v1/hr/org-chart/reporting-chain/:id

Full reporting chain

employees:read

POST/api/v1/payroll/runs

Create payroll run

payroll:runs:write

GET/api/v1/payroll/runs

List runs

payroll:runs:read

GET/api/v1/payroll/runs/:id

Get run with line items

payroll:runs:read

POST/api/v1/payroll/runs/:id/calculate

Calculate payroll

payroll:runs:write

PATCH/api/v1/payroll/runs/:id/approve

Approve run

payroll:runs:write

POST/api/v1/payroll/runs/:id/export

Export CSV/JSON

payroll:export:read

POST/api/v1/payroll/runs/:id/journal-entries

Generate journal entries

payroll:runs:write

GET/api/v1/payroll/runs/:id/journal-entries

Get journal entries

payroll:runs:read

GET/api/v1/payroll/journal-entries

List journal entries (filtered)

payroll:runs:read

PUT/api/v1/payroll/employees/:id/tax-details

Update tax details

payroll:tax_details:write

GET/api/v1/payroll/employees/:id/tax-details

Get tax details

payroll:tax_details:read

GET/api/v1/payroll/employees/:id/payslips/:runId

Get payslip data

payroll:payslips:read

GET/api/v1/payroll/pay-schedules

List pay schedules

payroll:runs:read

POST/api/v1/payroll/pay-schedules

Create pay schedule

payroll:runs:write

GET/api/v1/payroll/pay-schedules/:id

Get pay schedule

payroll:runs:read

PUT/api/v1/payroll/pay-schedules/:id

Update pay schedule

payroll:runs:write

POST/api/v1/payroll/employees/:id/pay-assignment

Assign to schedule

payroll:runs:write

GET/api/v1/payroll/employees/:id/pay-assignments

List pay assignments

payroll:runs:read

POST/api/v1/payroll/period-locks

Lock payroll period

payroll:runs:write

POST/api/v1/payroll/period-locks/:id/unlock

Unlock period

payroll:runs:write

GET/api/v1/payroll/period-locks

List period locks

payroll:runs:read

GET/api/v1/integrations

List tenant integrations

Auth: Required

GET/api/v1/integrations/:id

Get integration

Auth: Required

POST/api/v1/integrations/connect

Connect integration

Auth: Required

PATCH/api/v1/integrations/:id/config

Update config

Auth: Required

POST/api/v1/integrations/:id/disconnect

Disconnect

Auth: Required

DELETE/api/v1/integrations/:id

Delete integration

Auth: Required

Workforce Management

  • /api/v1/absence/*Leave requests, policies, types, entitlements
  • /api/v1/time/*Timesheets, shifts, clock-in/out
  • /api/v1/onboarding/*Templates, tasks
  • /api/v1/probation/*Probation tracking
  • /api/v1/equipment/*Equipment management

Talent & Performance

  • /api/v1/talent/*Reviews, goals, development plans
  • /api/v1/talent-pools/*Talent pool management
  • /api/v1/feedback-360/*360-degree feedback
  • /api/v1/competencies/*Frameworks, assessments
  • /api/v1/succession/*Plans, pools
  • /api/v1/one-to-one/*1:1 meetings
  • /api/v1/recognition/*Recognition & rewards

Recruitment & Learning

  • /api/v1/recruitment/*Requisitions, candidates, interviews, offers
  • /api/v1/lms/*Courses, learning paths, certificates

Benefits & Compensation

  • /api/v1/benefits/*Plans, enrollment, nominations
  • /api/v1/pension/*Schemes, enrollment, compliance

Employee Relations

  • /api/v1/cases/*ER cases, comments, attachments
  • /api/v1/warnings/*Disciplinary warnings
  • /api/v1/whistleblowing/*Whistleblowing reports
  • /api/v1/flexible-working/*Flexible working requests

UK Compliance

  • /api/v1/ssp/*Statutory Sick Pay
  • /api/v1/family-leave/*Family leave
  • /api/v1/statutory-leave/*Statutory leave
  • /api/v1/nmw/*National Minimum Wage
  • /api/v1/wtr/*Working Time Regulations
  • /api/v1/right-to-work/*Right to work checks
  • /api/v1/gender-pay-gap/*Gender pay gap reporting
  • /api/v1/ir35/*IR35 compliance
  • /api/v1/bank-holidays/*Bank holiday management
  • /api/v1/health-safety/*Health & safety

GDPR & Privacy

  • /api/v1/dsar/*Data subject access requests
  • /api/v1/data-erasure/*Data erasure requests
  • /api/v1/data-breach/*Breach incident tracking

Automation & Workflows

  • /api/v1/workflows/*Definitions, instances, tasks
  • /api/v1/approvals/*Approval chains
  • /api/v1/notifications/*Notification management

Platform & Admin

  • /api/v1/tenant/*Tenant settings
  • /api/v1/security/*Roles, permissions, users, audit log
  • /api/v1/dashboard/*Dashboard data
  • /api/v1/documents/*Upload, download, manage
  • /api/v1/analytics/*Metrics, charts
  • /api/v1/reports/*Dynamic report builder
  • /api/v1/sso/*SAML/OIDC configuration
  • /api/v1/api-keys/*API key management
  • /api/v1/bulk-operations/*Bulk operations
  • /api/v1/data-import/*Data import

Authentication

Two authentication methods are supported. All API endpoints under /api/v1/ require authentication unless explicitly noted.

Session Cookie

The primary method for browser-based clients. After signing in via Better Auth, a session token is set as an HTTP-only cookie.

Cookie: staffora.session_token=eyJhb...
  • Set automatically by Better Auth on sign-in
  • HTTP-only, Secure, SameSite=Lax
  • CSRF protection via HMAC-SHA256 double-submit

API Key

For service-to-service and programmatic access. API keys are tenant-scoped, hashed with SHA-256, and managed via the API Keys module.

Authorization: Bearer sfra_live_...
  • Prefix: sfra_ for easy identification
  • Stored as SHA-256 hash (plaintext never persisted)
  • Scoped to a single tenant with configurable permissions

Pagination

All collection endpoints use cursor-based pagination for consistent, efficient paging through large result sets.

Request Parameters

cursor string, optional

Opaque cursor from previous response. Omit for first page.

limit number, optional

Number of items per page (default: 20, max: 100).

GET /api/v1/hr/employees?limit=25&cursor=eyJpZCI6Ij...

Response Shape

{
  "data": [ ... ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "eyJpZCI6Ij...",
    "prevCursor": "eyJpZCI6Ij..."
  }
}
  • No offset drift -- consistent across concurrent writes
  • Efficient index-based seeking (no OFFSET scans)

Rate Limiting

Redis-backed rate limiting protects the API from abuse while providing clear feedback via response headers.

100
requests / minute
Default limit for all authenticated endpoints
10
attempts / minute
Login and authentication attempts per IP
5
requests / minute
Password reset requests per IP

Response Headers

X-RateLimit-Limit

Maximum requests allowed in the current window.

X-RateLimit-Remaining

Number of requests remaining in the current window.

X-RateLimit-Reset

Unix timestamp (seconds) when the rate limit window resets.

When a rate limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating seconds until the next request can be made.

Error Response Format

All errors follow a consistent shape with machine-readable codes and a request ID for debugging.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request body",
    "details": [
      { "field": "email", "message": "Must be a valid email" }
    ],
    "requestId": "req_01HXYZ..."
  }
}
400 Validation / bad request
401 Not authenticated
403 Insufficient permissions
404 Resource not found
409 Conflict / duplicate
429 Rate limit exceeded
500 Internal server error
503 Service unavailable