Skip to main content
All endpoints require a valid Bearer token. State-mutating requests (POST, PUT, DELETE) must include a csrf_token field — obtain one from GET /api/security/csrf-token. PropOps supports five account types:
IDType
1Staff
2Agent
3Landlord
4Tenant
5Contractor
Fields containing personal data (first_name, last_name, email) are encrypted at rest using XSalsa20-Poly1305. They are transparently decrypted in API responses.

Profile

Get profile

GET /api/users/profile Returns the authenticated user’s profile. To retrieve another user’s profile (staff only), pass user_uuid as a query parameter. Required permission: api.users.users.manage
curl -X GET "https://propops.yourcompany.com/api/users/users?action=get_user&uuid=660e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": {
    "ID": 1,
    "uuid": "660e8400-e29b-41d4-a716-446655440001",
    "first_name": "User_001",
    "last_name": "Surname_001",
    "email": "user001@example.com",
    "phone": "07700000001",
    "account_type_id": 1,
    "account_type_name": "Staff",
    "account_status_id": 1,
    "account_status_name": "Active",
    "branch_id": 1,
    "role_id": 2,
    "created_at": "2024-01-01T09:00:00Z"
  },
  "message": "Operation completed successfully"
}

Update profile

PUT /api/users/profile Update profile fields for a user. You can update your own profile; updating another user’s profile requires staff privileges. Required permission: api.users.users.manage
user_uuid
string
required
UUID of the user to update.
first_name
string
Updated first name.
last_name
string
Updated last name.
phone
string
Updated phone number.
branch_id
integer
Branch assignment (staff-only field).
role_id
integer
Role assignment. Subject to privilege-level hierarchy — you cannot assign a role above your own level.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/users/users" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action":"update","user_uuid":"660e8400-e29b-41d4-a716-446655440001","phone":"07712345678","csrf_token":"<csrf-token>"}'
{
  "success": true,
  "message": "Profile updated successfully"
}

Permissions

The permissions endpoint returns the calling user’s own permission map. It does not accept a user UUID or action parameter.

List permissions

GET /api/users/permissions Returns the authenticated user’s permission map, role, and account type. No additional query parameters are required — the endpoint always returns the calling user’s own permissions.
curl -X GET "https://propops.yourcompany.com/api/users/permissions" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "account_type_id": 1,
  "account_type": "Staff",
  "permissions": {
    "api.jobs.manage.manage": true,
    "api.jobs.case-notes.manage": true
  },
  "role": {
    "id": 2,
    "name": "Manager"
  }
}

Update permissions

PUT /api/users/permissions Grant, revoke, or completely sync the permissions for a user. Required permission: api.users.permissions.manage
action
string
required
grant, revoke, or sync. The sync action replaces the user’s full permission set with the provided list.
user_uuid
string
required
UUID of the user.
permission_keys
array
required
Array of permission key strings to grant or revoke.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/users/permissions" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action":"grant","user_uuid":"660e8400-e29b-41d4-a716-446655440001","permission_keys":["api.jobs.manage.manage","api.financial.invoices.manage"],"csrf_token":"<csrf-token>"}'

Notification Preferences

Get notification preferences

GET /api/users/notification-settings Returns the notification channel preferences for the specified user. Required permission: api.users.notification_settings.manage
uuid
string
required
UUID of the user whose preferences to retrieve.
curl -X GET "https://propops.yourcompany.com/api/users/notification-settings?uuid=660e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "email_notifications": true,
  "desktop_notifications": true
}

Update notification preferences

POST /api/users/notification-settings Required permission: api.users.notification_settings.manage
uuid
string
required
UUID of the user whose preferences to update.
email_notifications
boolean
Enable or disable email notifications.
desktop_notifications
boolean
Enable or disable desktop notifications.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/users/notification-settings" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"uuid":"660e8400-e29b-41d4-a716-446655440001","email_notifications":true,"desktop_notifications":false,"csrf_token":"<csrf-token>"}'

Avatar

Get avatar

