Messages Since
Query · messagesSince
messagesSince(afterSequence: Int!, conversationId: ID!, first: Int! = 50): MessagePage!
Lấy các tin nhắn có sequence lớn hơn mốc client đã giữ, theo thứ tự tăng dần. Dùng sau khi WebSocket kết nối lại hoặc khi nghi ngờ bỏ lỡ sự kiện: subscription chỉ thông báo theo thời gian thực, còn query này đọc dữ liệu đã lưu. Bắt đầu bằng afterSequence: 0 để lấy từ đầu conversation. Query không tự cập nhật mốc đã đọc.
Gửi query qua HTTP POST /graphql với Authorization: Bearer <accessToken>. Người gọi phải là thành viên conversation. Tin đã xóa mềm vẫn nằm trong luồng sequence nhưng có content: null và không có tệp đính kèm.
Input
| Đối số | Kiểu GraphQL | Bắt buộc | Quy tắc và ý nghĩa |
|---|---|---|---|
afterSequence | Int! | Có | Sequence cuối cùng client đã giữ; số nguyên không âm, 0 hợp lệ. Chỉ trả tin có sequence lớn hơn mốc này. Không có giá trị mặc định. |
conversationId | ID! | Có | UUID của conversation; không có giá trị mặc định. |
first | Int! | Không nếu bỏ qua | Số tin tối đa trong một trang, từ 1 đến 100; mặc định 50. Không nhận null. |
Output
Trả về MessagePage!, không null. nodes tăng dần theo sequence. Nếu hasNextPage là true, gọi tiếp với afterSequence bằng sequence của tin cuối trong nodes; endCursor chỉ biểu thị mốc cuối trang, không phải đối số của query này. Trang rỗng có endCursor: null.
MessagePage
| Trường | Kiểu GraphQL | Ý nghĩa |
|---|---|---|
nodes | [MessageView!]! | Tin nhắn mới hơn mốc đã cho; danh sách và phần tử không null. Xem MessageView. |
endCursor | String | Cursor mã hóa conversation và sequence mới nhất trong trang, hoặc null nếu rỗng. |
hasNextPage | Boolean! | true nếu còn tin mới hơn sau trang này. |
MessageView
| Trường | Kiểu GraphQL | Ý nghĩa |
|---|---|---|
id | ID! | ID tin nhắn trên server. |
clientMessageId | String! | ID client gửi, dùng đối chiếu retry và tin nhắn lạc quan. |
conversationId | ID! | Conversation chứa tin nhắn. |
senderId | ID! | Người gửi. |
sequence | Int! | Thứ tự tăng trong conversation. |
type | MessageType! | TEXT cho tin do người dùng gửi; schema còn có SYSTEM. |
content | String | Nội dung hoặc null khi đã xóa mềm; có thể rỗng khi chỉ gửi tệp. |
replyToMessageId | ID | ID tin được trả lời hoặc null. |
replyTo | MessageSummary | Tóm tắt tin được trả lời hoặc null; xem MessageSummary. |
createdAt | DateTime! | Thời điểm tạo. |
updatedAt | DateTime! | Thời điểm cập nhật. |
deletedAt | DateTime | Thời điểm xóa mềm hoặc null. |
attachments | [MessageAttachmentView!]! | Tệp còn truy cập được; rỗng khi tin đã xóa. Xem MessageAttachmentView. |
reactions | [ReactionSummary!]! | Phản ứng nhóm theo emoji. Xem ReactionSummary. |
MessageSummary
| Trường | Kiểu GraphQL | Ý nghĩa |
|---|---|---|
id | ID! | ID tin được trả lời. |
senderId | ID! | Người gửi tin đó. |
content | String | Nội dung hoặc null nếu đã xóa. |
deletedAt | DateTime | Thời điểm xóa mềm hoặc null. |
MessageAttachmentView
| Trường | Kiểu GraphQL | Ý nghĩa |
|---|---|---|
id | ID! | ID tệp đính kèm. |
fileName | String! | Tên tệp hiển thị. |
contentType | String! | MIME type. |
size | Int! | Kích thước byte do client báo khi gửi. |
ReactionSummary
| Trường | Kiểu GraphQL | Ý nghĩa |
|---|---|---|
emoji | String! | Emoji phản ứng. |
userIds | [ID!]! | ID những người đã dùng emoji này; danh sách và phần tử không null. |
Ví dụ
query MessagesSince($conversationId: ID!, $afterSequence: Int!, $first: Int!) {
messagesSince(conversationId: $conversationId, afterSequence: $afterSequence, first: $first) {
nodes {
id
clientMessageId
conversationId
senderId
sequence
type
content
replyToMessageId
replyTo { id senderId content deletedAt }
createdAt
updatedAt
deletedAt
attachments { id fileName contentType size }
reactions { emoji userIds }
}
endCursor
hasNextPage
}
}
Biến:
{
"conversationId": "33333333-3333-4333-8333-333333333333",
"afterSequence": 3,
"first": 1
}
Phản hồi minh họa:
{
"data": {
"messagesSince": {
"nodes": [
{
"id": "44444444-4444-4444-8444-444444444444",
"clientMessageId": "send-004",
"conversationId": "33333333-3333-4333-8333-333333333333",
"senderId": "11111111-1111-4111-8111-111111111111",
"sequence": 4,
"type": "TEXT",
"content": "Chào bạn",
"replyToMessageId": null,
"replyTo": null,
"createdAt": "2026-09-26T09:00:00.000Z",
"updatedAt": "2026-09-26T09:00:00.000Z",
"deletedAt": null,
"attachments": [],
"reactions": []
}
],
"endCursor": "WyIzMzMzMzMzMy0zMzMzLTQzMzMtODMzMy0zMzMzMzMzMzMzMzMiLCI0Il0",
"hasNextPage": true
}
}
}
Nếu còn trang, gọi tiếp với afterSequence: 4. Thiếu hoặc sai access token trả UNAUTHENTICATED; ID conversation sai định dạng, afterSequence âm hoặc first ngoài 1–100 trả BAD_USER_INPUT. Không phải thành viên nhận FORBIDDEN.
Chữ ký operation được tạo từ GraphQL schema.