> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thena.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# User events

> Platform events related to user interactions and mentions

User events are published when users are mentioned in comments or when user-related activities occur. These events enable real-time notification systems and user engagement tracking. These events are delivered through the platform events system.

## Developer quickstart

### Minimal handler (mentions only)

```javascript theme={null}
app.post("/webhook/platform-events", async (req, res) => {
  const event = req.body;
  if (!event?.eventId || event?.eventType !== "user:mentioned") {
    return res.status(200).send("OK");
  }
  res.status(200).send("OK");

  await onUserMentioned(event.payload.user, event.metadata);
});
```

### Checklist

* Respect user notification preferences and quiet hours when sending alerts.
* Enrich notifications with context (linked entity, comment excerpt) for UX.
* De-duplicate multiple mentions in the same comment before notifying.

## Event types

### `user:mentioned`

Triggered when a user is mentioned in a comment across any entity type (tickets, account tasks, activities, or notes).

**Payload structure:**

```typescript theme={null}
interface UserMentionEventPayload {
  user: {
    id: string;
    email: string;
    name: string;
    userType: string;
    status: string;
    organization: {
      id: string;
      name: string | null;
    };
    teams: Array<{
      id: string;
      name: string;
    }>;
    metadata?: Record<string, unknown>;
  };
}
```

**Event metadata:**

```typescript theme={null}
interface MentionMetadata {
  mentionedUserId: string;
  mentionedByUserId: string;
  entityId: string;
  entityType: string; // "TICKET", "ACCOUNT_TASK", "ACCOUNT_ACTIVITY", "ACCOUNT_NOTE"
  commentId: string;
  timestamp: string;
  organizationId: string;
  teamId?: string; // Present for ticket mentions
}
```

## Event structure

User events follow the standard platform event structure:

```typescript theme={null}
interface UserEventEnvelope {
  eventId: string;
  eventType: string; // "user:mentioned"
  timestamp: string;
  orgId: string;
  actor: {
    id: string;
    type: string;
    email: string;
  };
  payload: UserMentionEventPayload;
  metadata: MentionMetadata;
}
```

## Mention context

### Entity types

Users can be mentioned in comments on different entity types:

#### Ticket mentions

* **Entity type**: `TICKET`
* **Additional context**: `teamId` is included in metadata
* **Common use cases**: Agent collaboration, customer escalation, knowledge sharing

#### Account task mentions

* **Entity type**: `ACCOUNT_TASK`
* **Context**: Task collaboration and assignment discussions
* **Common use cases**: Task handoffs, status updates, collaboration requests

#### Account activity mentions

* **Entity type**: `ACCOUNT_ACTIVITY`
* **Context**: Activity discussions and follow-ups
* **Common use cases**: Activity reviews, next steps planning

#### Account note mentions

* **Entity type**: `ACCOUNT_NOTE`
* **Context**: Note discussions and clarifications
* **Common use cases**: Knowledge sharing, note reviews, clarifications

## Event processing

### Mention detection

The system automatically detects mentions in comment content using patterns like:

* `@username`
* `@user.email`
* `@"Full Name"`

### Deduplication

Multiple users can be mentioned in a single comment, generating separate events for each mentioned user.

### Self-mention filtering

Users mentioning themselves may be filtered out based on the `ignoreSelf` flag in the comment metadata.

## Integration examples

### Real-time notification system

```javascript theme={null}
function handleUserMention(payload) {
  const { user, metadata } = payload;

  // Get mention context
  const context = getMentionContext(metadata.entityType, metadata.entityId);

  // Create notification
  const notification = {
    userId: user.id,
    type: 'mention',
    title: `You were mentioned by ${payload.actor.name}`,
    message: createMentionMessage(context, payload.actor),
    actionUrl: generateActionUrl(metadata),
    createdAt: new Date(payload.timestamp)
  };

  // Send real-time notification
  sendRealtimeNotification(user.id, notification);

  // Send email if user preferences allow
  if (await shouldSendEmailNotification(user.id, 'mention')) {
    sendMentionEmail(user, notification, context);
  }

  // Send mobile push notification
  if (await shouldSendPushNotification(user.id, 'mention')) {
    sendPushNotification(user.id, notification);
  }
}
```

### Mention analytics

```javascript theme={null}
function trackMentionMetrics(payload) {
  const { metadata } = payload;

  // Track mention frequency
  trackEvent("user_mentioned", {
    mentionedUserId: metadata.mentionedUserId,
    mentionedByUserId: metadata.mentionedByUserId,
    entityType: metadata.entityType,
    organizationId: metadata.organizationId,
    teamId: metadata.teamId,
    timestamp: metadata.timestamp,
  });

  // Update user engagement scores
  updateUserEngagement(metadata.mentionedUserId, {
    type: "mention_received",
    weight: 1,
  });

  updateUserEngagement(metadata.mentionedByUserId, {
    type: "mention_sent",
    weight: 0.5,
  });

  // Track cross-team collaboration
  if (metadata.teamId) {
    trackCrossTeamCollaboration(
      metadata.mentionedByUserId,
      metadata.mentionedUserId,
      metadata.teamId,
    );
  }
}
```

### Smart notification routing

```javascript theme={null}
function routeMentionNotification(payload) {
  const { user, metadata } = payload;

  // Check user availability
  const availability = await getUserAvailability(user.id);

  if (!availability.isAvailable) {
    // User is out of office or busy
    if (metadata.entityType === 'TICKET' && isPriorityTicket(metadata.entityId)) {
      // Route to team lead for high-priority tickets
      const teamLead = await getTeamLead(metadata.teamId);
      notifyTeamLead(teamLead, payload, 'user_unavailable');
    } else {
      // Queue notification for later
      queueNotificationForLater(user.id, payload, availability.returnTime);
    }
  } else {
    // User is available, send normal notification
    sendImmediateNotification(user.id, payload);
  }
}
```

