All endpoints require authentication via Bearer token in the Authorization header.
POST /api/v1/user/notes
Creates a new note or replaces the user's existing active note.
Request Body:
{
"text": "at the gym 💪",
"audience": "followers" // or "everyone"
}Response (201 Created):
{
"status": 201,
"message": "Note created successfully",
"data": {
"note": {
"_id": "...",
"author": {
"_id": "...",
"userName": "john",
"displayName": "John Doe",
"profileImage": "/images/...",
"school": "Arcadia High School"
},
"text": "at the gym 💪",
"audience": "followers",
"expiresAt": "2025-11-26T12:00:00.000Z",
"createdAt": "2025-11-25T12:00:00.000Z"
}
}
}Validation:
- Text is required and must be 1-60 characters
- Audience must be "followers" or "everyone"
- Only one active note per user (previous note is deleted)
GET /api/v1/user/notes/feed?audience=followers
Retrieves notes based on the selected audience filter.
Query Parameters:
audience(optional): "followers" (default) or "everyone"
Response (200 OK):
{
"status": 200,
"message": "Notes fetched successfully",
"data": {
"notes": [
{
"_id": "...",
"author": {
"_id": "...",
"userName": "sarah",
"displayName": "Sarah Johnson",
"profileImage": "/images/...",
"school": "Arcadia High School"
},
"text": "studying for finals 📚",
"audience": "followers",
"expiresAt": "2025-11-26T14:30:00.000Z",
"createdAt": "2025-11-25T14:30:00.000Z"
}
]
}
}Feed Logic:
audience=followers: Returns notes from users you follow + your own noteaudience=everyone: Returns all public notes (audience="everyone")- Results sorted by
createdAtdescending (newest first) - Limit: 100 notes
GET /api/v1/user/notes/mine
Retrieves the current user's active note (if any).
Response (200 OK):
{
"status": 200,
"message": "Note fetched successfully",
"data": {
"note": {
"_id": "...",
"author": { ... },
"text": "at the gym 💪",
"audience": "followers",
"expiresAt": "2025-11-26T12:00:00.000Z",
"createdAt": "2025-11-25T12:00:00.000Z"
}
}
}If no active note:
{
"status": 200,
"message": "No active note",
"data": {
"note": null
}
}DELETE /api/v1/user/notes
Deletes the user's active note.
Response (200 OK):
{
"status": 200,
"message": "Note deleted successfully",
"data": {}
}If no active note (404):
{
"status": 404,
"message": "No active note to delete",
"data": {}
}curl -X POST https://api.theirlapp.com/api/v1/user/notes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"text": "Testing notes feature 🎉",
"audience": "followers"
}'curl -X GET "https://api.theirlapp.com/api/v1/user/notes/feed?audience=followers" \
-H "Authorization: Bearer YOUR_TOKEN"curl -X GET "https://api.theirlapp.com/api/v1/user/notes/feed?audience=everyone" \
-H "Authorization: Bearer YOUR_TOKEN"curl -X GET https://api.theirlapp.com/api/v1/user/notes/mine \
-H "Authorization: Bearer YOUR_TOKEN"curl -X DELETE https://api.theirlapp.com/api/v1/user/notes \
-H "Authorization: Bearer YOUR_TOKEN"- 400 Bad Request: Invalid input (missing text, invalid audience, text too long)
- 401 Unauthorized: Missing or invalid token
- 404 Not Found: No active note to delete
- 500 Internal Server Error: Server error
Notes automatically expire after 24 hours via MongoDB's TTL index on the expiresAt field. MongoDB's background task checks for expired documents approximately every 60 seconds.
To verify TTL index:
db.notes.getIndexes()
// Should show: { expiresAt: 1 } with expireAfterSeconds: 0To manually test expiry (for development):
// Create a note that expires in 1 minute
db.notes.insertOne({
author: ObjectId("..."),
text: "Test expiry",
audience: "followers",
expiresAt: new Date(Date.now() + 60000), // 1 minute
createdAt: new Date()
})
// Wait 2 minutes, then check
db.notes.find({ text: "Test expiry" })
// Should return emptyImport the following into Postman:
{
"info": {
"name": "IRL Notes API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Create Note",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{token}}"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"text\": \"Testing notes 🎉\",\n \"audience\": \"followers\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/api/v1/user/notes",
"host": ["{{baseUrl}}"],
"path": ["api", "v1", "user", "notes"]
}
}
},
{
"name": "Get Feed (Followers)",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{token}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/user/notes/feed?audience=followers",
"host": ["{{baseUrl}}"],
"path": ["api", "v1", "user", "notes", "feed"],
"query": [
{
"key": "audience",
"value": "followers"
}
]
}
}
},
{
"name": "Get Feed (Everyone)",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{token}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/user/notes/feed?audience=everyone",
"host": ["{{baseUrl}}"],
"path": ["api", "v1", "user", "notes", "feed"],
"query": [
{
"key": "audience",
"value": "everyone"
}
]
}
}
},
{
"name": "Get Own Note",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{token}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/user/notes/mine",
"host": ["{{baseUrl}}"],
"path": ["api", "v1", "user", "notes", "mine"]
}
}
},
{
"name": "Delete Note",
"request": {
"method": "DELETE",
"header": [
{
"key": "Authorization",
"value": "Bearer {{token}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/v1/user/notes",
"host": ["{{baseUrl}}"],
"path": ["api", "v1", "user", "notes"]
}
}
}
],
"variable": [
{
"key": "baseUrl",
"value": "https://api.theirlapp.com"
},
{
"key": "token",
"value": "YOUR_TOKEN_HERE"
}
]
}