Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Paramount-Intelligence/HR_Monitoring_System/llms.txt

Use this file to discover all available pages before exploring further.

The realtime layer of the Workforce Intelligence OS combines a persistent WebSocket channel with REST endpoints that write to and read from that same event pipeline. Every connected client receives server-initiated events — new messages, meeting invites, presence changes, notification counts — without polling. All REST paths are prefixed with /api/v1. The WebSocket endpoint lives at /api/v1/ws.
The WebSocket endpoint does not accept a JWT via query string. Direct ?token= usage is rejected with close code 1008 (Policy Violation). You must first exchange a JWT for a short-lived WS ticket and pass that instead.

Obtaining a WebSocket Ticket

Before opening a WebSocket connection, the client must call the ticket-issuance endpoint with its JWT.

POST /api/v1/auth/ws-ticket

Issues a single-use, short-lived WebSocket connection ticket (TTL: 60 seconds). Auth: Any authenticated user (Authorization: Bearer <token>).
ticket
string
A URL-safe random string (32 bytes, base64-encoded). Pass this as the ticket query parameter when upgrading to WebSocket.
expires_in
integer
Seconds until the ticket expires. Always 60.
Example Request
POST /api/v1/auth/ws-ticket
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Response
{
  "ticket": "g7hK2mNpQrStUvWxYz0A1bCdEfGhIjKl",
  "expires_in": 60
}
Tickets are single-use and expire in 60 seconds. A ticket that has already been used or has expired is silently rejected and the WebSocket connection is closed with code 1008.

WebSocket Connection

GET /api/v1/ws

Upgrades the HTTP connection to a WebSocket session. Authentication is performed server-side by consuming the ticket before accepting the socket. Query Parameters:
ticket
string
required
Single-use WS ticket obtained from POST /api/v1/auth/ws-ticket.
platform
string
Client platform hint. Accepted values: web (default), mobile. Any other value is normalised to web.
Connection lifecycle:
  1. Server validates and consumes the ticket.
  2. On success, the user is marked online via OnlinePresenceService.
  3. Server sends an immediate connected event.
  4. Server sends a ping every 30 seconds — the client should respond with a pong message.
  5. On disconnect, the user’s presence record is updated to reflect the connection closure.
Rejection close codes:
CodeReason
1008Missing ticket, invalid ticket, expired ticket, inactive user
1011Internal server error during connection setup

JavaScript Connection Example

async function connectToWorkforceWS(jwtToken) {
  // Step 1: Issue a WS ticket
  const ticketRes = await fetch("/api/v1/auth/ws-ticket", {
    method: "POST",
    headers: { Authorization: `Bearer ${jwtToken}` },
  });
  const { ticket } = await ticketRes.json();

  // Step 2: Open the WebSocket with the ticket
  const ws = new WebSocket(
    `wss://api.example.com/api/v1/ws?ticket=${ticket}&platform=web`
  );

  ws.onopen = () => {
    console.log("[WS] Connection established");
  };

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    console.log("[WS] Event received:", msg.type, msg.payload);

    // Respond to server pings
    if (msg.type === "ping") {
      ws.send(JSON.stringify({ type: "pong" }));
    }
  };

  ws.onclose = (event) => {
    console.warn("[WS] Connection closed. Code:", event.code);
    // Implement exponential back-off reconnect here
  };

  ws.onerror = (error) => {
    console.error("[WS] Error:", error);
  };

  return ws;
}

Realtime Event Shape

All events delivered over the WebSocket follow the RealtimeEvent schema:
type
string
Event type identifier, e.g. connected, ping, new_message, notification_created.
event_id
string
UUID assigned to this event instance (useful for deduplication).
timestamp
string
ISO-8601 UTC timestamp of event emission.
payload
object
Event-specific data dictionary.
actor_id
string | null
UUID of the user who triggered the event, if applicable.
conversation_id
string | null
Associated conversation UUID, if applicable.
entity_type
string | null
Type of related entity, e.g. "meeting", "call", "task".
entity_id
string | null
UUID of the related entity.
Known event types:
Event TypeDescription
connectedSent immediately after a successful WS handshake
pingServer heartbeat — respond with { "type": "pong" }
pongServer response to a client-initiated ping
new_messageA new message was sent to one of the user’s conversations
message_updatedAn existing message was edited
message_deletedA message was soft-deleted
conversation_updatedA conversation’s metadata (title, settings) changed
conversation_participants_addedNew members were added to a group/channel
conversation_readA participant marked a conversation as read
notification_createdA new in-app notification was created for this user
notifications_count_updatedThe unread notification count changed
notification_readA specific notification was marked as read
announcement_createdA new announcement was published matching the user’s audience
meeting_createdThe user was invited to a new meeting
meeting_updatedA meeting the user is part of was updated
meeting_deletedA meeting was cancelled
meeting_rsvp_updatedA participant RSVP status changed
call_incomingAn inbound voice/video call is ringing
call_acceptedThe other party accepted the call
call_declinedThe other party declined the call
call_missedThe call timed out before being answered
call_endedThe call session was terminated
call_signalWebRTC ICE candidate / offer / answer signal

