API Backend — Rune Courier¶
Visao Geral¶
O backend expoe REST (/bff/*) para CRUD e WebSocket (/ws/chat) para tempo real.
Base URL: http://localhost:5060
Autenticacao¶
Todas as requisicoes REST (exceto /health) exigem:
O WebSocket recebe esses dados como query params na conexao.
Conversas¶
Listar conversas¶
GET /bff/conversations
Retorna conversas do usuario autenticado no tenant, ordenadas por ultima atividade.
Response 200:
[
{
"id": "uuid",
"type": "DIRECT",
"name": null,
"participants": [
{
"userId": "uuid",
"email": "[email protected]",
"name": "Joao",
"role": "MEMBER",
"isActive": true
}
],
"lastMessage": {
"content": "Ola!",
"senderName": "Maria",
"contentType": "TEXT",
"createdAt": "2026-02-17T10:00:00Z"
},
"unreadCount": 3,
"createdAt": "2026-02-17T09:00:00Z",
"updatedAt": "2026-02-17T10:00:00Z"
}
]
Criar conversa¶
POST /bff/conversations
Request:
{
"type": "GROUP",
"name": "Equipe Recepcao",
"participantIds": ["uuid-1", "uuid-2"],
"metadata": { "channel": "INTERNAL" }
}
O criador e automaticamente adicionado como ADMIN.
Encontrar ou criar conversa direta¶
POST /bff/conversations/direct
Encontra conversa 1:1 existente ou cria uma nova. Previne duplicatas.
Request:
{
"targetUserId": "uuid",
"targetEmail": "[email protected]",
"targetName": "Maria"
}
Obter conversa¶
GET /bff/conversations/{id}
Atualizar conversa¶
PUT /bff/conversations/{id}
Request:
Adicionar participante¶
POST /bff/conversations/{id}/participants
Request:
{
"userId": "uuid",
"email": "[email protected]",
"name": "Carlos"
}
Marcar como lido¶
POST /bff/conversations/{id}/read
Marca todas as mensagens ate messageId como lidas.
Request:
Mensagens¶
Listar mensagens¶
GET /bff/conversations/{conversationId}/messages
Paginacao por cursor (mais recentes primeiro).
Query params:
| Param | Tipo | Default | Descricao |
|---|---|---|---|
before |
UUID | - | Mensagens antes deste ID |
limit |
int | 50 | Quantidade (max 100) |
Response 200:
[
{
"id": "uuid",
"conversationId": "uuid",
"senderId": "uuid",
"senderEmail": "[email protected]",
"senderName": "Joao",
"content": "Bom dia!",
"contentType": "TEXT",
"replyToId": null,
"isEdited": false,
"isDeleted": false,
"metadata": {},
"createdAt": "2026-02-17T10:00:00Z",
"updatedAt": null
}
]
Enviar mensagem¶
POST /bff/conversations/{conversationId}/messages
A mensagem e criada no banco e broadcast via WebSocket para todos os participantes online.
Request:
Editar mensagem¶
PUT /bff/conversations/{conversationId}/messages/{messageId}
Apenas o remetente pode editar. Marca isEdited = true.
Request:
Deletar mensagem¶
DELETE /bff/conversations/{conversationId}/messages/{messageId}
Soft-delete — marca isDeleted = true e limpa o conteudo.
Status¶
Contagem de nao-lidos¶
GET /bff/unread-counts
Response 200:
WebSocket¶
Conexao¶
Autenticacao: O token JWT e validado via OATH introspection no @OnOpen. Se invalido, a conexao e recusada.
Eventos recebidos (Server → Client)¶
| Evento | Payload | Descricao |
|---|---|---|
MESSAGE_RECEIVED |
MessageResponse |
Nova mensagem |
MESSAGE_UPDATED |
MessageResponse |
Mensagem editada |
MESSAGE_DELETED |
{ conversationId, messageId } |
Mensagem removida |
TYPING_START |
{ conversationId, userId, userName } |
Digitando |
TYPING_STOP |
{ conversationId, userId } |
Parou de digitar |
READ_RECEIPT |
{ conversationId, userId, messageId } |
Marcou como lido |
PRESENCE_CHANGED |
{ userId, online } |
Status mudou |
CONVERSATION_CREATED |
ConversationResponse |
Nova conversa |
Mensagens enviadas (Client → Server)¶
Ping/pong nativo do protocolo WebSocket para manter a conexao.
Health¶
GET /health
GET /health/ready
GET /health/live
SDK — ChatClientService¶
Para integracao server-to-server, use o ChatClientService do haus-quarkus-sdk:
Metodos disponiveis¶
| Metodo | Descricao |
|---|---|
listConversations(tenantId) |
Listar conversas |
findOrCreateDirect(tenantId, userId, email, name) |
Conversa 1:1 |
createGroup(tenantId, name, participants) |
Criar grupo |
addParticipant(tenantId, convId, userId, email, name) |
Adicionar participante |
sendMessage(tenantId, convId, content) |
Enviar mensagem TEXT |
sendMessage(tenantId, convId, content, type) |
Enviar com tipo |
sendSystemMessage(tenantId, convId, content) |
Mensagem SYSTEM |
listMessages(tenantId, convId, before, limit) |
Listar mensagens |
markAsRead(tenantId, convId, messageId) |
Marcar como lido |
getUnreadCounts(tenantId) |
Contagem nao-lidos |
isHealthy() |
Health check |
isEnabled() |
Verificar se chat esta habilitado |
Exemplo — Notificacao de reserva¶
// Quando uma reserva e confirmada, envia msg de sistema no chat
chatClient.sendSystemMessage(
hotelId.toString(),
conversationId,
"Reserva #" + reservation.getCode() + " confirmada!"
);