# Internet Engineering Blog API — Complete Specification
**Base URL:** `http://localhost:9092/api`
**Version:** 2.0
**Data format:** JSON (all requests & responses)
**Encoding:** UTF‑8
---
## Table of Contents
1. [Authentication & General Notes](#authentication--general-notes)
2. [Common Response Structures](#common-response-structures)
3. [Authentication Endpoints](#authentication-endpoints)
4. [Articles](#articles)
5. [Comments](#comments)
6. [Likes](#likes)
7. [Tags](#tags)
8. [Users](#users)
9. [Bookmarks](#bookmarks)
10. [Profile](#profile)
11. [Notifications](#notifications)
12. [Citations](#citations)
13. [User Analytics](#user-analytics)
14. [Admin Panel](#admin-panel)
15. [Messaging – One‑to‑One](#messaging--onetoone)
16. [Messaging – Groups](#messaging--groups)
17. [Media Uploads](#media-uploads)
18. [Reactions](#reactions)
19. [Polls](#polls)
20. [Typing Indicators](#typing-indicators)
21. [Pinned Messages](#pinned-messages)
22. [Search](#search)
23. [User Search (Mentions)](#user-search-mentions)
24. [Muting Groups](#muting-groups)
25. [Rate Limiting & Error Codes](#rate-limiting--error-codes)
---
## Authentication & General Notes
### Authentication Methods
The API supports both **cookie‑based** sessions and **Bearer token** headers.
- **Cookies** – set automatically after login; the client should send credentials with every request (`credentials: 'include'`).
- **Bearer token** – obtained via `POST /login` and sent in the `Authorization` header.
- **CSRF Protection** – state‑changing requests (POST, PUT, DELETE) must include a custom header:
`X-CSRF-Token: <csrf_token>`
The token is returned in the login response and can be read from the (non‑HttpOnly) cookie or from the JSON body.
### Rate Limiting
Public endpoints are limited to 60 requests per minute per IP.
Authenticated endpoints are limited to 120 requests per minute per user.
Messaging endpoints have stricter limits – see the [Rate Limiting](#rate-limiting--error-codes) section.
---
## Common Response Structures
**Success:** 200/201 with the expected payload.
204 No Content for successful DELETE or actions with no return body.
**Client Errors:**
`400 Bad Request` – validation error
`401 Unauthorized` – missing / expired token or session
`403 Forbidden` – insufficient permissions
`404 Not Found` – resource not found
`409 Conflict` – duplicate resource
`429 Too Many Requests` – rate limit exceeded
**Server Error:**
`500 Internal Server Error`
All error bodies for new messaging endpoints follow the envelope form (with `"ok":false`).
Older endpoints (articles, comments, etc.) retain the legacy format:
```json
{
"error": "Human‑readable message",
"details": [ "Optional" ]
}
For new endpoints, errors also include a numeric error_code and an optional description:
{
"ok": false,
"error_code": 400,
"description": "Validation error"
}
Messaging – One‑to‑One
Conversations
GET /api/conversations
Return the list of one‑on‑one conversations for the authenticated user.
Auth – required (cookie or Bearer).
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Max conversations returned |
after |
integer | – | Cursor: return conversations with last message id > after (for pagination) |
Success – 200 OK
{
"ok": true,
"result": [
{
"with": "username",
"lastMessage": "Hello!",
"lastTime": "2025-04-10T14:23:00",
"unread": 2
}
]
}
Errors
401if not authenticated.
DELETE /api/conversations/{username}
Delete the entire conversation with the specified user.
Auth – required.
Success – 200 OK ({"ok":true,"result":true})
Messages
GET /api/conversations/{username}/messages
Fetch messages between the current user and another user. Supports cursor‑based pagination.
Auth – required.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Max messages to return |
after |
integer | – | Return messages with id > after (newer) |
before |
integer | – | Return messages with id < before (older) |
Success – 200 OK
{
"ok": true,
"result": [
{
"id": 123,
"from": "ali_tehrani",
"to": "m_bagheri",
"body": "Hello!",
"sentAt": "2025-04-10T14:22:00",
"read": true
}
]
}
POST /api/conversations/{username}/messages
Send a message to a user.
Auth – required.
Request body
{
"body": "string, required, max 5000 chars"
}
Success – 201 Created – returns the created message object.
Errors
400if body missing or too long.404if target user does not exist.
POST /api/conversations/{username}/read
Mark all messages from the specified user as read.
Auth – required.
Success – 200 OK ({"ok":true,"result":true})
POST /api/conversations/{username}/typing
Notify that the current user is typing. Typing status expires after 5 seconds.
Auth – required.
Body – empty.
Success – 200 OK
GET /api/conversations/{username}/typing
Check if the specified user is currently typing.
Auth – required.
Success – 200 OK
{
"ok": true,
"result": { "typing": true }
}
GET /api/conversations/{username}/read-status
Get the last read message ID for both participants.
Auth – required.
Success – 200 OK
{
"ok": true,
"result": {
"lastReadMessageId": 120
}
}
Messaging – Groups
Group Management
GET /api/groups
List all groups the current user is a member of.
Auth – required.
Success – 200 OK – array of group objects.
POST /api/groups
Create a new group. The creator automatically becomes an admin and member.
Auth – required.
Request body
{
"name": "string, required, max 100 chars",
"description": "optional, max 500 chars",
"members": [1, 2, 3] // array of user IDs (optional)
}
Success – 201 Created – returns the created group object.
GET /api/groups/{groupId}
Get group information.
Auth – required.
Success – 200 OK – group object.
PUT /api/groups/{groupId}
Update group settings (name, description, slow mode, avatar).
Auth – admin only.
Request body (all optional)
{
"name": "string",
"description": "string",
"slowMode": true,
"slowModeSeconds": 30,
"avatarUrl": "string"
}
Success – 200 OK
DELETE /api/groups/{groupId}
Delete a group. Auth – admin only.
Success – 200 OK
Membership
GET /api/groups/{groupId}/members
Return a list of members with their admin status.
Auth – group member.
Success – 200 OK
{
"ok": true,
"result": [
{ "userId": 1, "isAdmin": true },
{ "userId": 2, "isAdmin": false }
]
}
POST /api/groups/{groupId}/members
Add one or more members to the group. Auth – admin only.
Request body
{
"members": [ 4, 5 ]
}
Success – 200 OK
DELETE /api/groups/{groupId}/members/{memberId}
Remove a member (or kick). Auth – admin only.
Success – 200 OK
POST /api/groups/{groupId}/members/{memberId}/promote
Promote a member to admin. Auth – admin only.
Success – 200 OK
POST /api/groups/{groupId}/members/{memberId}/demote
Demote an admin back to member. Auth – admin only.
Success – 200 OK
POST /api/groups/{groupId}/leave
Leave the group. Auth – required.
Success – 200 OK
Group Messages
GET /api/groups/{groupId}/messages
Fetch messages in a group with cursor‑based pagination.
Auth – member of the group.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Max messages |
after |
integer | – | Return messages with id > after (newer) |
before |
integer | – | Return messages with id < before (older) |
Success – 200 OK – array of group message objects (enriched with reactions, media, poll info).
POST /api/groups/{groupId}/messages
Send a message to a group.
Auth – member of the group.
Request body (all optional except body)
{
"body": "string, required",
"replyTo": 123, // message ID being replied to
"mentions": [ 1, 2 ], // user IDs to mention
"media": [ 99, 100 ], // uploaded media IDs
"pollId": 10, // poll ID (if the message is a poll)
"keyboard": "{...}" // inline keyboard JSON
}
Success – 201 Created – returns the created message.
Errors
400if body missing.403if not a group member.429if slow mode is active.
DELETE /api/groups/{groupId}/messages/{messageId}
Delete a message. Auth – sender or group admin.
Success – 200 OK
PUT /api/groups/{groupId}/messages/{messageId}
Edit a message. Auth – sender.
Request body {"body": "new text"}
Success – 200 OK
POST /api/groups/{groupId}/messages/{messageId}/forward
Forward a message to another group (or the same).
Auth – group member.
Request body {"toGroupId": 456}
Success – 201 Created – returns the new forwarded message.
POST /api/groups/{groupId}/messages/bulk-delete
Delete a list of messages. Auth – group admin.
Request body {"messageIds": [1,2,3]}
Success – 200 OK with {"deleted": 3}
POST /api/groups/{groupId}/read
Mark the group as read (sets last read timestamp).
Auth – member.
Success – 200 OK
GET /api/groups/{groupId}/read-status
Return the last read timestamp for each member.
Auth – member.
Success – array of { userId, lastRead }
Media Uploads
POST /api/media/upload
Upload a file (image, video, audio, document) as a Base64 data‑URL.
Maximum file size: 10 MB.
Auth – required.
Request body
{
"file": "data:image/png;base64,iVBOR...",
"fileName": "optional.png"
}
Success – 201 Created
{
"ok": true,
"result": {
"mediaId": 1,
"url": "/uploads/media/...",
"thumbnail": "base64..." // only for images
}
}
Errors
400if file is missing or invalid.413if file too large.
GET /api/media/{mediaId}
Retrieve a media file’s metadata.
Auth – required.
Success – media object.
Reactions
POST /api/messages/{messageId}/reactions
Toggle a reaction on a message (both one‑on‑one and group).
If the user already reacted with the same emoji, it is removed.
Otherwise, the reaction is added.
Auth – required.
Request body {"emoji": "❤️"}
Success – 200 OK
Note: The client should optimistically update the UI.
GET /api/messages/{messageId}/reactions
Get all reactions for a message.
Auth – required.
Success – array of { userId, emoji }
Polls
POST /api/groups/{groupId}/polls
Create a new poll in a group.
Auth – group member.
Request body
{
"question": "string, required",
"options": ["Option 1", "Option 2"], // 2‑10 options
"multipleAnswers": false, // allow multiple choice
"shuffleOptions": false, // randomise options order
"closeDate": 1712345678000 // optional, epoch millis
}
Success – 201 Created – poll object.
Errors
400if fewer than 2 or more than 10 options.
GET /api/polls/{pollId}
Get poll details (including current results).
Auth – required (any member of the group).
POST /api/polls/{pollId}/vote
Vote on a poll.
Auth – required (must be a group member).
Request body
For single‑choice polls: {"optionId": 1}
For multiple‑choice polls: {"optionIds": [1, 3]}
Success – 200 OK
Errors – 400 if poll is closed or invalid option, 409 if already voted (for single‑choice).
POST /api/polls/{pollId}/close
Close a poll. Auth – poll creator or group admin.
Success – 200 OK
POST /api/polls/{pollId}/reopen
Reopen a closed poll. Auth – poll creator or group admin.
Success – 200 OK
DELETE /api/polls/{pollId}
Delete a poll. Auth – poll creator or group admin.
Success – 200 OK
Typing Indicators
POST /api/conversations/{username}/typing
Already described in One‑to‑One section.
GET /api/conversations/{username}/typing
Already described in One‑to‑One section.
POST /api/groups/{groupId}/typing
Notify that the user is typing in a group. Typing status expires after 5 seconds.
Auth – required.
Success – 204 No Content
GET /api/groups/{groupId}/typing
Return a list of user IDs currently typing in the group.
Auth – group member.
Success – 200 OK
{
"ok": true,
"result": [ 1, 2 ]
}
Pinned Messages
POST /api/groups/{groupId}/pin/{messageId}
Pin a message. It will appear at the top of the pinned list.
Auth – group admin.
Success – 200 OK
DELETE /api/groups/{groupId}/pin/{messageId}
Unpin a message. Auth – group admin.
Success – 200 OK
GET /api/groups/{groupId}/pins
List all pinned message IDs. Auth – group member.
Success – array of message IDs.
Search
GET /api/conversations/search
Search one‑on‑one messages for the authenticated user.
Auth – required.
Query parametersq (required), limit (optional, default 50)
Success – 200 OK – array of matching messages.
GET /api/groups/{groupId}/search
Search messages inside a group.
Auth – group member.
Query parametersq (required), limit (optional, default 50)
Success – 200 OK – array of matching group messages.
User Search (Mentions)
GET /api/users/search
Search for users by username (for mentions / starting conversations).
Auth – required.
Query parameter q (required, minimum 2 characters)
Success – 200 OK
{
"ok": true,
"result": [
{ "id": 1, "username": "ali_tehrani", "fullName": "Ali Tehrani", "avatarUrl": "..." }
]
}
Muting Groups
POST /api/groups/{groupId}/mute
Mute notifications for a group.
Auth – required (any member).
Success – 200 OK
DELETE /api/groups/{groupId}/mute
Unmute notifications.
Auth – required.
Success – 200 OK
Rate Limiting & Error Codes
| Error Code | Meaning |
|---|---|
| 400 | Bad Request – missing or invalid parameters |
| 401 | Unauthorized – authentication required |
| 403 | Forbidden – not enough permissions |
| 404 | Not Found – resource doesn’t exist |
| 409 | Conflict – duplicate or conflicting state |
| 429 | Too Many Requests – rate limit exceeded |
Rate limit headers
All responses include the headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (epoch seconds) to inform the client of the current status.
End of API specification ```
Xet Storage Details
- Size:
- 16.1 kB
- Xet hash:
- 507c48503c0150eeeb4d3ae2647944301362e79c886120869a075c63d56653ed
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.