Presence

The presence system tracks whether a user is online, away, or offline. Presence state is maintained per-device and expires automatically. The default TTL for an online heartbeat is 90 seconds (configurable via ONLINE_PRESENCE_TTL_SECONDS).

POST /api/v1/presence/heartbeat

Refreshes the caller’s online presence state. Clients should call this on a regular interval (recommended: every 30–60 seconds) while the application is in the foreground. Auth: Any authenticated user.
device_id
string
required
Stable device or browser identifier (8–128 characters).
platform
string
required
Must be "web" or "mobile".
app_state
string
Optional foreground/background hint (max 32 chars), e.g. "active" or "background".
user_id
string
UUID of the caller.
online_state
string
online, away, or offline.
is_online
boolean
last_seen_at
string | null
ISO-8601 UTC timestamp.
platforms
array
List of platform strings ("web", "mobile") currently active for this user.
Example Request Body
{
  "device_id": "browser-abc-123",
  "platform": "web",
  "app_state": "active"
}
Example Response
{
  "user_id": "u1a2b3c4-...",
  "online_state": "online",
  "is_online": true,
  "last_seen_at": "2025-01-20T10:45:00Z",
  "platforms": ["web"]
}

POST /api/v1/presence/offline

Explicitly marks a specific device session as offline. Call this on intentional logout or app backgrounding. Auth: Any authenticated user.
device_id
string
required
The device ID to go offline for.
platform
string
required
"web" or "mobile".
online_state
string
Will be "offline" after a successful call.
is_online
boolean
Always false.
presence_status
string
User-set status label.
last_seen_at
string | null
ISO-8601 UTC timestamp of the final heartbeat.
platforms
array
Remaining active platforms after this device goes offline.

GET /api/v1/presence/users

Batch-fetches the online presence state for a set of users by UUID. Useful for rendering online indicators in conversation lists. Auth: Any authenticated user.
ids
string
required
Comma-separated list of user UUIDs, e.g. ids=uuid1,uuid2,uuid3.
users
object
Map of user_id (string)OnlinePresenceRead.
Presence state uses a 90-second TTL by default. A user with no heartbeat in the last 90 seconds transitions to away; beyond a further configurable threshold they become offline.

Notifications

In-app notifications are lightweight inbox items for each user. They are also emitted as notification_created WebSocket events when first written.

GET /api/v1/notifications

Returns up to limit notifications for the authenticated user, ordered newest-first. Auth: Any authenticated user.
limit
integer
Maximum notifications to return. Defaults to 50.
[]
array
Array of NotificationRead objects.

GET /api/v1/notifications/unread-count

Returns the count of unread notifications for the authenticated user. Auth: Any authenticated user.
count
integer
Number of unread notifications.

PATCH /api/v1/notifications/read-all

Marks all unread notifications for the authenticated user as read and emits a notifications_count_updated WebSocket event. Auth: Any authenticated user.
message
string
Confirmation message.

PATCH /api/v1/notifications/{notification_id}/read

Marks a specific notification as read and emits a notification_read WebSocket event. Auth: The notification’s owner only.
notification_id
string
required
UUID of the notification.
id
string
is_read
boolean
Always true after a successful call.
read_at
string
ISO-8601 UTC timestamp set at read time.

Notification Preferences & Push Delivery

The notification preferences system allows users to control which notification categories they receive and via which channels (in-app, email, web push, mobile push).

GET /api/v1/notifications/preferences

Returns the authenticated user’s notification preferences. Auth: Any authenticated user.
user_id
string
UUID of the user.
email_notifications
boolean
Whether email delivery is enabled.
push_notifications
boolean
Whether push delivery is enabled.

PATCH /api/v1/notifications/preferences

Update the authenticated user’s notification preferences. Only provided fields are changed. Auth: Any authenticated user.
email_notifications
boolean
Enable or disable email notification delivery.
push_notifications
boolean
Enable or disable push notification delivery.

GET /api/v1/notifications/push-public-key

Returns the server’s VAPID public key for Web Push subscription registration. Auth: None required.
public_key
string | null
VAPID public key string, or null if Web Push is not configured on this server.
configured
boolean
Whether VAPID credentials are configured on the server.

POST /api/v1/notifications/push-subscriptions

