API Documentation
How to explore and call the MotorPH REST API. These pages are the map: cross-cutting conventions, module-by-module endpoint tables, and detailed request/response shapes for only the highest-traffic endpoints. The exhaustive, always-current per-field contract is Swagger UI — generated from the code by springdoc, so it can never drift from the controllers the way hand-written docs can.
Swagger UI (the source of truth)
With the dev stack running (docker compose up -d --build):
| What | URL |
|---|---|
| Swagger UI | http://localhost:8081/swagger-ui.html |
| Raw OpenAPI 3 spec (JSON) | http://localhost:8081/v3/api-docs |
Both are gated by the SWAGGER_ENABLED environment variable
(reference/env-vars.md): it defaults to on in
docker-compose.yml and is hard-set to off in
production client stacks
(docker-compose.client.template.yml),
so never assume Swagger is reachable on a deployed instance.
Authorizing inside Swagger UI
Almost every endpoint requires a JWT. To use "Try it out":
- In Swagger UI, expand Authentication → POST /api/auth/login, click
Try it out, and send a body such as
{"username": "sysadmin_demo", "password": "<the seeded demo password>"}(seeded dev logins: reference/demo-users.md). - Copy the
accessTokenvalue from the response. - Click the Authorize button (top right), paste the token into the dialog,
and confirm. Swagger now sends
Authorization: Bearer <token>on every "Try it out" request.
Access tokens expire after 15 minutes — if calls start returning 401, log in again and re-authorize.
Importing into Postman or Insomnia
Postman:
- Import (top-left of the workspace) → choose the Link / URL option.
- Paste
http://localhost:8081/v3/api-docsand continue. - Confirm the import as an OpenAPI 3 collection — Postman generates a folder per tag with every endpoint prefilled.
Then set a collection-level Bearer Token auth using an accessToken from
POST /api/auth/login so you don't paste it per request.
Insomnia: Create → Import From → URL, paste the same /v3/api-docs URL.
Insomnia builds a request collection from the spec; add the
Authorization: Bearer <token> header via collection environment or per
request.
curl quickstart
BASE=http://localhost:8081
# 1. Log in and capture the access token (jq required)
TOKEN=$(curl -s -X POST "$BASE/api/auth/login" \
-H 'Content-Type: application/json' \
-d '{"username":"sysadmin_demo","password":"<the seeded demo password>"}' \
| jq -r .accessToken)
# 2. Call an authenticated endpoint
curl -s "$BASE/api/auth/me" -H "Authorization: Bearer $TOKEN" | jq .
# 3. A paged list (permissions permitting — try the `hr_demo` login for HR endpoints)
curl -s "$BASE/api/employees?page=0&size=5&sort=lastName,asc" \
-H "Authorization: Bearer $TOKEN" | jq .
Port 8081 is the host-mapped backend from docker-compose.yml. Requests
through the frontend proxy (http://localhost:5173/api/...) behave
identically — that is the path the browser uses in normal operation
(architecture.md).
Module documentation index
| Doc | Modules covered |
|---|---|
| conventions.md | Cross-cutting: auth header, pagination, filtering, validation, the error table, permissions |
| auth.md | Login / refresh / logout / me, portal auth, ALTCHA |
| hr.md | Employees, departments, positions, timesheets, leave, overtime, work suspensions |
| payroll.md | Payroll runs, payslips, transactions, settings, bonuses, deductions, statutory rate tables, government forms, holidays, reports |
| recruitment.md | Requisitions → openings → applicants → offers, interviews, staffing plans, public careers |
| admin-and-messaging.md | Users/roles/permissions, audit logs, saved views, demo data, announcements, notifications, chat + WebSocket |
| portal-crm-inventory.md | Customer portal (separate auth), CRM, inventory/warehouse |
| billing-and-webhooks.md | Billing endpoints, public checkout links, provider webhooks |