Skip to main content

API Endpoints

Overview

The Notes App backend provides a RESTful API with endpoints for user management and note operations. All endpoints return JSON responses and follow standard HTTP status codes for success and error handling.

What is a REST API?

REST (Representational State Transfer) is an architectural style for web services that uses:

  • HTTP methods (GET, POST, PUT, DELETE) to indicate the type of operation
  • URLs to identify resources (users, notes)
  • JSON for data exchange
  • Status codes to indicate success or failure

Server Configuration

File: backend/index.js

The server is built using Express.js, a web framework for Node.js:

const express = require("express");
const cors = require("cors");
const app = express();

app.use(express.json());
app.use(cors({ origin: "*" }));

app.listen(8000);

Middleware Setup

  • express.json(): Parses incoming JSON request bodies
  • cors({ origin: "*" }): Enables Cross-Origin Resource Sharing from any domain
  • app.listen(8000): Starts the server on port 8000

User Management Endpoints

Create Account

Endpoint: POST /create-account Authentication: None required

app.post("/create-account", async (req, res) => {
const { fullName, email, password } = req.body;

// Validation
if (!fullName) {
return res.status(400).json({ error: true, message: "Full Name is required" });
}

// Check for existing user
const isUser = await User.findOne({ email: email });
if (isUser) {
return res.json({ error: true, message: "User already exists" });
}

// Create and save user
const user = new User({ fullName, email, password });
await user.save();

// Generate JWT token
const accessToken = jwt.sign({ user }, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "36000m",
});

return res.json({
error: false,
user,
accessToken,
message: "Registration Successful",
});
});

Request Format

{
"fullName": "John Doe",
"email": "john@example.com",
"password": "password123"
}

Response Format

{
"error": false,
"user": { "fullName": "John Doe", "email": "john@example.com", "_id": "..." },
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"message": "Registration Successful"
}

User Login

Endpoint: POST /login Authentication: None required

app.post("/login", async (req, res) => {
const { email, password } = req.body;

const userInfo = await User.findOne({ email: email });

if (userInfo.email == email && userInfo.password == password) {
const user = { user: userInfo };
const accessToken = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "36000m",
});

return res.json({
error: false,
message: "Login Successful",
email,
accessToken,
});
} else {
return res.status(400).json({
error: true,
message: "Invalid Credentials",
});
}
});

Key Features

  • Plain text password comparison (security concern)
  • JWT token generation on successful login
  • Error handling for invalid credentials

Get User Information

Endpoint: GET /get-user Authentication: Required (JWT token)

app.get("/get-user", authenticateToken, async (req, res) => {
const { user } = req.user;
const isUser = await User.findOne({ _id: user._id });

return res.json({
user: {
fullName: isUser.fullName,
email: isUser.email,
_id: isUser._id,
createdOn: isUser.createOn,
},
message: "",
});
});

Note Management Endpoints

Create Note

Endpoint: POST /add-note Authentication: Required

app.post("/add-note", authenticateToken, async (req, res) => {
const { title, content, tags } = req.body;
const { user } = req.user;

if (!title) {
return res.status(400).json({ message: "Title is required" });
}

if (!content) {
return res.status(400).json({ message: "content is required" });
}

try {
const note = new Note({
title,
content,
tags: tags || [],
userId: user._id,
});

await note.save();

return res.json({
error: false,
note,
message: "Note added successfully",
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error",
});
}
});

Request Format

{
"title": "Meeting Notes",
"content": "Discussed project timeline and deliverables",
"tags": ["work", "meeting"]
}

Edit Note

Endpoint: PUT /edit-note/:noteId Authentication: Required

app.put("/edit-note/:noteId", authenticateToken, async (req, res) => {
const noteId = req.params.noteId;
const { title, content, tags, isPinned } = req.body;
const { user } = req.user;

try {
const note = await Note.findOne({ _id: noteId, userId: user._id });
if (!note) {
return res.status(404).json({ error: true, message: "Note not found" });
}

if (title) note.title = title;
if (content) note.content = content;
if (tags) note.tags = tags;
if (isPinned) note.isPinned = isPinned;

await note.save();
return res.json({
error: false,
note,
message: "Note updated successfully",
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error ",
});
}
});

Key Features

  • URL parameters: :noteId extracts note ID from URL
  • Partial updates: Only provided fields are updated
  • User ownership verification: Ensures users can only edit their own notes

Delete Note

Endpoint: DELETE /delete-note/:noteId Authentication: Required

app.delete("/delete-note/:noteId", authenticateToken, async (req, res) => {
const noteId = req.params.noteId;
const { user } = req.user;

try {
const note = await Note.findOne({ _id: noteId, userId: user._id });
if (!note) {
return res.status(404).json({ error: true, message: "Note not found" });
}

await Note.deleteOne({ _id: noteId, userId: user._id });

return res.json({
error: false,
note,
message: "Note deleted successfully",
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error ",
});
}
});

Pin/Unpin Note

Endpoint: PUT /update-note-pinned/:noteId Authentication: Required

app.put("/update-note-pinned/:noteId", authenticateToken, async (req, res) => {
const noteId = req.params.noteId;
const { isPinned } = req.body;
const { user } = req.user;

try {
const note = await Note.findOne({ _id: noteId, userId: user._id });
if (!note) {
return res.status(404).json({ error: true, message: "Note not found" });
}

if (isPinned !== undefined) note.isPinned = isPinned;

await note.save();
return res.json({
error: false,
note,
message: "Note updated successfully",
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error ",
});
}
});

Get All Notes

Endpoint: GET /get-all-notes Authentication: Required

app.get("/get-all-notes", authenticateToken, async (req, res) => {
const { user } = req.user;

try {
const notes = await Note.find({ userId: user._id }).sort({ isPinned: -1 });

return res.json({
error: false,
notes,
message: "All notes retrieved successfully",
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error",
});
}
});

Key Features

  • Sorting: .sort({ isPinned: -1 }) puts pinned notes first
  • User filtering: Only returns notes belonging to authenticated user

Search Notes

Endpoint: GET /search-notes Authentication: Required

app.get("/search-notes/", authenticateToken, async (req, res) => {
const { user } = req.user;
const { query } = req.query;

if (!query) {
return res.status(400).json({ error: true, message: "Search query is required" });
}

try {
const matchingNotes = await Note.find({
userId: user._id,
$or: [
{ title: { $regex: new RegExp(query, "i") } },
{ content: { $regex: new RegExp(query, "i") } },
],
});

return res.json({
error: false,
notes: matchingNotes,
message: "Notes matching the search query retrieved successfully"
});
} catch (error) {
return res.status(500).json({
error: true,
message: "Internal Server Error",
});
}
});

Search Features

  • Query parameters: ?query=searchterm in URL
  • Case-insensitive search: "i" flag in regex
  • Multiple field search: Searches both title and content
  • MongoDB regex: $regex operator for pattern matching

HTTP Status Codes Used

  • 200 OK: Successful requests
  • 400 Bad Request: Invalid input or missing required fields
  • 401 Unauthorized: Missing or invalid authentication token
  • 404 Not Found: Requested resource doesn't exist
  • 500 Internal Server Error: Server-side errors

Error Response Format

All error responses follow a consistent format:

{
"error": true,
"message": "Description of the error"
}

Connection to Other Components

  • Authentication System: Most endpoints require JWT token validation
  • Database Models: All endpoints interact with User and Note models
  • Frontend: These endpoints are consumed by the React application
  • Middleware: authenticateToken protects sensitive operations