REST API v1 · Stable Third-party Integration

API Documentation

The Octal HR REST API gives third-party systems programmatic access to all HR data. Integrate ERPs, accounting platforms, payroll exporters, and custom dashboards using API Key + Secret authentication. All responses are JSON.

Overview

Third-party integrations authenticate as an API User — a dedicated credential set created and managed by an Octal HR administrator. API Users carry a scoped role that determines exactly which modules and operations are accessible.

Third-party Integration
API Key + API Secret → JWT Bearer token
token_type: api_user

Post your api_key and api_secret to /auth/token to receive a short-lived JWT. Include that JWT as Authorization: Bearer <token> on every subsequent request. Tokens expire after 1 hour; use /auth/refresh to renew without re-authenticating.

Keep secrets server-side. Never embed your API Key, API Secret, or any token in client-side JavaScript, mobile source code, or public repositories. Always use environment variables or a secrets manager.

Base URL

All v1 API requests are prefixed with:

URL
https://api.octalhr.com/v1/

All endpoints accept and return application/json. Include the following headers on every authenticated request:

Request Headers
Content-Type: application/json
Accept: application/json
Authorization: Bearer <access_token>

All list endpoints support pagination via ?page=1&per_page=25 query parameters. Responses include a meta object with total, page, per_page, and last_page.

Authentication

Every protected endpoint requires a valid JWT access token in the Authorization: Bearer header. Tokens are valid for 1 hour. Use the refresh endpoint to obtain a new pair without re-posting credentials.

On success, every auth endpoint returns the same token envelope:

Token Response
{
  "success": true,
  "data": {
    "access_token":  "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "a3f9d2e1c8b...",
    "token_type":    "Bearer",
    "expires_in":    3600
  }
}

Auth Endpoints

POST /api/v1/auth/token

Exchanges an API Key + API Secret for a JWT pair. The API User must be created and activated by an admin — see Creating API Users.

Request Body

JSON
{
  "api_key":    "hrms_4a7f2e9d1c3b8a6e...",   // required
  "api_secret": "9d3f1a7c2e8b4d6a..."    // required — shown once at creation
}

Success Response 200

JSON
{
  "success": true,
  "data": {
    "access_token":  "eyJ...",
    "refresh_token": "c9e2...",
    "token_type":    "Bearer",
    "expires_in":    3600,
    "api_user": { "id": 1, "name": "ERP Connector" },
    "tenant":   { "id": 4 }
  }
}

IP Whitelisting: API Users can optionally have an IP whitelist configured. Requests from non-whitelisted IPs receive 403 Forbidden.

POST /api/v1/auth/refresh

Exchanges a valid refresh token for a new access + refresh token pair. The old refresh token is immediately revoked (token rotation). Refresh tokens expire after 30 days of inactivity.

JSON
{
  "refresh_token": "a3f9d2e1c8b..."   // required
}

Returns the same token envelope as /auth/token.

POST /api/v1/auth/logout 🔒 Auth required

Revokes the provided refresh token. The current access token remains valid until its natural expiry (max 1 hour). Call this when your integration session ends.

JSON
{
  "refresh_token": "a3f9d2e1c8b..."
}

Returns 200 with "message": "Logged out successfully." even if the token was already revoked.

HR — Employees Permission prefix: hr.employees.*

Full CRUD for employee records including termination, reinstatement, and sub-resources like documents, bank accounts, and emergency contacts.

MethodEndpointDescriptionPermission
GET/api/v1/hr/employeesList employees (paginated). Filter by ?status=active&department_id=3hr.employees.view
POST/api/v1/hr/employeesCreate a new employee recordhr.employees.add
GET/api/v1/hr/employees/{id}Get single employee with full profilehr.employees.view
PATCH/api/v1/hr/employees/{id}Update employee fields (partial)hr.employees.edit
DELETE/api/v1/hr/employees/{id}Archive employee recordhr.employees.delete
POST/api/v1/hr/employees/{id}/terminateTerminate employee — requires termination_date, reasonhr.employees.terminate
POST/api/v1/hr/employees/{id}/reinstateReinstate a terminated employeehr.employees.edit
GET/api/v1/hr/employees/{id}/documentsList documents attached to employeehr.employees.view
GET/api/v1/hr/employees/{id}/bank-accountsEmployee bank accounts for salary disbursementhr.employees.view
GET/api/v1/hr/employees/{id}/emergency-contactsEmergency contacts on filehr.employees.view

