Complete API reference for all Harvous endpoints with request/response examples and error codes.
- Authentication
- Notes
- Threads
- Spaces
- User
- Tags
- Search
- Scripture
- Inbox
- Navigation
- Error Codes
- Rate Limiting
All API endpoints require authentication via Clerk. The userId is automatically extracted from the request context. Unauthenticated requests return 401 Unauthorized.
POST /api/notes/create
Creates a new note. Notes are always created in the "Unorganized" thread initially, and can be added to specific threads via the junction table.
Request Body (FormData):
content: string (required, 1-50,000 characters)
title?: string (optional)
threadId?: string (optional, format: "thread_*")
noteType?: "default" | "scripture" | "resource" (default: "default")
scriptureReference?: string (optional)
scriptureVersion?: string (optional)
spaceId?: string (optional, format: "space_*")
Response (200 OK):
{
"id": "note_1234567890",
"content": "This is my note content",
"title": "My Note Title",
"threadId": "thread_unorganized",
"spaceId": null,
"simpleNoteId": 1,
"noteType": "default",
"userId": "user_abc123",
"isPublic": false,
"createdAt": "2025-01-15T10:30:00.000Z"
}Error Responses:
400 Bad Request: Invalid input (validation failed)CONTENT_REQUIRED: Content is requiredCONTENT_EMPTY: Content cannot be emptyCONTENT_TOO_LONG: Content exceeds 50,000 charactersINVALID_NOTE_TYPE: Invalid note typeINVALID_THREAD_ID: Invalid thread ID formatINVALID_SPACE_ID: Invalid space ID format
401 Unauthorized: Authentication required429 Too Many Requests: Rate limit exceededRATE_LIMIT_EXCEEDED: Maximum 20 requests per minute
500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
PUT /api/notes/update
Updates an existing note's content.
Request Body (JSON):
{
"noteId": "note_1234567890",
"content": "Updated note content",
"title": "Updated title"
}Response (200 OK):
{
"id": "note_1234567890",
"content": "Updated note content",
"title": "Updated title",
"threadId": "thread_unorganized",
"updatedAt": "2025-01-15T11:00:00.000Z"
}Error Responses:
400 Bad Request: Invalid inputCONTENT_REQUIRED: Content is requiredCONTENT_EMPTY: Content cannot be emptyCONTENT_TOO_LONG: Content exceeds 50,000 characters
401 Unauthorized: Authentication required404 Not Found: Note not found or doesn't belong to user429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
DELETE /api/notes/delete?noteId=note_1234567890
Deletes a note and revokes associated XP.
Query Parameters:
noteId(required): Note ID to delete
Response (200 OK):
{
"success": true,
"message": "Note deleted successfully"
}Error Responses:
400 Bad Request: Missing noteId parameter401 Unauthorized: Authentication required404 Not Found: Note not found or doesn't belong to user429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/notes/[id]/details
Gets detailed information about a specific note, including associated threads, comments, and tags.
Path Parameters:
id(required): Note ID
Response (200 OK):
{
"note": {
"id": "note_1234567890",
"content": "Note content",
"title": "Note title",
"threadId": "thread_unorganized",
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T11:00:00.000Z"
},
"threads": [
{
"id": "thread_abc123",
"title": "My Thread",
"count": 5
}
],
"comments": [],
"tags": [
{
"id": "tag_xyz789",
"name": "Bible Study"
}
],
"scriptureMetadata": null
}Error Responses:
401 Unauthorized: Authentication required404 Not Found: Note not found or doesn't belong to user500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/notes/[id]/add-thread
Adds a note to an additional thread via the junction table.
Path Parameters:
id(required): Note ID
Request Body (JSON):
{
"threadId": "thread_abc123"
}Response (200 OK):
{
"success": true,
"message": "Note added to thread successfully"
}Error Responses:
400 Bad Request: Invalid threadId or note already in thread401 Unauthorized: Authentication required404 Not Found: Note or thread not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/notes/[id]/remove-thread
Removes a note from a thread. If it's the last thread, the note becomes unorganized.
Path Parameters:
id(required): Note ID
Request Body (JSON):
{
"threadId": "thread_abc123"
}Response (200 OK):
{
"success": true,
"message": "Note removed from thread successfully"
}Error Responses:
400 Bad Request: Invalid threadId401 Unauthorized: Authentication required404 Not Found: Note or thread not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/notes/recent?limit=10
Gets the most recently created notes for the authenticated user.
Query Parameters:
limit(optional): Number of notes to return (default: 10, max: 100)
Response (200 OK):
{
"notes": [
{
"id": "note_1234567890",
"content": "Recent note",
"title": "Recent Title",
"threadId": "thread_unorganized",
"createdAt": "2025-01-15T12:00:00.000Z"
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/threads/create
Creates a new thread.
Request Body (FormData):
title: string (optional, defaults to "Untitled Thread", max 200 characters)
color?: string (optional, must be one of: paper, blue, yellow, orange, pink, purple, green)
isPublic?: boolean (default: false)
spaceId?: string (optional, format: "space_*")
selectedNoteIds?: string (optional, JSON array of note IDs to add to thread)
Response (200 OK):
{
"id": "thread_abc123",
"title": "My Thread",
"subtitle": null,
"spaceId": null,
"userId": "user_abc123",
"isPublic": false,
"color": "blue",
"isPinned": false,
"createdAt": "2025-01-15T10:30:00.000Z"
}Error Responses:
400 Bad Request: Invalid inputTITLE_TOO_LONG: Title exceeds 200 charactersINVALID_COLOR: Invalid color valueINVALID_SPACE_ID: Invalid space ID format
401 Unauthorized: Authentication required429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/threads/update
Updates thread properties and manages associated notes.
Request Body (FormData):
id: string (required)
title: string (required, 1-200 characters)
color?: string (optional, must be valid thread color)
isPublic?: boolean (optional)
selectedNoteIds?: string (optional, JSON array of note IDs)
Response (200 OK):
{
"id": "thread_abc123",
"title": "Updated Thread Title",
"color": "green",
"isPublic": false,
"updatedAt": "2025-01-15T11:00:00.000Z"
}Error Responses:
400 Bad Request: Invalid inputTITLE_REQUIRED: Title is requiredTITLE_EMPTY: Title cannot be emptyTITLE_TOO_LONG: Title exceeds 200 charactersINVALID_COLOR: Invalid color value
401 Unauthorized: Authentication required404 Not Found: Thread not found or doesn't belong to user429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
DELETE /api/threads/delete?threadId=thread_abc123
Deletes a thread and moves associated notes to the "Unorganized" thread.
Query Parameters:
threadId(required): Thread ID to delete
Response (200 OK):
{
"success": true,
"message": "Thread deleted successfully"
}Error Responses:
400 Bad Request: Missing threadId parameter401 Unauthorized: Authentication required404 Not Found: Thread not found or doesn't belong to user429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/threads/[threadId]/notes
Gets all notes in a specific thread.
Path Parameters:
threadId(required): Thread ID
Response (200 OK):
{
"notes": [
{
"id": "note_1234567890",
"content": "Note content",
"title": "Note title",
"createdAt": "2025-01-15T10:30:00.000Z"
}
]
}Error Responses:
401 Unauthorized: Authentication required404 Not Found: Thread not found or doesn't belong to user500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
GET /api/threads/list
Gets all threads for the authenticated user.
Response (200 OK):
{
"threads": [
{
"id": "thread_abc123",
"title": "My Thread",
"color": "blue",
"isPinned": false,
"createdAt": "2025-01-15T10:30:00.000Z"
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/threads/ensure-unorganized
Ensures the "Unorganized" thread exists for the authenticated user. This is called automatically when needed.
Response (200 OK):
{
"id": "thread_unorganized",
"title": "Unorganized",
"exists": true
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/spaces/create
Creates a new space and optionally assigns selected notes and threads to it.
Request Body (FormData):
title: string (required, 1-200 characters)
color?: string (optional, must be valid thread color, default: "paper")
isPublic?: boolean (optional, default: false)
selectedNoteIds?: string (optional, JSON array)
selectedThreadIds?: string (optional, JSON array)
Response (200 OK):
{
"id": "space_xyz789",
"title": "My Space",
"color": "paper",
"isPublic": false,
"backgroundGradient": "linear-gradient(180deg, var(--color-paper) 0%, var(--color-paper) 100%)",
"userId": "user_abc123",
"createdAt": "2025-01-15T10:30:00.000Z"
}Error Responses:
400 Bad Request: Invalid inputTITLE_REQUIRED: Title is requiredTITLE_EMPTY: Title cannot be emptyTITLE_TOO_LONG: Title exceeds 200 charactersINVALID_COLOR: Invalid color value
401 Unauthorized: Authentication required429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
DELETE /api/spaces/delete?spaceId=space_xyz789
Deletes a space and all associated threads and notes.
Query Parameters:
spaceId(required): Space ID to delete
Response (200 OK):
{
"success": true,
"message": "Space deleted successfully"
}Error Responses:
400 Bad Request: Missing spaceId parameter401 Unauthorized: Authentication required404 Not Found: Space not found or doesn't belong to user500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/spaces/items
Gets all spaces, threads, and notes for the authenticated user.
Response (200 OK):
{
"spaces": [
{
"id": "space_xyz789",
"title": "My Space",
"totalItemCount": 10
}
],
"threads": [
{
"id": "thread_abc123",
"title": "My Thread",
"noteCount": 5
}
],
"notes": [
{
"id": "note_1234567890",
"title": "My Note"
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/spaces/[spaceId]/update
Updates space properties.
Path Parameters:
spaceId(required): Space ID
Request Body (FormData):
title?: string (optional, 1-200 characters)
color?: string (optional, must be valid thread color)
isPublic?: boolean (optional)
Response (200 OK):
{
"id": "space_xyz789",
"title": "Updated Space Title",
"color": "blue",
"updatedAt": "2025-01-15T11:00:00.000Z"
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Authentication required404 Not Found: Space not found or doesn't belong to user500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/spaces/[spaceId]/add-items
Adds notes and/or threads to a space.
Path Parameters:
spaceId(required): Space ID
Request Body (FormData):
noteIds?: string (optional, JSON array)
threadIds?: string (optional, JSON array)
Response (200 OK):
{
"success": true,
"message": "Items added to space successfully"
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Authentication required404 Not Found: Space not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/spaces/[spaceId]/remove-items
Removes notes and/or threads from a space.
Path Parameters:
spaceId(required): Space ID
Request Body (FormData):
noteIds?: string (optional, JSON array)
threadIds?: string (optional, JSON array)
Response (200 OK):
{
"success": true,
"message": "Items removed from space successfully"
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Authentication required404 Not Found: Space not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/user/get-profile
Gets the authenticated user's profile data, including cached Clerk data and church information.
Response (200 OK):
{
"userId": "user_abc123",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"displayName": "John D",
"userColor": "blue",
"profileImageUrl": "https://...",
"emailVerified": true,
"churchData": {
"churchName": "My Church",
"churchCity": "City",
"churchState": "State"
}
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/user/update-profile
Updates user's first name, last name, and color preference.
Request Body (JSON):
{
"firstName": "John",
"lastName": "Doe",
"color": "blue"
}Response (200 OK):
{
"success": true,
"message": "Profile updated successfully"
}Error Responses:
400 Bad Request: Invalid inputFIRST_NAME_REQUIRED: First name is requiredLAST_NAME_REQUIRED: Last name is requiredFIRST_NAME_TOO_LONG: First name exceeds 100 charactersLAST_NAME_TOO_LONG: Last name exceeds 100 charactersINVALID_COLOR: Invalid color value
401 Unauthorized: Authentication required429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/user/update-church
Updates user's church information.
Request Body (JSON):
{
"churchName": "My Church",
"churchCity": "City",
"churchState": "State"
}Response (200 OK):
{
"success": true,
"message": "Church information updated successfully"
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/user/update-credentials
Updates user's email and/or password via Clerk.
Request Body (JSON):
{
"email": "newemail@example.com",
"currentPassword": "oldpassword",
"newPassword": "newpassword"
}Response (200 OK):
{
"success": true,
"message": "Credentials updated successfully"
}Error Responses:
400 Bad Request: Invalid input or Clerk validation errorform_password_incorrect: Current password is incorrectform_password_pwned: Password found in data breachform_password_too_common: Password is too commonform_email_address_invalid: Invalid email addressform_email_address_already_exists: Email already in use
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/user/xp
Gets user's XP (experience points) data.
Response (200 OK):
{
"totalXP": 150,
"level": 2,
"xpHistory": [
{
"id": "xp_123",
"amount": 10,
"reason": "note_created",
"createdAt": "2025-01-15T10:30:00.000Z"
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
DELETE /api/user/delete-account
Deletes the user's account and all associated data.
Response (200 OK):
{
"success": true,
"message": "Account deleted successfully"
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
DELETE /api/user/clear-data
Clears all user data but keeps the account.
Response (200 OK):
{
"success": true,
"message": "Data cleared successfully"
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/tags/create
Creates a new tag.
Request Body (FormData):
name: string (required, 1-50 characters)
Response (200 OK):
{
"id": "tag_xyz789",
"name": "Bible Study",
"userId": "user_abc123",
"createdAt": "2025-01-15T10:30:00.000Z"
}Error Responses:
400 Bad Request: Invalid input or tag already exists401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/tags/list
Gets all tags for the authenticated user.
Response (200 OK):
{
"tags": [
{
"id": "tag_xyz789",
"name": "Bible Study",
"createdAt": "2025-01-15T10:30:00.000Z"
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
DELETE /api/tags/delete?tagId=tag_xyz789
Deletes a tag and removes all associations with notes.
Query Parameters:
tagId(required): Tag ID to delete
Response (200 OK):
{
"success": true,
"message": "Tag deleted successfully"
}Error Responses:
400 Bad Request: Missing tagId parameter401 Unauthorized: Authentication required404 Not Found: Tag not found or doesn't belong to user500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/note-tags/assign
Assigns a tag to a note.
Request Body (JSON):
{
"noteId": "note_1234567890",
"tagId": "tag_xyz789"
}Response (200 OK):
{
"success": true,
"message": "Tag assigned successfully"
}Error Responses:
400 Bad Request: Invalid input or tag already assigned401 Unauthorized: Authentication required404 Not Found: Note or tag not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/note-tags/remove
Removes a tag from a note.
Request Body (JSON):
{
"noteId": "note_1234567890",
"tagId": "tag_xyz789"
}Response (200 OK):
{
"success": true,
"message": "Tag removed successfully"
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Authentication required404 Not Found: Note or tag not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
GET /api/note-tags/list?noteId=note_1234567890
Gets all tags for a specific note.
Query Parameters:
noteId(required): Note ID
Response (200 OK):
{
"tags": [
{
"id": "tag_xyz789",
"name": "Bible Study"
}
]
}Error Responses:
400 Bad Request: Missing noteId parameter401 Unauthorized: Authentication required404 Not Found: Note not found500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
GET /api/search?q=query&type=all&limit=50
Searches notes and threads by content and title.
Query Parameters:
q(required): Search querytype(optional):"all"|"notes"|"threads"(default:"all")limit(optional): Maximum results (default: 50, max: 100)
Response (200 OK):
{
"results": [
{
"type": "note",
"id": "note_1234567890",
"title": "Search Result Note",
"content": "Matching content...",
"threadId": "thread_abc123"
},
{
"type": "thread",
"id": "thread_abc123",
"title": "Search Result Thread"
}
]
}Error Responses:
400 Bad Request: Missing query parameter401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/scripture/fetch-verse
Fetches scripture verse text from Bible.org API.
Request Body (JSON):
{
"reference": "John 3:16"
}Response (200 OK):
{
"reference": "John 3:16",
"text": "For God so loved the world...",
"version": "ESV"
}Error Responses:
400 Bad Request: Invalid reference format401 Unauthorized: Authentication required500 Internal Server Error: Server error or Bible.org API error
Rate Limit: 100 requests/minute (read operation)
POST /api/scripture/detect
Detects scripture references in text content.
Request Body (JSON):
{
"content": "Check out John 3:16 and Romans 8:28"
}Response (200 OK):
{
"references": [
{
"reference": "John 3:16",
"normalized": "John 3:16"
},
{
"reference": "Romans 8:28",
"normalized": "Romans 8:28"
}
]
}Error Responses:
400 Bad Request: Missing content401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
GET /api/scripture/check-existing?reference=John 3:16
Checks if scripture metadata already exists for a reference.
Query Parameters:
reference(required): Scripture reference
Response (200 OK):
{
"exists": true,
"metadata": {
"id": "scripture_123",
"reference": "John 3:16",
"normalizedReference": "John 3:16"
}
}Error Responses:
400 Bad Request: Missing reference parameter401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
GET /api/navigation/data
Gets navigation data including spaces, threads, and inbox count.
Response (200 OK):
{
"spaces": [
{
"id": "space_xyz789",
"title": "My Space",
"totalItemCount": 10,
"backgroundGradient": "linear-gradient(...)"
}
],
"threads": [
{
"id": "thread_abc123",
"title": "My Thread",
"noteCount": 5,
"backgroundGradient": "linear-gradient(...)"
}
],
"inboxCount": 3
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
GET /api/inbox/preview
Gets preview of inbox items.
Response (200 OK):
{
"items": [
{
"id": "inbox_123",
"title": "Inbox Item",
"content": "Item content...",
"isActive": true
}
]
}Error Responses:
401 Unauthorized: Authentication required500 Internal Server Error: Server error
Rate Limit: 100 requests/minute (read operation)
POST /api/inbox/add-to-harvous
Adds an inbox item to Harvous as a note or thread.
Request Body (FormData):
inboxItemId: string (required)
asNote?: boolean (default: true)
threadId?: string (optional)
Response (200 OK):
{
"success": true,
"noteId": "note_1234567890",
"threadId": "thread_abc123"
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Authentication required404 Not Found: Inbox item not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/inbox/archive
Archives an inbox item.
Request Body (JSON):
{
"inboxItemId": "inbox_123"
}Response (200 OK):
{
"success": true,
"message": "Item archived successfully"
}Error Responses:
400 Bad Request: Missing inboxItemId401 Unauthorized: Authentication required404 Not Found: Inbox item not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
POST /api/inbox/unarchive
Unarchives an inbox item.
Request Body (JSON):
{
"inboxItemId": "inbox_123"
}Response (200 OK):
{
"success": true,
"message": "Item unarchived successfully"
}Error Responses:
400 Bad Request: Missing inboxItemId401 Unauthorized: Authentication required404 Not Found: Inbox item not found500 Internal Server Error: Server error
Rate Limit: 20 requests/minute (write operation)
All error responses follow this format:
{
"error": "Error message",
"code": "ERROR_CODE"
}AUTH_REQUIRED: Authentication required (401)
CONTENT_REQUIRED: Content is requiredCONTENT_EMPTY: Content cannot be emptyCONTENT_TOO_LONG: Content exceeds maximum length (50,000 characters)TITLE_REQUIRED: Title is requiredTITLE_EMPTY: Title cannot be emptyTITLE_TOO_LONG: Title exceeds maximum length (200 characters)FIRST_NAME_REQUIRED: First name is requiredLAST_NAME_REQUIRED: Last name is requiredFIRST_NAME_TOO_LONG: First name exceeds maximum length (100 characters)LAST_NAME_TOO_LONG: Last name exceeds maximum length (100 characters)INVALID_COLOR: Invalid color value (must be one of: paper, blue, yellow, orange, pink, purple, green)INVALID_NOTE_TYPE: Invalid note type (must be: default, scripture, or resource)INVALID_THREAD_ID: Invalid thread ID formatINVALID_SPACE_ID: Invalid space ID formatUSER_ID_MISMATCH: User ID mismatch
RATE_LIMIT_EXCEEDED: Rate limit exceeded (429)- Read operations: 100 requests/minute
- Write operations: 20 requests/minute
form_password_incorrect: Current password is incorrectform_password_pwned: Password found in data breachform_password_too_common: Password is too commonform_email_address_invalid: Invalid email addressform_email_address_already_exists: Email already in use
200 OK: Request successful400 Bad Request: Invalid input or validation error401 Unauthorized: Authentication required404 Not Found: Resource not found or doesn't belong to user429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
- Read Operations: 100 requests per minute
- Write Operations: 20 requests per minute
When rate limited, responses include:
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705315200000
Read Operations (100 req/min):
- GET
/api/notes/[id]/details - GET
/api/notes/recent - GET
/api/threads/list - GET
/api/threads/[threadId]/notes - GET
/api/spaces/items - GET
/api/user/get-profile - GET
/api/user/xp - GET
/api/tags/list - GET
/api/note-tags/list - GET
/api/search - GET
/api/scripture/check-existing - GET
/api/navigation/data - GET
/api/inbox/preview
Write Operations (20 req/min):
- POST
/api/notes/create - PUT
/api/notes/update - DELETE
/api/notes/delete - POST
/api/notes/[id]/add-thread - POST
/api/notes/[id]/remove-thread - POST
/api/threads/create - POST
/api/threads/update - DELETE
/api/threads/delete - POST
/api/spaces/create - DELETE
/api/spaces/delete - POST
/api/spaces/[spaceId]/update - POST
/api/spaces/[spaceId]/add-items - POST
/api/spaces/[spaceId]/remove-items - POST
/api/user/update-profile - POST
/api/user/update-church - POST
/api/user/update-credentials - POST
/api/tags/create - DELETE
/api/tags/delete - POST
/api/note-tags/assign - POST
/api/note-tags/remove - POST
/api/inbox/add-to-harvous - POST
/api/inbox/archive - POST
/api/inbox/unarchive
- All timestamps are in ISO 8601 format (UTC)
- All IDs follow the pattern:
{type}_{timestamp}_{random} - Content is HTML-encoded and sanitized
- Auto-tagging and XP awards are non-critical operations (won't fail the main request)
- Scripture metadata creation is non-critical (won't fail note creation)
Last Updated: January 2025