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 bodiescors({ origin: "*" })
: Enables Cross-Origin Resource Sharing from any domainapp.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