Example — List active employees

HTTP
GET /v1/hr/employees?status=active&per_page=50
Authorization: Bearer eyJ...
Response 200
{
  "success": true,
  "data": [
    {
      "id": 42,
      "employee_code": "EMP-0042",
      "full_name": "Sara Khan",
      "email": "sara.khan@company.com",
      "department": "Finance",
      "designation": "Senior Accountant",
      "hire_date": "2022-03-01",
      "status": "active"
    }
  ],
  "meta": { "total": 84, "page": 1, "per_page": 50, "last_page": 2 }
}
HR — Employee Profile Sub-resources Permission prefix: hr.employees.profile.*

CRUD for structured profile sections: work history, education, skills, dependants, certifications, and distinctions. All routes are nested under /employees/{id}/.

MethodEndpointDescriptionPermission
GET/api/v1/employees/{id}/work-historyList work history entrieshr.employees.profile.view
POST/api/v1/employees/{id}/work-historyAdd work history entryhr.employees.profile.add
PATCH/api/v1/employees/{id}/work-history/{rid}Update work history entryhr.employees.profile.edit
DELETE/api/v1/employees/{id}/work-history/{rid}Delete work history entryhr.employees.profile.delete
GET/api/v1/employees/{id}/educationList education recordshr.employees.profile.view
POST/api/v1/employees/{id}/educationAdd education recordhr.employees.profile.add
PATCH/api/v1/employees/{id}/education/{rid}Update education recordhr.employees.profile.edit
DELETE/api/v1/employees/{id}/education/{rid}Delete education recordhr.employees.profile.delete
GET/api/v1/employees/{id}/skillsList skillshr.employees.profile.view
POST/api/v1/employees/{id}/skillsAdd skillhr.employees.profile.add
PATCH/api/v1/employees/{id}/skills/{rid}Update skillhr.employees.profile.edit
DELETE/api/v1/employees/{id}/skills/{rid}Delete skillhr.employees.profile.delete
GET/api/v1/employees/{id}/dependantsList dependantshr.employees.profile.view
POST/api/v1/employees/{id}/dependantsAdd dependanthr.employees.profile.add
PATCH/api/v1/employees/{id}/dependants/{rid}Update dependanthr.employees.profile.edit
DELETE/api/v1/employees/{id}/dependants/{rid}Delete dependanthr.employees.profile.delete
GET/api/v1/employees/{id}/certificationsList certificationshr.employees.profile.view
POST/api/v1/employees/{id}/certificationsAdd certificationhr.employees.profile.add
PATCH/api/v1/employees/{id}/certifications/{rid}Update certificationhr.employees.profile.edit
DELETE/api/v1/employees/{id}/certifications/{rid}Delete certificationhr.employees.profile.delete
GET/api/v1/employees/{id}/distinctionsList distinctions / awardshr.employees.profile.view
POST/api/v1/employees/{id}/distinctionsAdd distinctionhr.employees.profile.add
PATCH/api/v1/employees/{id}/distinctions/{rid}Update distinctionhr.employees.profile.edit
DELETE/api/v1/employees/{id}/distinctions/{rid}Delete distinctionhr.employees.profile.delete

Key fields — work-history POST body

