Base URL: https://your-backend.vercel.app or http://localhost:3000

Health & Status

Server health monitoring endpoint

GET /health

Check server status and uptime.

Response

{
  "status": "healthy",
  "message": "MR BunkManager Notification Server is running",
  "timestamp": "26/11/2025, 03:30:45 PM",
  "timezone": "Asia/Kolkata (IST)",
  "uptime": 3600.5
}

Push Token Management

Register and manage device push tokens

POST /save-token

Register a device push token for notifications.

Request Body

{
  "userId": "firebase_user_id",
  "token": "ExponentPushToken[xxxxx] or FCM_token"
}

Response

{
  "success": true,
  "message": "Push token saved successfully",
  "userId": "firebase_user_id",
  "tokenType": "expo",
  "timestamp": "26/11/2025, 03:30:45 PM"
}

Error Codes

CodeDescription
400Missing userId or token
400Invalid token format
500Firebase error
DELETE /delete-token

Remove push token(s) for a user or specific token.

Request Body

{
  "token": "ExponentPushToken[xxxxx]"
}

or

{
  "userId": "firebase_user_id"
}
GET /tokens/:userId

Get all push tokens for a specific user.

Response

{
  "success": true,
  "userId": "firebase_user_id",
  "tokens": [
    {
      "id": "token_id",
      "token": "ExponentPushToken[xxxxx]",
      "tokenType": "expo",
      "createdAt": "timestamp",
      "active": true
    }
  ],
  "count": 1
}

Notification Sending

Send push notifications to users

POST /send-notification

Send notification to a specific user.

Request Body

{
  "userId": "firebase_user_id",
  "title": "Custom Title (optional)",
  "body": "Custom message (optional)",
  "data": {
    "type": "custom",
    "key": "value"
  }
}

Response

{
  "success": true,
  "message": "Notification sent successfully",
  "result": {
    "userId": "firebase_user_id",
    "sent": 1,
    "failed": 0,
    "invalidTokensRemoved": 0
  }
}
POST /send-notification-all

Broadcast notification to all registered users.

Request Body

{
  "title": "System Update",
  "body": "Important announcement",
  "data": { "type": "system" }
}
POST /send-daily-reminders

Send personalized daily reminders about tomorrow's classes. Generates contextual messages based on attendance data.

POST /send-class-reminders

Send reminders for classes starting soon.

Request Body

{
  "minutesBefore": 30
}

Valid values: 30 or 10

Group Notifications

Notify group members about activity

POST /notify-group-members

Notify group members about activity (messages, files, calls).

Request Body

{
  "groupId": "group_id",
  "groupName": "Study Group",
  "senderId": "user_id",
  "senderName": "John Doe",
  "type": "message",
  "extra": {
    "message": "Hello everyone!"
  }
}

Activity Types

TypeExtra FieldsNotification
messagemessage"John Doe: Hello..."
filefileName"John Doe shared a file"
callisVideo"John Doe started a call"

Follower Notifications

Notify followers about new content

POST /notify-followers

Notify followers when user uploads a new note.

Request Body

{
  "authorId": "user_id",
  "authorName": "John Doe",
  "noteId": "note_id",
  "title": "Biology Notes Chapter 5",
  "subject": "Biology"
}

File Upload

Upload files to cloud storage

POST /upload

Upload file to Google Drive. Accepts multipart/form-data with file field.

Allowed Types: JPEG, PNG, GIF, WebP, PDF (max 50MB)

Response

{
  "success": true,
  "fileId": "google_drive_file_id",
  "fileName": "timestamp_filename.pdf",
  "mimeType": "application/pdf",
  "size": 2048576,
  "webViewLink": "https://drive.google.com/file/d/{id}/view",
  "webContentLink": "https://drive.google.com/uc?id={id}&export=download",
  "thumbnailLink": "https://drive.google.com/thumbnail?id={id}&sz=w400"
}
POST /upload-catbox

Upload file to Catbox.moe (CORS-friendly for web/avatars).

DELETE /upload/:fileId

Delete file from Google Drive.

Deep Links

Handle shared content links

GET /note/:noteId

Web page handler for shared note links. Returns HTML with Open Graph meta tags and auto-redirects to app on mobile.

Deep Link Format: mrbunkmanager://note/{noteId}

Error Handling

Standard error response format

Error Response Format

{
  "success": false,
  "error": "Error message",
  "details": "Technical details",
  "timestamp": "26/11/2025, 03:30:45 PM"
}

HTTP Status Codes

