Base URL & Versioning

All API requests are made to a tenant-specific subdomain. The current stable version is v1.

https://{your-tenant}.octalhr.com/api/v1/

# Example
https://abc.octalhr.com/api/v1/employees

The API is versioned in the URL path. The current version is v1; a breaking change would be introduced as a new version.

Authentication

Authenticate by exchanging your API key and secret for a short-lived JWT access token, then send that token as a Bearer token on subsequent requests.

# 1. Exchange key + secret for a token
POST /api/v1/auth/token
{
  "api_key": "...",
  "api_secret": "..."
}

# 2. Use the returned JWT on every request
Authorization: Bearer <jwt-access-token>
Content-Type: application/json
Accept: application/json

Access tokens are short-lived; use the refresh token returned alongside them (POST /api/v1/auth/refresh) to obtain a new pair, and POST /api/v1/auth/logout to revoke it.

Never expose your API secret. Do not include it in frontend JavaScript, mobile apps, or public repositories. Keep it in environment variables on your server side.

Core Endpoints

The API covers all major HR modules. Below are the most commonly used endpoints.

Employees

MethodEndpointDescription
GET/employeesList all employees (paginated, filterable)
GET/employees/{id}Get a single employee's full profile
POST/employeesCreate a new employee record
PATCH/employees/{id}Update employee fields (partial update)
DELETE/employees/{id}Soft-delete (archive) an employee

Attendance & Leave

MethodEndpointDescription
GET/attendanceGet attendance records with date range filter
POST/attendancePost a check-in or check-out event
GET/leavesList leave applications
POST/leavesSubmit a leave application on behalf of an employee

Payroll

MethodEndpointDescription
GET/payroll/runsList payroll runs with status
GET/payroll/runs/{id}/payslipsGet all payslips for a payroll run
GET/employees/{id}/payslipsGet payslip history for a single employee

Request & Response Format

All request and response bodies use JSON. Dates are ISO 8601 (YYYY-MM-DD). Monetary amounts are integers in the smallest unit of the configured currency (paisas for PKR).

// GET /api/v1/employees/42 — example response
{
  "id": 42,
  "employee_number": "EMP-0042",
  "first_name": "Sana",
  "last_name": "Akhtar",
  "department": "Finance",
  "designation": "Senior Accountant",
  "joining_date": "2022-03-01",
  "status": "active",
  "gross_salary": 9500000  // PKR 95,000 in paisas
}

Paginated endpoints return a meta object with total, page, per_page, and last_page. Use the page query parameter to navigate pages.

Error Codes

HTTP StatusCodeMeaning
400validation_errorRequest body failed validation; errors array in response
401unauthorizedMissing or invalid API key
403forbiddenAPI key does not have permission for this action
404not_foundResource does not exist
409conflictDuplicate resource (e.g., employee number already exists)
422unprocessableBusiness rule violation (e.g., approving a closed loan)
500server_errorInternal error; please contact support with the request ID

Generating API Keys

1
Go to Settings → Integrations → API Keys.
2
Click + New API Key.
3
Enter a descriptive name (e.g., "Accounting Sync — QuickBooks") and select the permission scopes needed.
4
Set an optional expiry date. Keys with no expiry date are valid until revoked.
5
Click Generate. Copy the API key and secret immediately — the secret is only shown once.
6
To revoke a key, return to API Keys, find the key, and click Revoke. Revocation is immediate.
Scoped keys: Create separate API keys for each integration with only the scopes needed. A payroll export key should not have write access to employee records.