JSON
{
  "company_name":       "Acme Corp",       // required
  "designation":        "Team Lead",
  "department":         "Engineering",
  "from_date":          "2019-01-01",       // required
  "to_date":            "2022-12-31",
  "responsibilities":   "Led a team of 6...",
  "reason_for_leaving": "Better opportunity",
  "last_salary":        120000,
  "reference_name":     "Jane Doe",
  "reference_contact":  "+1-555-000-1234"
}
HR — Departments Permission prefix: hr.departments.*
MethodEndpointDescriptionPermission
GET/api/v1/hr/departmentsList all departmentshr.departments.view
POST/api/v1/hr/departmentsCreate departmenthr.departments.add
GET/api/v1/hr/departments/{id}Get department detailhr.departments.view
PATCH/api/v1/hr/departments/{id}Update departmenthr.departments.edit
DELETE/api/v1/hr/departments/{id}Delete departmenthr.departments.delete
HR — Designations Permission prefix: hr.designations.*
MethodEndpointDescriptionPermission
GET/api/v1/hr/designationsList all designationshr.designations.view
POST/api/v1/hr/designationsCreate designationhr.designations.add
GET/api/v1/hr/designations/{id}Get designation detailhr.designations.view
PATCH/api/v1/hr/designations/{id}Update designationhr.designations.edit
DELETE/api/v1/hr/designations/{id}Delete designationhr.designations.delete
HR — Shifts Permission prefix: hr.shifts.*
MethodEndpointDescriptionPermission
GET/api/v1/hr/shiftsList all shiftshr.shifts.view
POST/api/v1/hr/shiftsCreate shifthr.shifts.add
GET/api/v1/hr/shifts/{id}Get shift detailhr.shifts.view
PATCH/api/v1/hr/shifts/{id}Update shifthr.shifts.edit
DELETE/api/v1/hr/shifts/{id}Delete shifthr.shifts.delete
HR — Holidays Permission prefix: hr.holidays.*
MethodEndpointDescriptionPermission
GET/api/v1/hr/holidaysList holidays. Filter by ?year=2026hr.holidays.view
POST/api/v1/hr/holidaysCreate holidayhr.holidays.add
GET/api/v1/hr/holidays/{id}Get holiday detailhr.holidays.view
PATCH/api/v1/hr/holidays/{id}Update holidayhr.holidays.edit
DELETE/api/v1/hr/holidays/{id}Delete holidayhr.holidays.delete
HR — Org Chart Permission: hr.orgchart.view

Read-only org chart endpoints. Returns the reporting hierarchy as a nested tree, or a flat node for a single employee.

MethodEndpointDescriptionPermission
GET/api/v1/hr/org-chartFull org tree (nested JSON)hr.orgchart.view
GET/api/v1/hr/org-chart/employee/{id}Single employee node with direct reportshr.orgchart.view
GET/api/v1/hr/org-chart/searchSearch employees in tree by ?q=sarahr.orgchart.view
Attendance — Records Permission prefix: attendance.*

Attendance records track daily check-in/check-out events per employee. Filter by ?employee_id=42&from=2026-05-01&to=2026-05-31.

MethodEndpointDescriptionPermission
GET/api/v1/attendanceList attendance records (paginated)attendance.view
POST/api/v1/attendancePost a new attendance recordattendance.add
GET/api/v1/attendance/{id}Get single attendance recordattendance.view
PATCH/api/v1/attendance/{id}Edit attendance record (regularization)attendance.edit
DELETE/api/v1/attendance/{id}Delete attendance recordattendance.delete
Attendance — Overtime Permission prefix: attendance.overtime.*
MethodEndpointDescriptionPermission
GET/api/v1/attendance/overtimeList overtime entriesattendance.overtime.view
POST/api/v1/attendance/overtimeCreate overtime entryattendance.overtime.add
PATCH/api/v1/attendance/overtime/{id}Update overtime entryattendance.overtime.edit
DELETE/api/v1/attendance/overtime/{id}Delete overtime entryattendance.overtime.delete
Attendance — Loss of Pay (LOP) Permission prefix: attendance.lop.*

LOP records are deducted from the employee's payslip for the applicable period.

MethodEndpointDescriptionPermission
GET/api/v1/attendance/lopList LOP entriesattendance.lop.view
POST/api/v1/attendance/lopCreate LOP entryattendance.lop.add
PATCH/api/v1/attendance/lop/{id}Update LOP entryattendance.lop.edit
DELETE/api/v1/attendance/lop/{id}Delete LOP entryattendance.lop.delete
Leave — Leave Types Permission prefix: leave.types.*
MethodEndpointDescriptionPermission
GET/api/v1/leave/typesList all leave typesleave.types.view
POST/api/v1/leave/typesCreate leave typeleave.types.add
GET/api/v1/leave/types/{id}Get leave type detailleave.types.view
PATCH/api/v1/leave/types/{id}Update leave typeleave.types.edit
DELETE/api/v1/leave/types/{id}Delete leave typeleave.types.delete
Leave — Allocations Permission prefix: leave.allocations.*

Allocate leave entitlements to employees or groups for a specific leave type and period.

