Notification API
GraphQL operations for the notification system -- querying notifications, managing read state, updating preferences, and subscribing to real-time events. All operations require JWT authentication.
Queries
myNotifications
Paginated, filtered notification list for the current user.
query MyNotifications($input: GetNotificationsInput) {
myNotifications(input: $input) {
notifications {
id
type
category
priority
title
message
actionUrl
status
readAt
channels
companyId
createdAt
}
total
hasMore
}
}
Input fields:
| Field | Type | Default | Description |
|---|---|---|---|
status | NotificationStatus | -- | Filter: UNREAD, READ, ARCHIVED, DISMISSED |
category | NotificationCategory | -- | Filter by category |
companyId | ID | -- | Filter by company context |
limit | Int | 20 | Page size (max 100) |
offset | Int | 0 | Pagination offset |
includeExpired | Boolean | false | Include expired notifications |
unreadNotificationCount
Returns the number of unread notifications, optionally scoped to a company.
query UnreadCount($companyId: ID) {
unreadNotificationCount(companyId: $companyId) {
count
companyId
}
}
myNotificationPreferences / companyNotificationPreferences
Returns user-level or company-specific notification preferences.
query Preferences {
myNotificationPreferences {
enableEmailNotifications
enableInAppNotifications
enablePushNotifications
notifyOnJobApplications
notifyOnInterviews
notifyOnInvitations
notifyOnBillingEvents
notifyOnMatchingJobs
enableDailyDigest
enableWeeklyDigest
doNotDisturbEnabled
doNotDisturbStart
doNotDisturbEnd
}
}
Mutations
| Operation | Description |
|---|---|
markNotificationAsRead(notificationId) | Mark a single notification as read |
markAllNotificationsAsRead(input?) | Mark all notifications as read; optionally filter by companyId or notificationIds |
deleteNotification(notificationId) | Permanently delete a notification |
archiveNotification(notificationId) | Move a notification to archived status |
dismissNotification(notificationId) | Dismiss a notification |
recordNotificationClick(notificationId) | Record a click (also marks as read) |
updateNotificationPreferences(input) | Update user-level notification preferences |
updateCompanyNotificationPreferences(input) | Update preferences for a specific company context |
All mutations return { success: Boolean, message: String } or the updated preference object.
Subscriptions
Two WebSocket subscriptions for real-time notification updates. Both filter by the authenticated user's ID.
notificationCreated
Fires when a new notification is created for the current user.
subscription {
notificationCreated {
id
type
category
priority
title
message
actionUrl
companyId
channels
createdAt
}
}
unreadCountChanged
Fires when the unread count changes, optionally scoped to a company.
subscription UnreadCountChanged($companyId: ID) {
unreadCountChanged(companyId: $companyId) {
count
companyId
}
}
Notification Types
The NotificationType enum covers 45 types across nine categories:
| Category | Types |
|---|---|
| RECRUITMENT | JOB_APPLICATION_RECEIVED, JOB_APPLICATION_VIEWED, JOB_APPLICATION_WITHDRAWN, JOB_CLOSED, INTERVIEW_SCHEDULED, INTERVIEW_REMINDER, INTERVIEW_COMPLETED, INTERVIEW_PREP, PIPELINE_STATUS_CHANGED, CANDIDATE_HIRED, CANDIDATE_REJECTED |
| COLLABORATION | TALENT_SHARED, TALENT_UNSHARED, INVITATION_RECEIVED, INVITATION_ACCEPTED, INVITATION_DECLINED, CONNECTION_REQUEST_RECEIVED, CONNECTION_REQUEST_ACCEPTED, JOB_SEEKER_INVITATION_RECEIVED, JOB_SEEKER_INVITATION_ACCEPTED, JOB_SEEKER_INVITATION_DECLINED, PERMISSION_CHANGED, RESOURCE_SHARED |
| BILLING | SUBSCRIPTION_CREATED, SUBSCRIPTION_RENEWED, SUBSCRIPTION_EXPIRING, SUBSCRIPTION_EXPIRED, SUBSCRIPTION_CANCELLED, PAYMENT_SUCCEEDED, PAYMENT_FAILED, INVOICE_GENERATED, INVOICE_PAID |
| MATCHING | HIGH_MATCH_TALENT_FOUND, JOB_MATCH_FOUND, RECOMMENDED_TALENT |
| MESSAGING | MESSAGE_RECEIVED, MESSAGE_MENTION |
| USER_COMPANY | MEETING_SCHEDULED, MEETING_REMINDER, MEETING_RESCHEDULED, MEETING_CANCELLED |
| SYSTEM | SYSTEM_UPDATE, MAINTENANCE_SCHEDULED, FEATURE_ANNOUNCEMENT, SECURITY_ALERT |
| SUPPORT | SUPPORT_TICKET_CREATED, SUPPORT_TICKET_REPLY |
Priority levels: LOW (in-app only), NORMAL (in-app + email), HIGH (+ push), URGENT (all channels including SMS).
MESSAGE_MENTION
The MESSAGE_MENTION type is created when a user is @mentioned in a group chat message. It differs from MESSAGE_RECEIVED in two key ways:
- Priority is HIGH — ensuring push notification delivery, versus NORMAL for regular messages
- Bypasses mute and notification toggle — mentioned users always receive the notification, even if they have muted the conversation or disabled notifications for it
The notification metadata includes a mentioned: true flag for frontend differentiation. The actionUrl links directly to the conversation: /company/messages/{conversationId}.
| Field | Value |
|---|---|
type | MESSAGE_MENTION |
category | MESSAGING |
priority | HIGH |
resourceType | CONVERSATION |
resourceId | Conversation ID |
metadata.messageId | The message containing the mention |
metadata.senderId | User who wrote the message |
metadata.senderName | Display name of the sender |
metadata.mentioned | true |
Frontend Polling Pattern
The frontend uses polling rather than WebSocket subscriptions for notification counts:
const { data } = useQuery(UNREAD_NOTIFICATION_COUNT, {
pollInterval: 30000, // 30-second interval
});
// Update document title with badge
useEffect(() => {
const count = data?.unreadNotificationCount?.count || 0;
document.title = count > 0 ? `(${count}) AiQlick` : 'AiQlick';
}, [data]);
Company-specific preferences override user-level defaults. When a companyId is provided to updateCompanyNotificationPreferences, those settings take priority over the user's global preferences for notifications in that company context.