Sign up
Login
New
Trending
Archive
English
English
Sign up
Login
New Paste
Add Image
# Messaging Service API Documentation ## Base URL ``` Production: https://talentlink.io.vn/api/v1 Development: http://localhost:8888/api/v1 ``` ## Authentication Tất cả các endpoints đều yêu cầu authentication token trong header: ``` Authorization: Bearer <your_jwt_token> ``` --- ## 1. Storage API - Upload Files ### Upload File to MinIO Upload ảnh/video/audio/file để sử dụng trong tin nhắn. **Endpoint:** `POST /storage/upload` **Request Headers:** ``` Authorization: Bearer <token> Content-Type: multipart/form-data ``` **Request Body:** ``` file: <binary file> (max 10MB) ``` **Allowed File Types:** - Images: image/jpeg, image/png, image/gif, image/webp - Videos: video/mp4, video/mpeg, video/quicktime - Audio: audio/mpeg, audio/wav, audio/ogg - Documents: application/pdf, application/msword, application/vnd.* **Response:** `201 Created` ```json { "url": "http://minio:9000/messaging/messages/1732546789123-photo.jpg", "filename": "photo.jpg", "mimetype": "image/jpeg", "size": 102400 } ``` **Example:** ```javascript const formData = new FormData(); formData.append('file', fileInput.files[0]); const response = await fetch('https://talentlink.io.vn/api/v1/storage/upload', { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); const data = await response.json(); console.log('File URL:', data.url); ``` --- ## 2. Conversations API ### 2.1. Create Conversation Tạo cuộc trò chuyện mới giữa 2 người hoặc group chat. **Endpoint:** `POST /conversations` **Request Body:** ```json { "participantIds": ["user-uuid-1", "user-uuid-2"], "conversationType": "direct", // "direct" hoặc "group" "conversationName": "Team Discussion" // Chỉ bắt buộc cho group } ``` **Response:** `201 Created` ```json { "id": "conv-uuid-123", "conversationType": "direct", "conversationName": null, "createdBy": "current-user-uuid", "createdAt": "2025-11-25T15:30:00.000Z", "updatedAt": "2025-11-25T15:30:00.000Z", "participants": [ { "id": "participant-1-uuid", "userId": "user-uuid-1", "conversationId": "conv-uuid-123", "lastReadAt": "2025-11-25T15:30:00.000Z", "joinedAt": "2025-11-25T15:30:00.000Z" }, { "id": "participant-2-uuid", "userId": "user-uuid-2", "conversationId": "conv-uuid-123", "lastReadAt": null, "joinedAt": "2025-11-25T15:30:00.000Z" } ] } ``` ### 2.2. Get All Conversations Lấy danh sách tất cả conversations của user hiện tại. **Endpoint:** `GET /conversations` **Response:** `200 OK` ```json [ { "id": "conv-uuid-123", "conversationType": "direct", "conversationName": null, "createdBy": "user-uuid-1", "createdAt": "2025-11-25T15:00:00.000Z", "updatedAt": "2025-11-25T15:30:00.000Z", "participants": [...], "lastMessage": { "content": "Hello!", "createdAt": "2025-11-25T15:30:00.000Z", "senderId": "user-uuid-2" }, "unreadCount": 3 } ] ``` ### 2.3. Get Conversation by ID Lấy chi tiết một conversation. **Endpoint:** `GET /conversations/:id` **Response:** `200 OK` ```json { "id": "conv-uuid-123", "conversationType": "group", "conversationName": "Team Discussion", "createdBy": "user-uuid-1", "createdAt": "2025-11-25T15:00:00.000Z", "updatedAt": "2025-11-25T15:30:00.000Z", "participants": [...] } ``` ### 2.4. Update Conversation Cập nhật tên conversation (chỉ cho group chat). **Endpoint:** `PUT /conversations/:id` **Request Body:** ```json { "conversationName": "New Team Name" } ``` **Response:** `200 OK` ```json { "id": "conv-uuid-123", "conversationType": "group", "conversationName": "New Team Name", "updatedAt": "2025-11-25T15:35:00.000Z" } ``` ### 2.5. Add Participant Thêm người vào group chat. **Endpoint:** `POST /conversations/:id/participants` **Request Body:** ```json { "userId": "new-user-uuid" } ``` **Response:** `201 Created` ```json { "id": "participant-uuid", "userId": "new-user-uuid", "conversationId": "conv-uuid-123", "joinedAt": "2025-11-25T15:40:00.000Z" } ``` ### 2.6. Remove Participant Xóa người khỏi group chat. **Endpoint:** `DELETE /conversations/:id/participants/:participantId` **Response:** `200 OK` ```json { "message": "Participant removed successfully" } ``` ### 2.7. Delete Conversation Xóa conversation (chỉ creator mới được xóa). **Endpoint:** `DELETE /conversations/:id` **Response:** `200 OK` ```json { "message": "Conversation deleted successfully" } ``` --- ## 3. Messages API ### 3.1. Send Message Gửi tin nhắn mới trong conversation. **Endpoint:** `POST /messages` **Request Body:** ```json { "conversationId": "conv-uuid-123", "content": "Hello everyone!", "attachmentUrl": "http://minio:9000/messaging/messages/1732546789123-photo.jpg", // Optional "attachmentType": "image" // Optional: "image", "video", "audio", "file" } ``` **Response:** `201 Created` ```json { "id": "msg-uuid-456", "conversationId": "conv-uuid-123", "senderId": "current-user-uuid", "content": "Hello everyone!", "attachmentUrl": "http://minio:9000/messaging/messages/1732546789123-photo.jpg", "attachmentType": "image", "isEdited": false, "isDeleted": false, "createdAt": "2025-11-25T15:45:00.000Z", "updatedAt": "2025-11-25T15:45:00.000Z" } ``` **Flow gửi tin nhắn có ảnh:** ```javascript // Bước 1: Upload ảnh const formData = new FormData(); formData.append('file', imageFile); const uploadResponse = await fetch('/api/v1/storage/upload', { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); const { url } = await uploadResponse.json(); // Bước 2: Gửi tin nhắn với URL ảnh const messageResponse = await fetch('/api/v1/messages', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ conversationId: 'conv-uuid-123', content: 'Check out this photo!', attachmentUrl: url, attachmentType: 'image' }) }); ``` ### 3.2. Get Messages from Conversation Lấy danh sách tin nhắn trong conversation (có phân trang). **Endpoint:** `GET /messages/conversation/:conversationId` **Query Parameters:** - `limit` (optional): Số lượng messages (default: 50) - `before` (optional): Lấy messages trước timestamp này (ISO 8601 format) **Example:** ``` GET /messages/conversation/conv-uuid-123?limit=20&before=2025-11-25T15:00:00.000Z ``` **Response:** `200 OK` ```json { "messages": [ { "id": "msg-uuid-456", "conversationId": "conv-uuid-123", "senderId": "user-uuid-1", "content": "Hello!", "attachmentUrl": null, "attachmentType": null, "isEdited": false, "isDeleted": false, "createdAt": "2025-11-25T15:45:00.000Z", "updatedAt": "2025-11-25T15:45:00.000Z", "readBy": [ { "userId": "user-uuid-2", "readAt": "2025-11-25T15:46:00.000Z" } ] } ], "hasMore": true, "nextBefore": "2025-11-25T15:40:00.000Z" } ``` **Pagination Example:** ```javascript // Load tin nhắn ban đầu let messages = []; let nextBefore = null; async function loadMessages(conversationId) { const url = nextBefore ? `/api/v1/messages/conversation/${conversationId}?limit=20&before=${nextBefore}` : `/api/v1/messages/conversation/${conversationId}?limit=20`; const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); messages = [...messages, ...data.messages]; nextBefore = data.nextBefore; return data.hasMore; // true nếu còn tin nhắn cũ hơn } // Load more khi scroll lên đầu if (await loadMessages('conv-uuid-123')) { console.log('Has more messages to load'); } ``` ### 3.3. Get Single Message Lấy chi tiết một tin nhắn. **Endpoint:** `GET /messages/:id` **Response:** `200 OK` ```json { "id": "msg-uuid-456", "conversationId": "conv-uuid-123", "senderId": "user-uuid-1", "content": "Hello!", "attachmentUrl": null, "attachmentType": null, "isEdited": false, "isDeleted": false, "createdAt": "2025-11-25T15:45:00.000Z", "updatedAt": "2025-11-25T15:45:00.000Z" } ``` ### 3.4. Update Message Chỉnh sửa tin nhắn (chỉ người gửi mới được sửa). **Endpoint:** `PUT /messages/:id` **Request Body:** ```json { "content": "Updated message content" } ``` **Response:** `200 OK` ```json { "id": "msg-uuid-456", "content": "Updated message content", "isEdited": true, "updatedAt": "2025-11-25T15:50:00.000Z" } ``` ### 3.5. Mark Message as Read Đánh dấu một tin nhắn đã đọc. **Endpoint:** `POST /messages/:id/read` **Response:** `200 OK` ```json { "message": "Message marked as read" } ``` ### 3.6. Mark All Messages in Conversation as Read Đánh dấu tất cả tin nhắn trong conversation đã đọc. **Endpoint:** `POST /messages/conversation/:conversationId/read` **Response:** `200 OK` ```json { "message": "All messages marked as read" } ``` ### 3.7. Get Unread Count Lấy số lượng tin nhắn chưa đọc trong conversation. **Endpoint:** `GET /messages/conversation/:conversationId/unread-count` **Response:** `200 OK` ```json { "conversationId": "conv-uuid-123", "unreadCount": 5 } ``` ### 3.8. Delete Message Xóa tin nhắn (chỉ người gửi mới được xóa). **Endpoint:** `DELETE /messages/:id` **Response:** `200 OK` ```json { "message": "Message deleted successfully" } ``` --- ## 4. WebSocket Events WebSocket được sử dụng cho real-time messaging. Kết nối qua Socket.IO. ### Connection ```javascript import io from 'socket.io-client'; const socket = io('https://talentlink.io.vn', { path: '/socket.io', auth: { token: 'your_jwt_token' } }); socket.on('connect', () => { console.log('Connected to messaging server'); }); ``` ### 4.1. Join Conversation Join vào conversation để nhận real-time updates. **Event:** `conversation:join` **Emit:** ```javascript socket.emit('conversation:join', { conversationId: 'conv-uuid-123' }); ``` **Response:** ```javascript socket.on('conversation:joined', (data) => { console.log('Joined conversation:', data.conversationId); }); ``` ### 4.2. Leave Conversation Rời khỏi conversation. **Event:** `conversation:leave` **Emit:** ```javascript socket.emit('conversation:leave', { conversationId: 'conv-uuid-123' }); ``` ### 4.3. Send Message (Real-time) Gửi tin nhắn qua WebSocket. **Event:** `message:send` **Emit:** ```javascript socket.emit('message:send', { conversationId: 'conv-uuid-123', content: 'Hello from WebSocket!', attachmentUrl: null, attachmentType: null }); ``` **Receive (all participants in conversation):** ```javascript socket.on('message:new', (message) => { console.log('New message:', message); // { // id: 'msg-uuid-456', // conversationId: 'conv-uuid-123', // senderId: 'user-uuid-1', // content: 'Hello from WebSocket!', // createdAt: '2025-11-25T15:55:00.000Z' // } }); ``` ### 4.4. Edit Message (Real-time) Chỉnh sửa tin nhắn qua WebSocket. **Event:** `message:edit` **Emit:** ```javascript socket.emit('message:edit', { messageId: 'msg-uuid-456', content: 'Updated content' }); ``` **Receive:** ```javascript socket.on('message:edited', (data) => { console.log('Message edited:', data); // { // messageId: 'msg-uuid-456', // content: 'Updated content', // isEdited: true, // updatedAt: '2025-11-25T16:00:00.000Z' // } }); ``` ### 4.5. Delete Message (Real-time) Xóa tin nhắn qua WebSocket. **Event:** `message:delete` **Emit:** ```javascript socket.emit('message:delete', { messageId: 'msg-uuid-456' }); ``` **Receive:** ```javascript socket.on('message:deleted', (data) => { console.log('Message deleted:', data.messageId); }); ``` ### 4.6. Mark as Read (Real-time) Đánh dấu tin nhắn đã đọc qua WebSocket. **Event:** `message:read` **Emit:** ```javascript socket.emit('message:read', { messageId: 'msg-uuid-456' }); ``` **Receive:** ```javascript socket.on('message:read', (data) => { console.log('Message read by:', data); // { // messageId: 'msg-uuid-456', // userId: 'user-uuid-2', // readAt: '2025-11-25T16:05:00.000Z' // } }); ``` ### 4.7. Typing Indicators Hiển thị khi ai đó đang typing. **Start Typing:** ```javascript socket.emit('typing:start', { conversationId: 'conv-uuid-123' }); ``` **Stop Typing:** ```javascript socket.emit('typing:stop', { conversationId: 'conv-uuid-123' }); ``` **Receive:** ```javascript socket.on('user:typing', (data) => { console.log(`${data.userId} is typing in ${data.conversationId}`); }); socket.on('user:stopped-typing', (data) => { console.log(`${data.userId} stopped typing`); }); ``` --- ## 5. Error Responses Tất cả errors đều có format sau: ```json { "error": "Error Type", "message": "Detailed error message", "statusCode": 400 } ``` ### Common Error Codes: - `400 Bad Request` - Invalid request body hoặc parameters - `401 Unauthorized` - Missing hoặc invalid authentication token - `403 Forbidden` - User không có quyền thực hiện action - `404 Not Found` - Resource không tồn tại - `500 Internal Server Error` - Server error ### Example Errors: **Missing Authentication:** ```json { "error": "Unauthorized", "message": "Authentication token is required", "statusCode": 401 } ``` **Invalid File Type:** ```json { "error": "Bad Request", "message": "Invalid file type. Only images, videos, audio, and documents are allowed", "statusCode": 400 } ``` **File Too Large:** ```json { "error": "Bad Request", "message": "File size exceeds 10MB", "statusCode": 400 } ``` --- ## 6. Complete Example: Chat Application Flow ### Initialize Connection ```javascript // 1. Setup Socket.IO connection const socket = io('https://talentlink.io.vn', { path: '/socket.io', auth: { token: authToken } }); // 2. Load conversations list const conversationsResponse = await fetch('/api/v1/conversations', { headers: { 'Authorization': `Bearer ${authToken}` } }); const conversations = await conversationsResponse.json(); // 3. Join a conversation socket.emit('conversation:join', { conversationId: conversations[0].id }); // 4. Load messages const messagesResponse = await fetch( `/api/v1/messages/conversation/${conversations[0].id}?limit=50`, { headers: { 'Authorization': `Bearer ${authToken}` }} ); const { messages } = await messagesResponse.json(); ``` ### Send Message with Image ```javascript async function sendImageMessage(conversationId, imageFile, text) { // Step 1: Upload image const formData = new FormData(); formData.append('file', imageFile); const uploadResponse = await fetch('/api/v1/storage/upload', { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}` }, body: formData }); const { url } = await uploadResponse.json(); // Step 2: Send message with image URL socket.emit('message:send', { conversationId, content: text, attachmentUrl: url, attachmentType: 'image' }); } ``` ### Listen for Real-time Updates ```javascript // New message received socket.on('message:new', (message) => { addMessageToUI(message); // Mark as read if conversation is active if (isConversationActive(message.conversationId)) { socket.emit('message:read', { messageId: message.id }); } }); // Message edited socket.on('message:edited', (data) => { updateMessageInUI(data.messageId, data.content); }); // Message deleted socket.on('message:deleted', (data) => { removeMessageFromUI(data.messageId); }); // Typing indicator socket.on('user:typing', (data) => { showTypingIndicator(data.userId, data.conversationId); }); socket.on('user:stopped-typing', (data) => { hideTypingIndicator(data.userId); }); ``` ### Handle Typing Indicator ```javascript let typingTimeout; function onUserTyping(conversationId) { socket.emit('typing:start', { conversationId }); clearTimeout(typingTimeout); typingTimeout = setTimeout(() => { socket.emit('typing:stop', { conversationId }); }, 3000); // Stop after 3s of inactivity } ``` --- ## 7. Best Practices ### 1. File Upload - Luôn validate file size ở client trước khi upload (max 10MB) - Show progress bar khi upload file lớn - Cache uploaded URLs để tránh upload lại cùng một file ### 2. Message Pagination - Load 20-50 messages ban đầu - Implement infinite scroll để load thêm messages cũ - Cache messages đã load để tránh refetch ### 3. Real-time Updates - Luôn join conversation trước khi hiển thị chat UI - Leave conversation khi user rời khỏi chat screen - Reconnect socket khi mất kết nối ### 4. Read Receipts - Mark messages as read ngay khi hiển thị trên màn hình - Batch multiple read receipts thành một request - Update UI immediately, không cần đợi server response ### 5. Error Handling - Implement retry logic cho failed uploads - Show user-friendly error messages - Cache failed messages để user có thể retry ### 6. Performance - Debounce typing indicators - Lazy load images và videos - Implement virtual scrolling cho long message lists --- ## 8. Testing ### Test với cURL **Upload file:** ```bash curl -X POST https://talentlink.io.vn/api/v1/storage/upload \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "file=@/path/to/image.jpg" ``` **Send message:** ```bash curl -X POST https://talentlink.io.vn/api/v1/messages \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "conversationId": "conv-uuid-123", "content": "Hello!", "attachmentUrl": null, "attachmentType": null }' ``` **Get messages:** ```bash curl https://talentlink.io.vn/api/v1/messages/conversation/conv-uuid-123?limit=20 \ -H "Authorization: Bearer YOUR_TOKEN" ``` --- ## 9. Swagger Documentation Interactive API documentation có sẵn tại: ``` http://localhost:8081/swagger ``` Swagger UI cho phép test tất cả endpoints directly từ browser.
Settings
Title :
[Optional]
Paste Folder :
[Optional]
Select
Syntax :
[Optional]
Select
Markup
CSS
JavaScript
Bash
C
C#
C++
Java
JSON
Lua
Plaintext
C-like
ABAP
ActionScript
Ada
Apache Configuration
APL
AppleScript
Arduino
ARFF
AsciiDoc
6502 Assembly
ASP.NET (C#)
AutoHotKey
AutoIt
Basic
Batch
Bison
Brainfuck
Bro
CoffeeScript
Clojure
Crystal
Content-Security-Policy
CSS Extras
D
Dart
Diff
Django/Jinja2
Docker
Eiffel
Elixir
Elm
ERB
Erlang
F#
Flow
Fortran
GEDCOM
Gherkin
Git
GLSL
GameMaker Language
Go
GraphQL
Groovy
Haml
Handlebars
Haskell
Haxe
HTTP
HTTP Public-Key-Pins
HTTP Strict-Transport-Security
IchigoJam
Icon
Inform 7
INI
IO
J
Jolie
Julia
Keyman
Kotlin
LaTeX
Less
Liquid
Lisp
LiveScript
LOLCODE
Makefile
Markdown
Markup templating
MATLAB
MEL
Mizar
Monkey
N4JS
NASM
nginx
Nim
Nix
NSIS
Objective-C
OCaml
OpenCL
Oz
PARI/GP
Parser
Pascal
Perl
PHP
PHP Extras
PL/SQL
PowerShell
Processing
Prolog
.properties
Protocol Buffers
Pug
Puppet
Pure
Python
Q (kdb+ database)
Qore
R
React JSX
React TSX
Ren'py
Reason
reST (reStructuredText)
Rip
Roboconf
Ruby
Rust
SAS
Sass (Sass)
Sass (Scss)
Scala
Scheme
Smalltalk
Smarty
SQL
Soy (Closure Template)
Stylus
Swift
TAP
Tcl
Textile
Template Toolkit 2
Twig
TypeScript
VB.Net
Velocity
Verilog
VHDL
vim
Visual Basic
WebAssembly
Wiki markup
Xeora
Xojo (REALbasic)
XQuery
YAML
HTML
Expiration :
[Optional]
Never
Self Destroy
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Status :
[Optional]
Public
Unlisted
Private (members only)
Password :
[Optional]
Description:
[Optional]
Tags:
[Optional]
Encrypt Paste
(
?
)
Create Paste
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Site Languages
×
English