MethodEndpointDescriptionPermission
GET/api/v1/leave/allocationsList allocations. Filter by ?employee_id=42leave.allocations.view
POST/api/v1/leave/allocationsCreate allocationleave.allocations.add
GET/api/v1/leave/allocations/{id}Get allocation detailleave.allocations.view
PATCH/api/v1/leave/allocations/{id}Update allocationleave.allocations.edit
DELETE/api/v1/leave/allocations/{id}Delete allocationleave.allocations.delete
Leave — Requests Permission prefix: leave.*
MethodEndpointDescriptionPermission
GET/api/v1/leave/requestsList leave requests. Filter by ?status=pendingleave.view
POST/api/v1/leave/requestsSubmit a leave requestleave.add
GET/api/v1/leave/requests/{id}Get leave request detailleave.view
POST/api/v1/leave/requests/{id}/approveApprove pending leave requestleave.approve
POST/api/v1/leave/requests/{id}/rejectReject pending leave request — requires reasonleave.approve
DELETE/api/v1/leave/requests/{id}Cancel / delete leave requestleave.delete
Leave — Balances Permission: leave.view
MethodEndpointDescriptionPermission
GET/api/v1/leave/balancesAll employee balances for current yearleave.view
GET/api/v1/leave/balances/{employee_id}Balances for a specific employeeleave.view

Example response — employee balances

Response 200
{
  "success": true,
  "data": [
    { "leave_type": "Annual",  "allocated": 21, "used": 5, "balance": 16 },
    { "leave_type": "Sick",    "allocated": 10, "used": 2, "balance": 8  },
    { "leave_type": "Casual",  "allocated": 7,  "used": 0, "balance": 7  }
  ]
}
Payroll — Salary Structures Permission prefix: payroll.structures.*

Salary structures define the components (basic, HRA, allowances, deductions) that make up an employee's pay package.

MethodEndpointDescriptionPermission
GET/api/v1/payroll/structuresList salary structurespayroll.structures.view
POST/api/v1/payroll/structuresCreate salary structurepayroll.structures.add
GET/api/v1/payroll/structures/{id}Get structure with component breakdownpayroll.structures.view
PATCH/api/v1/payroll/structures/{id}Update structurepayroll.structures.edit
DELETE/api/v1/payroll/structures/{id}Delete structurepayroll.structures.delete
Payroll — Payroll Runs Permission prefix: payroll.runs.*

A payroll run processes salaries for a given period. Runs go through draft → processed → approved → finalized states.

MethodEndpointDescriptionPermission
GET/api/v1/payroll/runsList payroll runspayroll.runs.view
POST/api/v1/payroll/runsCreate a new payroll run draftpayroll.runs.add
GET/api/v1/payroll/runs/{id}Get run detail with summary totalspayroll.runs.view
POST/api/v1/payroll/runs/{id}/processProcess payroll (calculate payslips)payroll.runs.edit
POST/api/v1/payroll/runs/{id}/approveApprove a processed runpayroll.runs.approve
POST/api/v1/payroll/runs/{id}/rejectReject run — requires reasonpayroll.runs.approve
DELETE/api/v1/payroll/runs/{id}Delete draft runpayroll.runs.delete
Payroll — Payslips Permission prefix: payroll.payslips.*
MethodEndpointDescriptionPermission
GET/api/v1/payroll/payslipsList payslips. Filter by ?employee_id=42&run_id=7payroll.payslips.view
GET/api/v1/payroll/payslips/{id}Get payslip with earnings/deductions breakdownpayroll.payslips.view
GET/api/v1/payroll/payslips/{id}/pdfDownload payslip as PDF (binary response)payroll.payslips.view
Payroll — Salary Adjustments Permission prefix: payroll.adjustments.*

One-off additions or deductions applied to a specific payroll run (bonuses, penalties, reimbursements).