### Mention context enhancement

```javascript theme={null}
function enhanceMentionContext(payload) {
  const { metadata } = payload;

  // Get rich context based on entity type
  let context = {};

  switch (metadata.entityType) {
    case 'TICKET':
      context = await getTicketContext(metadata.entityId);
      break;
    case 'ACCOUNT_TASK':
      context = await getAccountTaskContext(metadata.entityId);
      break;
    case 'ACCOUNT_ACTIVITY':
      context = await getAccountActivityContext(metadata.entityId);
      break;
    case 'ACCOUNT_NOTE':
      context = await getAccountNoteContext(metadata.entityId);
      break;
  }

  // Get comment context
  const comment = await getComment(metadata.commentId);

  // Create enhanced notification
  const enhancedPayload = {
    ...payload,
    context: {
      entity: context,
      comment: {
        id: comment.id,
        excerpt: truncateText(comment.content, 100),
        author: comment.author
      },
      urgency: calculateUrgency(context, comment),
      suggestedActions: generateSuggestedActions(context, comment)
    }
  };

  return enhancedPayload;
}
```

### User preference management

```javascript theme={null}
function handleMentionWithPreferences(payload) {
  const { user } = payload;

  // Get user notification preferences
  const preferences = await getUserNotificationPreferences(user.id);

  // Check if mentions are enabled
  if (!preferences.mentions.enabled) {
    logSkippedNotification(user.id, 'mentions_disabled');
    return;
  }

  // Check time-based preferences
  if (preferences.mentions.quietHours) {
    const now = new Date();
    const userTimezone = user.timezone || 'UTC';

    if (isInQuietHours(now, preferences.mentions.quietHours, userTimezone)) {
      queueNotificationForLater(user.id, payload,
        getNextActiveTime(preferences.mentions.quietHours, userTimezone));
      return;
    }
  }

  // Check entity-specific preferences
  const entityPrefs = preferences.mentions.entityTypes[payload.metadata.entityType];
  if (!entityPrefs?.enabled) {
    logSkippedNotification(user.id, `mentions_disabled_for_${payload.metadata.entityType}`);
    return;
  }

  // Process mention with user preferences applied
  processMentionWithPreferences(payload, preferences);
}
```

## Mention patterns and best practices

### Mention syntax support

The platform supports various mention formats:

```javascript theme={null}
// Standard username mention
@john.smith

// Email-based mention
@john.smith@company.com

// Display name mention (with quotes for spaces)
@"John Smith"

// Department/role mention (if supported)
@support-team
```

### Integration best practices

1. **Deduplication**: Handle duplicate mentions gracefully
2. **Rate limiting**: Implement rate limiting for mention notifications
3. **Context preservation**: Maintain mention context for better user experience
4. **Privacy**: Respect user privacy settings and availability status
5. **Fallback handling**: Handle cases where mentioned users don't exist

### Performance considerations

```javascript theme={null}
function optimizeMentionProcessing(payload) {
  // Batch process multiple mentions from same comment
  const mentionBatch = groupMentionsByComment(payload.metadata.commentId);

  // Pre-load user data for all mentions
  const userIds = mentionBatch.map(m => m.mentionedUserId);
  const users = await batchLoadUsers(userIds);

  // Pre-load preferences
  const preferences = await batchLoadPreferences(userIds);

  // Process all mentions with cached data
  mentionBatch.forEach(mention => {
    processMentionWithCache(mention, users, preferences);
  });
}
```

## Error handling

### Common error scenarios

```javascript theme={null}
function handleMentionErrors(payload, error) {
  switch (error.type) {
    case "USER_NOT_FOUND":
      // Mentioned user doesn't exist
      logInvalidMention(payload.metadata);
      notifyCommentAuthor("invalid_mention", payload.metadata);
      break;

    case "USER_DEACTIVATED":
      // Mentioned user is deactivated
      logDeactivatedUserMention(payload.metadata);
      // Don't send notification
      break;

    case "NOTIFICATION_SERVICE_DOWN":
      // Notification service unavailable
      queueMentionForRetry(payload);
      break;

    case "RATE_LIMIT_EXCEEDED":
      // Too many notifications for user
      queueMentionForLater(payload);
      break;

    default:
      logMentionError(payload, error);
      alertDevelopmentTeam("mention_processing_error", { payload, error });
  }
}
```

## Event frequency and scaling

### Frequency characteristics

User mention events can vary greatly in frequency:

* **Low-volume organizations**: Few mentions per day
* **High-collaboration teams**: Hundreds of mentions per hour
* **Customer support teams**: Spike during business hours

### Scaling considerations

1. **Batch processing**: Group mentions for efficient processing
2. **Async processing**: Handle mention notifications asynchronously
3. **Caching**: Cache user data and preferences for better performance
4. **Rate limiting**: Prevent notification spam
5. **Monitoring**: Track mention processing latency and success rates

## Future enhancements

Potential future enhancements to user events:

* **Smart mentions**: AI-suggested mentions based on context
* **Group mentions**: Mention entire teams or roles
* **Mention threads**: Track mention conversation threads
* **Mention analytics**: Advanced analytics for collaboration patterns
* **Custom mention actions**: Configurable actions when mentioned