Registers a browser Web Push subscription for the authenticated user. If a subscription with the same endpoint already exists it is updated in place. Auth: Any authenticated user.
endpoint
string
required
Browser Push Service endpoint URL.
p256dh
string
required
Client public key for payload encryption.
auth
string
required
Auth secret for payload encryption.
user_agent
string
Optional browser user-agent string for identification.
message
string
Confirmation — "Push subscription registered." or "Push subscription updated."
Returns 503 Service Unavailable if VAPID credentials are not configured on the server.

DELETE /api/v1/notifications/push-subscriptions

Revokes (soft-deletes) a Web Push subscription. The request body uses the same schema as the registration endpoint. Auth: Any authenticated user.
endpoint
string
required
Endpoint URL of the subscription to revoke.
p256dh
string
required
Client public key.
auth
string
required
Auth secret.
message
string
Always "Push subscription removed." on success.

POST /api/v1/notifications/push/test

Sends a test Web Push notification to all active browser subscriptions for the authenticated user. Auth: Any authenticated user.
configured
boolean
Whether VAPID is configured.
message
string
Human-readable outcome description.
subscriptions
integer
Number of active subscriptions found.
attempted
integer
Number of push attempts made.
sent
integer
Number of successful deliveries.
failed
integer
Number of failed deliveries.

Mobile Push Device Tokens

POST /api/v1/notifications/device-tokens

Registers or refreshes the current user’s Expo push token for mobile push delivery. If the token is already registered to another user it is reassigned. Auth: Any authenticated user.
expo_push_token
string
required
Expo push token string in ExponentPushToken[...] or ExpoPushToken[...] format.
platform
string
"android" or "ios". Any other value is stored as "unknown".
device_name
string
Human-readable device name.
device_id
string
Stable device identifier.
app_version
string
App version string.
build_version
string
App build number.
environment
string
One of development, preview, production. Defaults to development.
id
string
UUID of the device token record.
expo_push_token
string
platform
string
is_active
boolean
Always true after successful registration.

DELETE /api/v1/notifications/device-tokens/current

Deactivates the current user’s active device token(s) on logout. If expo_push_token is provided in the body, only that specific token is revoked; otherwise all active tokens for the user are revoked. Auth: Any authenticated user.
expo_push_token
string
Specific token to revoke. Omit to revoke all active tokens for the user.
message
string
Always "Device token unregistered." on success.

DELETE /api/v1/notifications/device-tokens/{token_id}

Deactivates a specific device token by UUID. The token must be owned by the authenticated user. Auth: Any authenticated user. Must own the token.
token_id
string
required
UUID of the device token record to revoke.
message
string
Always "Device token unregistered." on success.

Messaging

Conversations support direct (1-to-1), group, channel, and context-thread types (task, project, meeting, support, EOD, approval). All conversation-scoped actions require the caller to be a participant.

GET /api/v1/messages/conversations

Returns conversations the authenticated user participates in, ordered by most recently updated. Auth: Any authenticated user.
type
string
Filter by conversation type: direct, group, channel, task_thread, etc.
Title substring search.
unread_only
boolean
When true, returns only conversations with unread messages. Defaults to false.
limit
integer
Maximum results. Defaults to 50, max 100.
offset
integer
Pagination offset. Defaults to 0.
[]
array
Array of ConversationRead objects including participant list, last message preview, and unread count.

POST /api/v1/messages/conversations

Creates a new direct, group, or channel conversation. If a direct conversation between the same two users already exists, it is returned instead of creating a duplicate. Auth: Any authenticated user.
type
string
required
Conversation type: direct, group, or channel.
participant_ids
array
required
List of user UUIDs to include. For direct conversations, provide exactly one other user ID.
title
string
Required for group and channel types. Auto-generated if omitted.

GET /api/v1/messages/conversations/{conversation_id}

Fetch details of a single conversation including participants and last message. Auth: Must be a participant.

GET /api/v1/messages/conversations/{conversation_id}/messages

Retrieves messages in a conversation in chronological order. Automatically marks fetched messages as delivered for the caller. Auth: Must be a participant.
limit
integer
Defaults to 50, max 100.
before
string
ISO-8601 datetime cursor — returns messages created before this timestamp (for pagination).

POST /api/v1/messages/conversations/{conversation_id}/messages

Sends a new message to a conversation. Triggers new_message and conversation_updated WebSocket events for all participants. Auth: Must be a participant. Channel posts require OWNER or ADMIN participant role.
body
string
Plain-text message body. Required unless attachment_ids is provided.
body_html
string
Optional sanitised HTML body (rich text). Server-side sanitisation is applied.
mentioned_user_ids
array
List of user UUIDs to mention. Only users with access to the conversation can be mentioned.
reply_to_message_id
string
UUID of the message being replied to — must belong to the same conversation.
attachment_ids
array
UUIDs of pre-uploaded MessageAttachment records to attach.
Example Request Body
{
  "body": "Can you review the updated spec?",
  "mentioned_user_ids": ["u9v8w7x6-..."],
  "reply_to_message_id": null
}
Upload attachments first via POST /api/v1/messages/conversations/{conversation_id}/attachments (multipart, max 5 files, 10 MB each), then reference the returned IDs in the message body.