MethodEndpointDescriptionPermission
GET/api/v1/payroll/adjustmentsList adjustments. Filter by ?run_id=7payroll.adjustments.view
POST/api/v1/payroll/adjustmentsCreate adjustment — requires employee_id, run_id, type (addition|deduction), amountpayroll.adjustments.add
PATCH/api/v1/payroll/adjustments/{id}Update adjustmentpayroll.adjustments.edit
DELETE/api/v1/payroll/adjustments/{id}Delete adjustmentpayroll.adjustments.delete
Payroll — Payment Vouchers Permission prefix: payroll.payments.*
MethodEndpointDescriptionPermission
GET/api/v1/payroll/paymentsList payment voucherspayroll.payments.view
POST/api/v1/payroll/paymentsCreate payment voucher for a finalized runpayroll.payments.add
GET/api/v1/payroll/payments/{id}Get voucher detailpayroll.payments.view
Payroll — Wage Configuration Permission prefix: payroll.wage.*

Tenant-level wage settings — minimum wage, overtime multipliers, and currency configuration used in payroll calculations.

MethodEndpointDescriptionPermission
GET/api/v1/payroll/wage-configGet current wage configurationpayroll.wage.view
PATCH/api/v1/payroll/wage-configUpdate wage configurationpayroll.wage.edit
Payroll — Salary Advances Permission prefix: payroll.advances.*

Short-term salary advances paid to employees ahead of their pay date. Recovered automatically from the next payslip.

MethodEndpointDescriptionPermission
GET/api/v1/payroll/advancesList advances. Filter by ?employee_id=42&status=pendingpayroll.advances.view
POST/api/v1/payroll/advancesCreate advance — requires employee_id, amount, advance_datepayroll.advances.add
POST/api/v1/payroll/advances/{id}/cancelCancel a pending advancepayroll.advances.delete
DELETE/api/v1/payroll/advances/{id}Delete advance recordpayroll.advances.delete
Payroll — Payroll Arrears Permission prefix: payroll.arrears.*

Arrears are supplementary amounts added to a payroll run to cover under-payments from previous periods.

MethodEndpointDescriptionPermission
GET/api/v1/payroll/runs/{runId}/arrearsList arrears for a payroll runpayroll.arrears.view
POST/api/v1/payroll/runs/{runId}/arrearsAdd arrear entry to runpayroll.arrears.add
DELETE/api/v1/payroll/runs/{runId}/arrears/{id}Remove arrear entrypayroll.arrears.delete
Payroll — Approval Chain Permission prefix: payroll.approval.*

Configure multi-level approval chains for payroll runs. Each level defines a role that must approve before the run advances.

MethodEndpointDescriptionPermission
GET/api/v1/settings/approval-chainGet current approval chain levelspayroll.approval.view
POST/api/v1/settings/approval-chainSave approval chain (replaces all levels)payroll.approval.edit
Loans Permission prefix: loans.*

Employee loan management with EMI, bullet, or manual repayment schedules. Loans integrate with payroll for automatic EMI deductions.

MethodEndpointDescriptionPermission
GET/api/v1/loansList loans. Filter by ?employee_id=42&status=activeloans.view
POST/api/v1/loansCreate loan applicationloans.add
GET/api/v1/loans/{id}Get loan detail with repayment scheduleloans.view
PATCH/api/v1/loans/{id}Edit loan details (draft only)loans.edit
DELETE/api/v1/loans/{id}Delete loan (draft only)loans.delete
POST/api/v1/loans/{id}/approveApprove loan applicationloans.approve
POST/api/v1/loans/{id}/disburseMark loan as disbursedloans.disburse
POST/api/v1/loans/{id}/restructureRestructure active loan scheduleloans.restructure
GET/api/v1/loans/reportsLoan summary report (outstanding, EMI, etc.)loans.reports.view

Loan — POST body

JSON
{
  "employee_id":    42,              // required
  "loan_type_id":   2,
  "amount":         500000,          // required
  "repayment_type": "emi",           // emi | bullet | manual
  "emi_months":     12,
  "interest_rate":  0,               // percent per annum
  "start_date":     "2026-06-01"
}
Tax — Regimes Permission prefix: tax.regimes.*

Tax regimes define the slab structure applied during payslip tax computation. Multiple regimes can exist simultaneously (e.g., different fiscal years).