CodeDescription
200Success
400Bad Request (validation error)
404Not Found
429Rate Limit Exceeded
500Server Error

Rate Limiting

Window: 15 minutes | Max Requests: 100 per window per IP

{
  "error": "Too many requests",
  "retryAfter": 900
}

OCR & Timetable Extraction

Image text extraction and AI parsing services

ocrService - OCR.space Integration

Extracts text from images using OCR (Optical Character Recognition). Supports JPG, PNG, GIF, WebP, BMP, TIFF formats.

extractTextFromImage(imageUri: string): Promise<OCRResult>

// Input types supported:
// - data:image/...;base64,... (Web & Native)
// - file:///path/to/image (Native only)
// - content://... (Android only)
// - https://... (Web & Native)

interface OCRResult {
  success: boolean;
  text: string;        // Extracted text
  error?: string;      // Error message if failed
}

timetableParserService - AI Parsing

Parses OCR-extracted text into structured timetable entries using Groq AI (Llama 4 Maverick).

parseTimetableFromText(ocrText: string): Promise<ParseResult>

interface ParseResult {
  success: boolean;
  entries: TimetableEntry[];  // Parsed timetable entries
  error?: string;
}

interface TimetableEntry {
  id: string;
  day: string;           // Monday, Tuesday, etc.
  subject: string;
  subjectCode?: string;
  startTime: string;     // HH:MM format
  endTime: string;
  type?: string;         // lecture, lab, tutorial
  faculty?: string;
  room?: string;
}

Frontend Services

Client-side service API reference

authService

signUp(email: string, password: string, displayName: string): Promise<User>
signIn(email: string, password: string): Promise<User>
signInWithGoogle(): Promise<User>
sendVerificationEmail(): Promise<void>
resetPassword(email: string): Promise<void>
signOut(): Promise<void>
getCurrentUser(): User | null

firestoreService

// User Profile
createUserProfile(uid: string, data: UserProfile): Promise<void>
getUserProfile(uid: string): Promise<UserProfile | null>
updateUserProfile(uid: string, data: Partial<UserProfile>): Promise<void>

// Timetable
saveTimetable(uid: string, entries: TimetableEntry[]): Promise<void>
getTimetable(uid: string): Promise<TimetableEntry[]>

// Subjects & Attendance
getSubjects(uid: string): Promise<Subject[]>
addSubject(uid: string, subject: Subject): Promise<void>
updateSubjectAttendance(uid: string, subjectId: string, attended: number, total: number): Promise<void>

notesService

createNote(authorId: string, data: CreateNoteInput): Promise<Note>
updateNote(noteId: string, data: Partial<Note>): Promise<void>
deleteNote(noteId: string, authorId: string): Promise<void>
getNoteWithContext(noteId: string, userId: string): Promise<FeedNote>
getFeedNotes(userId: string, followingIds: string[], lastDoc?: any): Promise<PaginatedResult<FeedNote>>
searchNotes(userId: string, query: string, filters?: NoteFilters): Promise<FeedNote[]>

groupsService

createGroup(name: string, description: string, category: string, isPrivate: boolean, userId: string, userName: string): Promise<Group>
joinGroup(groupId: string, userId: string, userName: string): Promise<void>
leaveGroup(groupId: string, userId: string): Promise<void>
sendMessage(groupId: string, userId: string, userName: string, photoURL: string | undefined, message: string): Promise<void>
subscribeToMessages(groupId: string, callback: (messages: GroupMessage[]) => void): Unsubscribe

socialService

likeNote(noteId: string, userId: string): Promise<void>
unlikeNote(noteId: string, userId: string): Promise<void>
toggleLike(noteId: string, userId: string): Promise<boolean>
addComment(noteId: string, comment: Omit<NoteComment, 'id' | 'createdAt'>): Promise<NoteComment>
saveNote(noteId: string, userId: string): Promise<void>
getSavedNotes(userId: string, lastDoc?: any): Promise<PaginatedResult<Note>>

followService

followUser(followerId: string, followingId: string): Promise<void>
unfollowUser(followerId: string, followingId: string): Promise<void>
getFollowing(userId: string): Promise<string[]>
getFollowers(userId: string): Promise<string[]>
isFollowing(followerId: string, followingId: string): Promise<boolean>
getSuggestedUsers(userId: string, college: string, course: string): Promise<PublicUserProfile[]>

Timezone: All timestamps are in Indian Standard Time (IST) - Asia/Kolkata
Format: DD/MM/YYYY, HH:MM:SS AM/PM