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.
Core Endpoints
The API covers all major HR modules. Below are the most commonly used endpoints.
Employees
| Method | Endpoint | Description |
|---|---|---|
| GET | /employees | List all employees (paginated, filterable) |
| GET | /employees/{id} | Get a single employee's full profile |
| POST | /employees | Create a new employee record |
| PATCH | /employees/{id} | Update employee fields (partial update) |
| DELETE | /employees/{id} | Soft-delete (archive) an employee |
Attendance & Leave
| Method | Endpoint | Description |
|---|---|---|
| GET | /attendance | Get attendance records with date range filter |
| POST | /attendance | Post a check-in or check-out event |
| GET | /leaves | List leave applications |
| POST | /leaves | Submit a leave application on behalf of an employee |
Payroll
| Method | Endpoint | Description |
|---|---|---|
| GET | /payroll/runs | List payroll runs with status |
| GET | /payroll/runs/{id}/payslips | Get all payslips for a payroll run |
| GET | /employees/{id}/payslips | Get 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 Status | Code | Meaning |
|---|---|---|
| 400 | validation_error | Request body failed validation; errors array in response |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key does not have permission for this action |
| 404 | not_found | Resource does not exist |
| 409 | conflict | Duplicate resource (e.g., employee number already exists) |
| 422 | unprocessable | Business rule violation (e.g., approving a closed loan) |
| 500 | server_error | Internal error; please contact support with the request ID |