MethodEndpointDescriptionPermission
GET/api/v1/tax/regimesList tax regimestax.regimes.view
POST/api/v1/tax/regimesCreate tax regimetax.regimes.add
GET/api/v1/tax/regimes/{id}Get regime with slab detailtax.regimes.view
PATCH/api/v1/tax/regimes/{id}Update regimetax.regimes.edit
DELETE/api/v1/tax/regimes/{id}Delete regimetax.regimes.delete
Tax — Employee Tax Profiles Permission prefix: tax.profiles.*
MethodEndpointDescriptionPermission
GET/api/v1/tax/profilesList employee tax profilestax.profiles.view
POST/api/v1/tax/profilesCreate tax profile for employeetax.profiles.add
GET/api/v1/tax/profiles/{id}Get profile detailtax.profiles.view
PATCH/api/v1/tax/profiles/{id}Update tax profiletax.profiles.edit
Tax — Reports Permission: tax.reports.view
MethodEndpointDescriptionPermission
GET/api/v1/tax/reportsTax deduction summary report. Filter by ?year=2026tax.reports.view
Payments — Company Bank Accounts Permission prefix: payments.banks.*

Company bank accounts used for salary disbursement and payment vouchers.

MethodEndpointDescriptionPermission
GET/api/v1/payments/bank-accountsList bank accountspayments.banks.view
POST/api/v1/payments/bank-accountsAdd bank accountpayments.banks.add
GET/api/v1/payments/bank-accounts/{id}Get account detailpayments.banks.view
PATCH/api/v1/payments/bank-accounts/{id}Update bank accountpayments.banks.edit
DELETE/api/v1/payments/bank-accounts/{id}Remove bank accountpayments.banks.delete
Tasks Permission prefix: tasks.*
MethodEndpointDescriptionPermission
GET/api/v1/tasksList tasks. Filter by ?assigned_to=42&status=opentasks.view
POST/api/v1/tasksCreate task — requires title, assigned_totasks.add
GET/api/v1/tasks/{id}Get task detailtasks.view
PATCH/api/v1/tasks/{id}Update tasktasks.edit
DELETE/api/v1/tasks/{id}Delete tasktasks.delete
POST/api/v1/tasks/{id}/completeMark task as completetasks.edit
Surveys Permission prefix: surveys.*
MethodEndpointDescriptionPermission
GET/api/v1/surveysList surveyssurveys.view
POST/api/v1/surveysCreate survey with questionssurveys.add
GET/api/v1/surveys/{id}Get survey with questionssurveys.view
PATCH/api/v1/surveys/{id}Update surveysurveys.edit
DELETE/api/v1/surveys/{id}Delete surveysurveys.delete
GET/api/v1/surveys/{id}/resultsAggregated response resultssurveys.reports.view
POST/api/v1/surveys/{id}/respondSubmit survey response on behalf of an employeesurveys.add
Visitors Permission prefix: visitors.*

Visitor management — log walk-in visits, manage a blacklist, and issue visitor badges.

MethodEndpointDescriptionPermission
GET/api/v1/visitorsList visitor records. Filter by ?date=2026-05-13visitors.view
POST/api/v1/visitorsLog a new visitorvisitors.add
GET/api/v1/visitors/{id}Get visitor detailvisitors.view
PATCH/api/v1/visitors/{id}Update visitor record (check-out time, etc.)visitors.edit
DELETE/api/v1/visitors/{id}Delete visitor recordvisitors.delete
GET/api/v1/visitors/blacklistList blacklisted visitorsvisitors.blacklist.view
POST/api/v1/visitors/blacklistAdd visitor to blacklistvisitors.blacklist.add
DELETE/api/v1/visitors/blacklist/{id}Remove from blacklistvisitors.blacklist.delete
GET/api/v1/visitors/badgesList visitor badge configurationsvisitors.badges.view
POST/api/v1/visitors/badgesIssue visitor badgevisitors.badges.add
DELETE/api/v1/visitors/badges/{id}Revoke visitor badgevisitors.badges.delete
Settings — Roles & Permissions Permission prefix: settings.roles.*
MethodEndpointDescriptionPermission
GET/api/v1/settings/rolesList all roles with permission slugssettings.roles.view
POST/api/v1/settings/rolesCreate role with permissions arraysettings.roles.add
GET/api/v1/settings/roles/{id}Get role detailsettings.roles.view
PATCH/api/v1/settings/roles/{id}Update role and its permissionssettings.roles.edit
DELETE/api/v1/settings/roles/{id}Delete role (only if unassigned)settings.roles.delete
Settings — Admin Users Permission prefix: settings.users.*
MethodEndpointDescriptionPermission
GET/api/v1/settings/usersList admin userssettings.users.view
POST/api/v1/settings/usersCreate admin usersettings.users.add
GET/api/v1/settings/users/{id}Get user detailsettings.users.view
PATCH/api/v1/settings/users/{id}Update usersettings.users.edit
DELETE/api/v1/settings/users/{id}Delete usersettings.users.delete
Settings — General Permission: settings.general.view / edit