GET /api/users/avatar Serves the avatar image for a user. Returns the image binary (SVG fallback if no avatar is set). Required permission: Authenticated session (staff may view other users’ avatars).
user
string
UUID of the user whose avatar to retrieve (legacy parameter name).
uuid
string
UUID of the user whose avatar to retrieve. Omit to serve the authenticated user’s own avatar.
size
string
Thumbnail size: small (48 px), medium (96 px), large (200 px), or original. Defaults to original.
curl -X GET "https://propops.yourcompany.com/api/users/avatar?uuid=660e8400-e29b-41d4-a716-446655440001&size=medium" \
  -H "Authorization: Bearer <token>"

Email Verification

Manage email verification

POST /api/users/email-verification Perform staff-initiated email verification actions on a user account. Requires authentication (staff only). Required permission: api.users.email_verification.view
action
string
required
Action to perform: send_activation sends a verification code email; unverify_email marks the email as unverified; change_email_and_send_verification updates the email address and sends a verification code.
target_uuid
string
required
UUID of the user to act on.
new_email
string
Required only when action is change_email_and_send_verification. The new email address to set.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/users/email-verification" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action":"send_activation","target_uuid":"660e8400-e29b-41d4-a716-446655440001","csrf_token":"<csrf-token>"}'
{
  "success": true,
  "message": "Verification code email sent to user@example.com. The user can complete verification at /guard/verify."
}

Sessions

List active sessions

GET /api/users/sessions Returns all active sessions for the authenticated user, including the current session. Required permission: Authenticated session (no additional permission required for own sessions).
curl -X GET "https://propops.yourcompany.com/api/security/sessions?action=get_active_sessions" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    {
      "session_id": "sess_001",
      "user_id": 1,
      "ip_address": "203.0.113.1",
      "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      "last_activity": "2024-06-01T15:00:00Z",
      "is_current": true
    },
    {
      "session_id": "sess_002",
      "user_id": 1,
      "ip_address": "203.0.113.5",
      "user_agent": "PropOps Desktop/2.0 Electron",
      "last_activity": "2024-05-30T09:00:00Z",
      "is_current": false
    }
  ],
  "message": "Operation completed successfully"
}

Revoke a session

DELETE /api/users/sessions Terminates a specific session. The session is immediately added to the blacklist and cannot be resumed.
To revoke sessions for another user you need the api.security.sessions.terminate permission. This is a staff-only operation.
action
string
required
Must be terminate.
session_id
string
required
ID of the session to revoke.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/security/sessions" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action":"terminate","session_id":"sess_002","csrf_token":"<csrf-token>"}'
{
  "success": true,
  "message": "Session terminated"
}

Admin User Management

The following endpoints are available to staff accounts with the api.admin.users.manage permission. They allow administrators to create, update, and deactivate accounts across all account types.
MethodEndpointDescription
GET/api/admin/usersList all accounts with filters (account type, status, branch)
POST/api/admin/usersCreate a new account
PUT/api/admin/usersUpdate account details, status, or branch assignment
DELETE/api/admin/usersDeactivate or delete an account

Admin roles management

MethodEndpointDescription
GET/api/admin/rolesList all roles and their assigned permissions
POST/api/admin/rolesCreate a new role
PUT/api/admin/rolesUpdate a role’s name or permission set
DELETE/api/admin/rolesRemove a role

System settings

MethodEndpointDescription
GET/api/admin/settingsRead current system settings
PUT/api/admin/settingsUpdate system settings (VAT rate, notification toggles, branding, etc.)
Admin endpoints require staff-level access. The privilege-level hierarchy applies — you cannot modify accounts or roles at a higher privilege level than your own.

Appearance Settings

Get appearance settings

GET /api/users/appearance Returns the authenticated user’s appearance preferences — dashboard greeting style and KPI band background theme. Required permission: api.users.appearance.manage
uuid
string
User UUID. Omit to retrieve your own preferences.
curl -X GET "https://propops.yourcompany.com/api/users/appearance" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": {
    "greeting_style": "formal",
    "kpi_background": "gradient_blue"
  },
  "message": "Operation completed successfully"
}

Update appearance settings

