Overview
The Notifications API allows you to retrieve and manage user notifications for video views, comments, reactions, and replies.
Endpoints
Get Notifications
Retrieve all notifications for the authenticated user.
Bearer token for authentication
Response
Array of notification objects
Record of notification counts by type
Example Request
curl -X GET "https://cap.so/api/notifications" \
-H "Authorization: Bearer <token>"
Example Response
{
"notifications": [
{
"id": "notif_123",
"type": "comment",
"videoId": "vid_456",
"author": {
"id": "user_789",
"name": "John Doe",
"avatar": "https://example.com/avatar.jpg"
},
"comment": {
"id": "comment_321",
"content": "Great video!"
},
"readAt": null,
"createdAt": "2024-02-28T12:00:00Z"
},
{
"id": "notif_124",
"type": "view",
"videoId": "vid_456",
"author": {
"id": "user_790",
"name": "Jane Smith",
"avatar": null
},
"readAt": "2024-02-28T13:00:00Z",
"createdAt": "2024-02-28T12:30:00Z"
}
],
"count": {
"comment": 5,
"view": 23,
"reaction": 8,
"reply": 2
}
}
Notification Types
Notifications can be one of four types:
View Notification
Someone viewed your video.
{
type: "view",
videoId: string,
author: NotificationAuthor,
id: string,
readAt: Date | null,
createdAt: Date
}
Someone commented on your video.
{
type: "comment",
videoId: string,
author: NotificationAuthor,
comment: {
id: string,
content: string
},
id: string,
readAt: Date | null,
createdAt: Date
}
Reaction Notification
Someone reacted to your video comment.
{
type: "reaction",
videoId: string,
author: NotificationAuthor,
comment: {
id: string,
content: string
},
id: string,
readAt: Date | null,
createdAt: Date
}
Reply Notification
Someone replied to your comment.
{
type: "reply",
videoId: string,
author: NotificationAuthor,
comment: {
id: string,
content: string
},
id: string,
readAt: Date | null,
createdAt: Date
}
Notification Schema
NotificationAuthor
Information about the user who triggered the notification.
Unique identifier of the author
Display name of the author
URL to the author’s avatar image, or null if not set
NotificationBase
Base fields present on all notifications.
Unique identifier of the notification
Timestamp when the notification was read, or null if unread
Timestamp when the notification was created
Comment information included in comment, reaction, and reply notifications.
Unique identifier of the comment
Text content of the comment
Implementation Details
The notifications endpoint is defined in packages/web-api-contract/src/index.ts:91-102:
notifications: c.router({
get: {
method: "GET",
path: "/notifications",
responses: {
200: z.object({
notifications: z.array(Notification),
count: z.record(z.string(), z.number()),
}),
},
},
})
Notification types are defined in packages/web-api-contract/src/index.ts:5-59:
export const NotificationAuthor = z.object({
id: z.string(),
name: z.string(),
avatar: z.string().nullable(),
});
export const NotificationBase = z.object({
id: z.string(),
readAt: z.coerce.date().nullable(),
createdAt: z.coerce.date(),
});
export const Notification = z
.union([
z.object({
type: z.literal("view"),
videoId: z.string(),
author: NotificationAuthor,
}),
z.object({
type: z.literal("comment"),
videoId: z.string(),
author: NotificationAuthor,
comment: CommentData,
}),
// ...
])
.and(NotificationBase);
Notification Preferences
Users can manage notification preferences through a separate endpoint:
POST /api/notifications/preferences
Preferences are stored in the user’s profile:
interface NotificationPreferences {
notifications: {
pauseComments: boolean;
pauseReplies: boolean;
pauseViews: boolean;
pauseReactions: boolean;
};
}
Error Responses
401 Unauthorized
{
"error": "Unauthorized"
}
Authentication required or token invalid.
500 Internal Server Error
{
"error": "Internal server error",
"message": "Failed to fetch notifications"
}
An unexpected error occurred on the server.
Usage Example
TypeScript Client
import { contract } from "@cap/web-api-contract";
import { initClient } from "@ts-rest/core";
const client = initClient(contract, {
baseUrl: "https://cap.so/api",
baseHeaders: {
Authorization: `Bearer ${token}`,
},
});
const { status, body } = await client.notifications.get();
if (status === 200) {
console.log(`You have ${body.notifications.length} notifications`);
console.log(`Unread comments: ${body.count.comment || 0}`);
}
Filter Unread Notifications
const unread = body.notifications.filter((n) => n.readAt === null);
console.log(`${unread.length} unread notifications`);
Group by Type
const grouped = body.notifications.reduce((acc, notification) => {
if (!acc[notification.type]) {
acc[notification.type] = [];
}
acc[notification.type].push(notification);
return acc;
}, {} as Record<string, typeof body.notifications>);
console.log(`Comments: ${grouped.comment?.length || 0}`);
console.log(`Views: ${grouped.view?.length || 0}`);
Next Steps
Authentication
Learn about authentication methods
Videos
Manage videos via API