Tenant-level settings: company name, locale, currency, logo, payroll period, etc.

MethodEndpointDescriptionPermission
GET/api/v1/settings/generalGet all tenant settingssettings.general.view
PATCH/api/v1/settings/generalUpdate tenant settings (partial)settings.general.edit
Settings — LOP Rules Permission prefix: settings.lop.*

Loss-of-pay deduction rules per absence type, applied automatically in payroll calculation.

MethodEndpointDescriptionPermission
GET/api/v1/settings/lop-rulesList LOP rulessettings.lop.view
POST/api/v1/settings/lop-rulesCreate LOP rulesettings.lop.edit
GET/api/v1/settings/lop-rules/{id}Get rule detailsettings.lop.view
PATCH/api/v1/settings/lop-rules/{id}Update LOP rulesettings.lop.edit
DELETE/api/v1/settings/lop-rules/{id}Delete LOP rulesettings.lop.edit
Settings — Overtime Rules Permission prefix: settings.overtime.*
MethodEndpointDescriptionPermission
GET/api/v1/settings/overtime-rulesList overtime rulessettings.overtime.view
POST/api/v1/settings/overtime-rulesCreate overtime rulesettings.overtime.edit
GET/api/v1/settings/overtime-rules/{id}Get rule detailsettings.overtime.view
PATCH/api/v1/settings/overtime-rules/{id}Update overtime rulesettings.overtime.edit
DELETE/api/v1/settings/overtime-rules/{id}Delete overtime rulesettings.overtime.edit
Logs — Audit Log Permission: logs.audit.view

Read-only audit trail of all create/update/delete actions across the system. Filter by ?user_id=5&module=payroll&from=2026-05-01.

MethodEndpointDescriptionPermission
GET/api/v1/logs/auditPaginated audit log entrieslogs.audit.view
Logs — Email Log Permission: logs.email.view
MethodEndpointDescriptionPermission
GET/api/v1/logs/emailList sent emails with delivery statuslogs.email.view
Logs — Notifications Permission: logs.notifications.view
MethodEndpointDescriptionPermission
GET/api/v1/notificationsList in-app notifications for the API Userlogs.notifications.view
PATCH/api/v1/notifications/{id}/readMark notification as readlogs.notifications.view

Permission Slugs

Every endpoint is gated by a permission slug. Assign slugs to a role in Settings → Roles & Permissions, then assign that role to an API User. The table below lists all slugs available for API Users (marked is_api = 1 in the system).

HR

hr.employees.view hr.employees.add hr.employees.edit hr.employees.delete hr.employees.terminate hr.employees.profile.view hr.employees.profile.add hr.employees.profile.edit hr.employees.profile.delete hr.departments.view hr.departments.add hr.departments.edit hr.departments.delete hr.designations.view hr.designations.add hr.designations.edit hr.designations.delete hr.shifts.view hr.shifts.add hr.shifts.edit hr.shifts.delete hr.holidays.view hr.holidays.add hr.holidays.edit hr.holidays.delete hr.orgchart.view

Attendance

attendance.view attendance.add attendance.edit attendance.delete attendance.overtime.view attendance.overtime.add attendance.overtime.edit attendance.overtime.delete attendance.lop.view attendance.lop.add attendance.lop.edit attendance.lop.delete

Leave

leave.view leave.add leave.approve leave.delete leave.types.view leave.types.add leave.types.edit leave.types.delete leave.allocations.view leave.allocations.add leave.allocations.edit leave.allocations.delete

Payroll

payroll.structures.view payroll.structures.add payroll.structures.edit payroll.structures.delete payroll.runs.view payroll.runs.add payroll.runs.edit payroll.runs.approve payroll.runs.delete payroll.payslips.view payroll.adjustments.view payroll.adjustments.add payroll.adjustments.edit payroll.adjustments.delete payroll.payments.view payroll.payments.add payroll.wage.view payroll.wage.edit payroll.advances.view payroll.advances.add payroll.advances.delete payroll.arrears.view payroll.arrears.add payroll.arrears.delete payroll.approval.view payroll.approval.edit

