Skip to main content

Authentication

Sanctum personal-access tokens for every client (web, mobile, third-party).

Login

POST /api/v1/auth/login
Content-Type: application/json

{
"email": "hr@acme.com",
"password": "secret",
"device_name": "chrome-desktop",
"device_fingerprint": "optional-for-mobile"
}

Response:

{
"token": "1|abcd...",
"token_type": "Bearer",
"user": {
"id": 42,
"name": "HR Admin",
"email": "hr@acme.com",
"roles": ["hr"],
"scopes": [{ "type": "organization", "organization_id": 1 }]
},
"expires_at": "2026-05-23T09:00:00Z"
}

Using the Token

Authorization: Bearer 1|abcd...

Mobile Device Binding

Mobile clients send X-Device-Fingerprint on every request. The server validates that the fingerprint matches a device row with status = approved for the authenticated employee; otherwise the request is rejected with 423 Locked.

Refresh / Logout

  • POST /api/v1/auth/logout — revokes the current token.
  • POST /api/v1/auth/logout-all — revokes every token for the user.
  • Tokens auto-expire after 30 days for web, 180 days for mobile (configurable).

Rate Limits

  • Login: 5 requests per minute per IP.
  • Ingestion: 30 requests per minute per employee (generous — offline buffers flush after reconnect).
  • Exports: 10 per hour per user.

Example: Curl

# Login
TOKEN=$(curl -sX POST https://api.example.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"hr@acme.com","password":"secret","device_name":"curl"}' \
| jq -r .token)

# Authenticated call
curl -H "Authorization: Bearer $TOKEN" \
https://api.example.com/api/v1/me