Complete API documentation for ErrorX Forum.
Production: https://yourdomain.com/api
Development: http://localhost:3000/api
Most endpoints require authentication. Include the session cookie in your requests.
- Session Cookie (recommended for web clients)
- JWT Token (for mobile/API clients)
Sign in with email and password.
Request Body:
{
"email": "user@example.com",
"password": "password123"
}Response:
{
"user": {
"id": "user_id",
"name": "User Name",
"username": "username",
"email": "user@example.com",
"image": "https://example.com/avatar.jpg"
}
}Error Responses:
400- Invalid credentials500- Server error
Sign out the current user.
Response:
{
"message": "Signed out successfully"
}Request a password reset email.
Request Body:
{
"email": "user@example.com"
}Response:
{
"message": "Password reset email sent"
}Reset password with token.
Request Body:
{
"token": "reset_token",
"password": "new_password123"
}Response:
{
"message": "Password reset successfully"
}Get all posts with pagination and filtering.
Query Parameters:
limit(optional): Number of posts per page (default: 25, max: 100)offset(optional): Number of posts to skip (default: 0)categoryId(optional): Filter by category IDauthorId(optional): Filter by author IDsearch(optional): Search term
Example Request:
GET /api/posts?limit=10&offset=0&categoryId=cat_123&search=javascript
Response:
{
"posts": [
{
"id": "post_id",
"title": "Post Title",
"content": "Post content...",
"author": {
"id": "user_id",
"name": "Author Name",
"username": "author_username",
"image": "https://example.com/avatar.jpg"
},
"category": {
"id": "category_id",
"name": "Category Name",
"description": "Category description"
},
"isPinned": false,
"isLocked": false,
"views": 42,
"likes": 5,
"replies": 3,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-01T00:00:00Z"
}
],
"pagination": {
"total": 100,
"limit": 10,
"offset": 0,
"hasMore": true
}
}Create a new post.
Request Body:
{
"title": "Post Title",
"content": "Post content...",
"categoryId": "category_id"
}Response:
{
"id": "post_id",
"title": "Post Title",
"content": "Post content...",
"author": {
"id": "user_id",
"name": "Author Name",
"username": "author_username"
},
"category": {
"id": "category_id",
"name": "Category Name"
},
"isPinned": false,
"isLocked": false,
"views": 0,
"likes": 0,
"replies": 0,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-01T00:00:00Z"
}Error Responses:
400- Validation error401- Unauthorized404- Category not found500- Server error
Get a specific post by ID.
Response:
{
"id": "post_id",
"title": "Post Title",
"content": "Post content...",
"author": {
"id": "user_id",
"name": "Author Name",
"username": "author_username",
"image": "https://example.com/avatar.jpg"
},
"category": {
"id": "category_id",
"name": "Category Name",
"description": "Category description"
},
"comments": [
{
"id": "comment_id",
"content": "Comment content...",
"author": {
"id": "user_id",
"name": "Commenter Name",
"username": "commenter_username"
},
"createdAt": "2025-01-01T00:00:00Z"
}
],
"isPinned": false,
"isLocked": false,
"views": 42,
"likes": 5,
"replies": 3,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-01T00:00:00Z"
}Update a post (author only).
Request Body:
{
"title": "Updated Post Title",
"content": "Updated post content..."
}Response:
{
"id": "post_id",
"title": "Updated Post Title",
"content": "Updated post content...",
"updatedAt": "2025-01-01T00:00:00Z"
}Delete a post (author or admin only).
Response:
{
"message": "Post deleted successfully"
}Get comments for a specific post.
Query Parameters:
limit(optional): Number of comments per page (default: 25)offset(optional): Number of comments to skip (default: 0)
Response:
{
"comments": [
{
"id": "comment_id",
"content": "Comment content...",
"author": {
"id": "user_id",
"name": "Commenter Name",
"username": "commenter_username",
"image": "https://example.com/avatar.jpg"
},
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-01T00:00:00Z"
}
],
"pagination": {
"total": 50,
"limit": 25,
"offset": 0,
"hasMore": true
}
}Create a new comment on a post.
Request Body:
{
"content": "Comment content..."
}Response:
{
"id": "comment_id",
"content": "Comment content...",
"author": {
"id": "user_id",
"name": "Commenter Name",
"username": "commenter_username"
},
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-01T00:00:00Z"
}Get all categories.
Response:
{
"categories": [
{
"id": "category_id",
"name": "Category Name",
"description": "Category description",
"postCount": 42,
"createdAt": "2025-01-01T00:00:00Z"
}
]
}Get user profile by ID.
Response:
{
"id": "user_id",
"name": "User Name",
"username": "username",
"email": "user@example.com",
"image": "https://example.com/avatar.jpg",
"bio": "User bio...",
"location": "City, Country",
"website": "https://example.com",
"joinedAt": "2025-01-01T00:00:00Z",
"postCount": 15,
"commentCount": 42
}Update user profile (owner only).
Request Body:
{
"name": "Updated Name",
"bio": "Updated bio...",
"location": "New City, Country",
"website": "https://newsite.com"
}Response:
{
"id": "user_id",
"name": "Updated Name",
"bio": "Updated bio...",
"location": "New City, Country",
"website": "https://newsite.com",
"updatedAt": "2025-01-01T00:00:00Z"
}Upload a file to Cloudflare R2.
Request Body:
{
"file": "file_data",
"userId": "user_id",
"folder": "uploads"
}Response:
{
"id": "file_id",
"filename": "example.jpg",
"url": "https://cdn.yourdomain.com/uploads/example.jpg",
"size": 1024000,
"mimeType": "image/jpeg",
"uploadedAt": "2025-01-01T00:00:00Z"
}Search across posts and users.
Query Parameters:
q(required): Search querytype(optional): Search type (posts,users,all)limit(optional): Number of results (default: 25)
Example Request:
GET /api/search?q=javascript&type=posts&limit=10
Response:
{
"results": [
{
"type": "post",
"id": "post_id",
"title": "JavaScript Tutorial",
"content": "Learn JavaScript...",
"author": {
"name": "Author Name",
"username": "author_username"
},
"score": 0.95
}
],
"query": "javascript",
"total": 25,
"limit": 10
}All endpoints may return the following error responses:
{
"error": "Validation error",
"details": "Field 'email' is required"
}{
"error": "Authentication required"
}{
"error": "Access denied"
}{
"error": "Resource not found"
}{
"error": "Internal server error"
}API endpoints are rate limited to prevent abuse:
- Authentication endpoints: 5 requests per minute
- Post creation: 10 requests per minute
- Comment creation: 20 requests per minute
- File uploads: 5 requests per minute
- Other endpoints: 100 requests per minute
curl -X POST https://yourdomain.com/api/auth/signin \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password123"}'curl -X POST https://yourdomain.com/api/posts \
-H "Content-Type: application/json" \
-H "Cookie: next-auth.session-token=your_session_token" \
-d '{"title":"New Post","content":"Post content...","categoryId":"cat_123"}'curl -X GET "https://yourdomain.com/api/posts?limit=10&offset=0" \
-H "Cookie: next-auth.session-token=your_session_token"// API client class
class ErrorXForumAPI {
private baseURL: string;
private sessionToken: string;
constructor(baseURL: string, sessionToken?: string) {
this.baseURL = baseURL;
this.sessionToken = sessionToken || '';
}
async signIn(email: string, password: string) {
const response = await fetch(`${this.baseURL}/auth/signin`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});
return response.json();
}
async getPosts(limit = 25, offset = 0) {
const response = await fetch(
`${this.baseURL}/posts?limit=${limit}&offset=${offset}`,
{
headers: {
'Cookie': `next-auth.session-token=${this.sessionToken}`,
},
}
);
return response.json();
}
async createPost(title: string, content: string, categoryId: string) {
const response = await fetch(`${this.baseURL}/posts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cookie': `next-auth.session-token=${this.sessionToken}`,
},
body: JSON.stringify({ title, content, categoryId }),
});
return response.json();
}
}
// Usage
const api = new ErrorXForumAPI('https://yourdomain.com/api', 'your_session_token');
const posts = await api.getPosts(10, 0);