POST /api/users/appearance Updates the appearance preferences for the authenticated user. Required permission: api.users.appearance.manage
Requires CSRF token.
uuid
string
User UUID. Omit to update your own preferences.
greeting_style
string
Dashboard greeting style: formal, casual, or none.
kpi_background
string
KPI band background theme key (e.g. gradient_blue, solid_dark, minimal).
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/users/appearance" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"greeting_style": "casual", "kpi_background": "gradient_blue", "csrf_token": "<csrf-token>"}'
{
  "success": true,
  "message": "Appearance settings updated"
}

Dashboard Widget Preferences

Get widget preferences

GET /api/users/dashboard-widget-preferences Returns the saved widget visibility and ordering preferences for the authenticated staff user’s dashboard. Required permission: Authenticated staff user (no additional permission required)
curl -X GET "https://propops.yourcompany.com/api/users/dashboard-widget-preferences" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    { "id": "new_jobs",      "visible": true,  "order": 1 },
    { "id": "pinned_jobs",   "visible": true,  "order": 2 },
    { "id": "recall",        "visible": false, "order": 3 },
    { "id": "booked_today",  "visible": true,  "order": 4 }
  ],
  "message": "Operation completed successfully"
}

Save widget preferences

POST /api/users/dashboard-widget-preferences Saves the widget visibility and ordering for the authenticated staff user. Required permission: Authenticated staff user
Requires CSRF token.
widgets
array
required
Array of widget configuration objects, each with id (string), visible (boolean), and order (integer).
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/users/dashboard-widget-preferences" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "widgets": [
      { "id": "new_jobs",     "visible": true,  "order": 1 },
      { "id": "pinned_jobs",  "visible": true,  "order": 2 },
      { "id": "recall",       "visible": false, "order": 3 }
    ],
    "csrf_token": "<csrf-token>"
  }'
{
  "success": true,
  "message": "Widget preferences saved"
}

User Status & Presence

Get online users

GET /api/users/user-status Returns all users who have been active within the last 30 minutes. Used by the online-users widget and presence indicators throughout the platform. Required permission: api.users.user_status.view
curl -X GET "https://propops.yourcompany.com/api/users/user-status" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    {
      "uuid": "660e8400-e29b-41d4-a716-446655440010",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane.smith@yourcompany.com",
      "account_type": "Staff",
      "last_active": "2024-06-14T10:58:00Z",
      "is_online": true
    }
  ],
  "count": 7,
  "message": "Operation completed successfully"
}

Set user status

POST /api/users/user-status Manually sets the authenticated user’s presence status. Required permission: api.users.user_status.view
Requires CSRF token.
action
string
required
Must be set.
status
string
required
Presence status: online, away, or offline.
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/users/user-status" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action": "set", "status": "away", "csrf_token": "<csrf-token>"}'
{
  "success": true,
  "message": "Status updated"
}

User Profile Popover

Get user profile card

GET /api/users/user-profile-popover?uuid=<uuid> Returns a compact profile card for a user — name, account type, branch, avatar, and recent activity. Used by inline popovers when hovering over user names throughout the platform. Required permission: Authenticated staff user (no additional permission)
uuid
string
required
UUID of the user to retrieve.
curl -X GET "https://propops.yourcompany.com/api/users/user-profile-popover?uuid=660e8400-e29b-41d4-a716-446655440010" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": {
    "uuid": "660e8400-e29b-41d4-a716-446655440010",
    "full_name": "Jane Smith",
    "account_type": "Staff",
    "branch_name": "London South",
    "avatar_url": "https://propops.yourcompany.com/uploads/avatars/660e8400.jpg",
    "last_active": "2024-06-14T10:58:00Z",
    "jobs_assigned": 12
  },
  "message": "Operation completed successfully"
}

Force Logout

Force-logout a user

POST /api/users/logout-user Administratively terminates all sessions for a specified user and prevents them from logging back in until the force-logout is cleared. Creates an audit log entry with the reason. Required permission: api.users.logout_user.manage
Account types: Staff only
Requires CSRF token.
uuid
string
required
UUID of the user to force-logout.
reason
string
Optional reason for the forced logout (stored in the audit log).
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/users/logout-user" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "uuid": "660e8400-e29b-41d4-a716-446655440010",
    "reason": "Account under investigation",
    "csrf_token": "<csrf-token>"
  }'
{
  "success": true,
  "message": "User logged out and all sessions terminated"
}