GET /api/v1/messages/unread-count

Returns the total number of unread conversations, unread messages, and unread mentions for the authenticated user.
unread_conversations
integer
unread_messages
integer
mentions
integer

Meetings

Meetings are calendar-style invitations with RSVP state. Creating a meeting automatically sends meeting_created WebSocket events and in-app notifications to all invited participants.

GET /api/v1/meetings

Returns meetings visible to the authenticated user — those they organise or are invited to. Auth: Any authenticated user. Admins and HR may pass scope=all to view all organisation meetings.
scope
string
Pass all to retrieve all meetings (Admin/HR only).
[]
array
Array of MeetingRead objects.

POST /api/v1/meetings

Creates a new meeting and sends invitations to all specified participants. The organiser is automatically added as an accepted participant. Auth: Any authenticated user.
title
string
required
Meeting title.
start_at
string
required
ISO-8601 UTC start datetime.
end_at
string
required
ISO-8601 UTC end datetime.
participants
array
required
List of participant user UUIDs to invite. Inactive users are rejected with 400.
description
string
Optional meeting agenda or description.
External video call URL.
location
string
Physical meeting location.
Example Request Body
{
  "title": "Q1 Sprint Planning",
  "start_at": "2025-02-03T10:00:00Z",
  "end_at": "2025-02-03T11:30:00Z",
  "participants": ["u1a2b3c4-...", "u5d6e7f8-..."],
  "meeting_link": "https://meet.example.com/sprint-q1",
  "description": "Planning session for Q1 deliverables"
}
Example Response
{
  "id": "m1n2o3p4-...",
  "title": "Q1 Sprint Planning",
  "organizer_id": "admin-uuid-...",
  "start_at": "2025-02-03T10:00:00Z",
  "end_at": "2025-02-03T11:30:00Z",
  "meeting_link": "https://meet.example.com/sprint-q1",
  "location": null,
  "status": "scheduled"
}

GET /api/v1/meetings/upcoming

Returns future scheduled meetings for the authenticated user, ordered by start time ascending. Auth: Any authenticated user.
[]
array
Array of MeetingRead objects with status = "scheduled" and start_at >= now.

GET /api/v1/meetings/today

Returns all meetings scheduled for today in the Asia/Karachi timezone. Auth: Any authenticated user. Pass scope=all for Admin/HR to see all org meetings.
scope
string
Pass all to retrieve all org meetings today (Admin/HR only).

GET /api/v1/meetings/{meeting_id}

Returns details of a single meeting. The caller must be the organiser, a participant, or an Admin/HR user. Auth: Any authenticated user with access to the meeting.
meeting_id
string
required
UUID of the meeting.
id
string
UUID of the meeting.
title
string
organizer_id
string
start_at
string
ISO-8601 UTC datetime.
end_at
string
ISO-8601 UTC datetime.
status
string
scheduled or cancelled.

POST /api/v1/meetings/{meeting_id}/cancel

Cancels a meeting, setting its status to "cancelled". Sends meeting_deleted WebSocket events and in-app notifications to all participants. Auth: Meeting organiser or ADMIN role required.
meeting_id
string
required
UUID of the meeting to cancel.
id
string
status
string
Always "cancelled" after a successful call.
Cancelled meetings cannot be reopened via the API. Participants will receive a meeting_deleted WebSocket event and an in-app notification.

POST /api/v1/meetings/{meeting_id}/respond

RSVP to a meeting invitation. Auth: Must be a participant.
meeting_id
string
required
UUID of the meeting.
response_status
string
required
One of: accepted, declined, tentative.
id
string
UUID of the updated meeting.
status
string
Meeting status (unchanged by RSVP).
Responding to a cancelled meeting returns 400 Bad Request. A meeting_rsvp_updated WebSocket event is emitted to the organiser on every RSVP update.

Error Reference

HTTP StatusError CodeReason
401AUTH_ERRORMissing or invalid JWT
403PERMISSION_ERRORNot a participant, not the organiser, or insufficient role
404NOT_FOUNDConversation, message, notification, or meeting not found
503SERVICE_UNAVAILABLEWeb Push not configured (VAPID missing)
1008 (WS)WS ticket missing, invalid, expired, or user inactive
1011 (WS)Internal server error during WS setup

Build docs developers (and LLMs) love