Skip to main content
The Notifications API allows you to manage user notifications for repository events.

Overview

Notifications are generated for events like:
  • Pull request activity (comments, reviews, merges)
  • Issue updates
  • Mentions
  • Repository access changes
All notification endpoints require authentication.

Endpoints

List Notifications

Get notifications for the authenticated user.
trpc.notifications.list.query({
  unreadOnly?: boolean,  // Filter to unread only (default: false)
  limit?: number,        // Max results (1-100, default: 50)
  offset?: number        // Pagination offset (default: 0)
})
Response:
{
  id: string;
  type: 'pr_comment' | 'pr_review' | 'pr_merged' | 'issue_comment' | 'mention' | 'access_granted';
  title: string;
  message: string;
  repoId: string;
  resourceId?: string;    // PR/Issue ID if applicable
  resourceType?: string;  // 'pull_request' | 'issue'
  isRead: boolean;
  createdAt: Date;
}[]
Example:
const notifications = await trpc.notifications.list.query({
  unreadOnly: true,
  limit: 20
});

for (const n of notifications) {
  console.log(`${n.isRead ? '○' : '●'} ${n.title}`);
}

Get Unread Count

Get the count of unread notifications.
trpc.notifications.unreadCount.query()
Response:
{
  count: number;
}
Example:
const { count } = await trpc.notifications.unreadCount.query();
console.log(`You have ${count} unread notifications`);

Mark as Read

Mark a specific notification as read.
trpc.notifications.markAsRead.mutate({
  id: string  // Notification UUID
})
Response:
{
  id: string;
  isRead: true;
  readAt: Date;
}
Example:
await trpc.notifications.markAsRead.mutate({
  id: 'a1b2c3d4-...'
});

Mark All as Read

Mark all notifications as read.
trpc.notifications.markAllAsRead.mutate()
Response:
{
  count: number;  // Number of notifications marked
}
Example:
const { count } = await trpc.notifications.markAllAsRead.mutate();
console.log(`Marked ${count} notifications as read`);

Delete Notification

Delete a specific notification.
trpc.notifications.delete.mutate({
  id: string  // Notification UUID
})
Response:
{
  success: boolean;
}

Delete All Notifications

Delete all notifications for the current user.
trpc.notifications.deleteAll.mutate()
Response:
{
  count: number;  // Number deleted
}

Notification Types

TypeDescription
pr_commentComment on a pull request
pr_reviewReview submitted on a PR
pr_mergedPull request was merged
pr_closedPull request was closed
issue_commentComment on an issue
issue_closedIssue was closed
mentionYou were @mentioned
access_grantedRepository access granted
access_revokedRepository access revoked

Usage Examples

React Component

import { trpc } from '@/lib/trpc';

function NotificationBell() {
  const { data: count } = trpc.notifications.unreadCount.useQuery();
  const { data: notifications } = trpc.notifications.list.useQuery({
    unreadOnly: true,
    limit: 5
  });

  const markRead = trpc.notifications.markAsRead.useMutation();
  const markAllRead = trpc.notifications.markAllAsRead.useMutation();

  return (
    <div>
      <button>
        🔔 {count?.count > 0 && <span>{count.count}</span>}
      </button>
      
      <div className="dropdown">
        {notifications?.map(n => (
          <div 
            key={n.id}
            onClick={() => markRead.mutate({ id: n.id })}
          >
            {n.title}
          </div>
        ))}
        
        <button onClick={() => markAllRead.mutate()}>
          Mark all as read
        </button>
      </div>
    </div>
  );
}

CLI Integration

import { createTRPCClient } from './api/client';

async function showNotifications() {
  const client = createTRPCClient();
  
  const notifications = await client.notifications.list.query({
    unreadOnly: true
  });

  if (notifications.length === 0) {
    console.log('No unread notifications');
    return;
  }

  console.log(`\n📬 ${notifications.length} unread notifications:\n`);
  
  for (const n of notifications) {
    const icon = n.type.startsWith('pr_') ? '🔀' : 
                 n.type.startsWith('issue_') ? '📋' : '💬';
    console.log(`  ${icon} ${n.title}`);
    console.log(`     ${n.message}`);
    console.log();
  }
}

Error Handling

Error CodeDescription
UNAUTHORIZEDNot authenticated
NOT_FOUNDNotification not found
FORBIDDENCannot access this notification
try {
  await trpc.notifications.markAsRead.mutate({ id: 'invalid' });
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.log('Notification not found');
  }
}