Loans

loans.view loans.add loans.edit loans.delete loans.approve loans.disburse loans.restructure loans.reports.view loans.reports.export

Tax

tax.regimes.view tax.regimes.add tax.regimes.edit tax.regimes.delete tax.profiles.view tax.profiles.add tax.profiles.edit tax.reports.view

Other Modules

payments.banks.view payments.banks.add payments.banks.edit payments.banks.delete tasks.view tasks.add tasks.edit tasks.delete surveys.view surveys.add surveys.edit surveys.delete surveys.reports.view visitors.view visitors.add visitors.edit visitors.delete visitors.blacklist.view visitors.blacklist.add visitors.blacklist.delete visitors.badges.view visitors.badges.add visitors.badges.delete

Settings & Logs

settings.roles.view settings.roles.add settings.roles.edit settings.roles.delete settings.users.view settings.users.add settings.users.edit settings.users.delete settings.general.view settings.general.edit settings.lop.view settings.lop.edit settings.overtime.view settings.overtime.edit logs.audit.view logs.email.view logs.notifications.view

To see all permissions in the admin UI, go to Settings → Roles & Permissions → All Permissions.

Error Codes

All errors follow a consistent envelope:

Error Envelope
{
  "success": false,
  "errors": [
    {
      "field":   "email",           // null for non-field errors
      "message": "Email is required."
    }
  ]
}
StatusMeaning
400Validation error — request body failed validation. The errors array contains field-level messages.
401Unauthorized — missing, invalid, or expired JWT. Re-authenticate with /auth/token or refresh with /auth/refresh.
403Forbidden — token is valid but the API User's role lacks the required permission slug, or the request IP is not whitelisted.
404Not found — the requested resource does not exist or belongs to a different tenant.
422Business rule violation — e.g., approving an already-approved leave, processing an already-processed payroll run, or disbursing an unapproved loan.
429Rate limited — too many requests in a short window. Slow down and retry after the Retry-After header value.
500Server error — unexpected internal failure. Contact support with the timestamp and request ID from the response.

Creating API Users

Third-party systems authenticate as an API User — a dedicated credential set with its own scoped role. API Users are created by an administrator in the Octal HR panel. The API Secret is shown exactly once at creation — store it immediately.

1
Log in to Octal HR as an Administrator or a user with the Settings: API Users — Add permission.
2
Navigate to Settings → User Management → API Users.
3
Click + New API User. Enter a descriptive Name (e.g., "ERP Connector", "Payroll Export Bot").
4
Select a Role to define which endpoints this integration can access. Create a scoped role first — grant only what is necessary (principle of least privilege).
5
Optionally enter a comma-separated IP Whitelist to restrict access to known server IPs.
6
Click Create API User. Copy both the API Key and API Secret immediately — the secret cannot be retrieved after you leave the page.
7
Store credentials securely in environment variables. Call POST /api/v1/auth/token to obtain a JWT on each session.

Secret stored as a one-way hash. Octal HR stores only a bcrypt hash of the API Secret. If you lose it, use the Regenerate Secret button — this immediately revokes all existing tokens for that API User and issues new credentials.

Typical Integration Pattern

Python — example
# 1. Authenticate once per session (token valid for 1 hour)
import requests, os

resp = requests.post("https://api.octalhr.com/v1/auth/token", json={
    "api_key":    os.environ["OCTALHR_API_KEY"],
    "api_secret": os.environ["OCTALHR_API_SECRET"],
})
token = resp.json()["data"]["access_token"]
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}

# 2. Use the token on subsequent requests
employees = requests.get(
    "https://api.octalhr.com/v1/hr/employees?status=active",
    headers=headers
).json()

# 3. Refresh before expiry (or handle 401 → re-auth)
refresh_resp = requests.post(
    "https://api.octalhr.com/v1/auth/refresh",
    json={"refresh_token": resp.json()["data"]["refresh_token"]}
)
token = refresh_resp.json()["data"]["access_token"]
Need help with the API?

Contact us at info@octalhr.com or visit the Help Center for guides and tutorials.