2026-04-18 02:00:09 +00:00
|
|
|
openapi: 3.1.0
|
|
|
|
|
info:
|
|
|
|
|
# Do not change the title, if the title changes, the import paths will be broken
|
|
|
|
|
title: Api
|
|
|
|
|
version: 0.1.0
|
2026-04-20 09:20:50 +00:00
|
|
|
description: TeaBoy OS API specification
|
2026-04-18 02:00:09 +00:00
|
|
|
servers:
|
|
|
|
|
- url: /api
|
|
|
|
|
description: Base API path
|
|
|
|
|
tags:
|
|
|
|
|
- name: health
|
|
|
|
|
description: Health operations
|
2026-04-20 09:20:50 +00:00
|
|
|
- name: auth
|
|
|
|
|
description: Authentication
|
|
|
|
|
- name: apps
|
|
|
|
|
description: App management
|
|
|
|
|
- name: services
|
|
|
|
|
description: Internal services (khidmati)
|
|
|
|
|
- name: conversations
|
|
|
|
|
description: Chat conversations
|
|
|
|
|
- name: messages
|
|
|
|
|
description: Chat messages
|
|
|
|
|
- name: notifications
|
|
|
|
|
description: Notifications
|
|
|
|
|
- name: users
|
|
|
|
|
description: User management
|
|
|
|
|
- name: stats
|
|
|
|
|
description: Dashboard stats
|
2026-04-20 10:55:11 +00:00
|
|
|
- name: storage
|
|
|
|
|
description: Object storage upload and serving endpoints
|
2026-04-20 09:20:50 +00:00
|
|
|
|
2026-04-18 02:00:09 +00:00
|
|
|
paths:
|
|
|
|
|
/healthz:
|
|
|
|
|
get:
|
|
|
|
|
operationId: healthCheck
|
|
|
|
|
tags: [health]
|
|
|
|
|
summary: Health check
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Healthy
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/HealthStatus"
|
2026-04-20 09:20:50 +00:00
|
|
|
|
|
|
|
|
# Auth
|
|
|
|
|
/auth/register:
|
|
|
|
|
post:
|
|
|
|
|
operationId: register
|
|
|
|
|
tags: [auth]
|
|
|
|
|
summary: Register a new user
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/RegisterBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Registered
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/AuthUser"
|
|
|
|
|
"400":
|
|
|
|
|
description: Validation error
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
|
|
|
|
|
|
|
|
/auth/login:
|
|
|
|
|
post:
|
|
|
|
|
operationId: login
|
|
|
|
|
tags: [auth]
|
|
|
|
|
summary: Login
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/LoginBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Logged in
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/AuthUser"
|
|
|
|
|
"401":
|
|
|
|
|
description: Unauthorized
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
|
|
|
|
|
|
|
|
/auth/logout:
|
|
|
|
|
post:
|
|
|
|
|
operationId: logout
|
|
|
|
|
tags: [auth]
|
|
|
|
|
summary: Logout
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Logged out
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/SuccessResponse"
|
|
|
|
|
|
|
|
|
|
/auth/me:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getMe
|
|
|
|
|
tags: [auth]
|
|
|
|
|
summary: Get current user
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Current user
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/AuthUser"
|
|
|
|
|
"401":
|
|
|
|
|
description: Unauthorized
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
|
|
|
|
|
|
|
|
/auth/me/language:
|
|
|
|
|
patch:
|
|
|
|
|
operationId: updateLanguage
|
|
|
|
|
tags: [auth]
|
|
|
|
|
summary: Update preferred language
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UpdateLanguageBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Updated
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/AuthUser"
|
|
|
|
|
|
|
|
|
|
# Apps
|
|
|
|
|
/apps:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listApps
|
|
|
|
|
tags: [apps]
|
|
|
|
|
summary: List all active apps
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Apps list
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/App"
|
|
|
|
|
|
|
|
|
|
post:
|
|
|
|
|
operationId: createApp
|
|
|
|
|
tags: [apps]
|
|
|
|
|
summary: Create a new app (admin)
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/CreateAppBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/App"
|
|
|
|
|
|
|
|
|
|
/apps/{id}:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getApp
|
|
|
|
|
tags: [apps]
|
|
|
|
|
summary: Get app by ID
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: App
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/App"
|
|
|
|
|
|
|
|
|
|
patch:
|
|
|
|
|
operationId: updateApp
|
|
|
|
|
tags: [apps]
|
|
|
|
|
summary: Update app (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UpdateAppBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Updated
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/App"
|
|
|
|
|
|
|
|
|
|
delete:
|
|
|
|
|
operationId: deleteApp
|
|
|
|
|
tags: [apps]
|
|
|
|
|
summary: Delete app (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"204":
|
|
|
|
|
description: Deleted
|
|
|
|
|
|
2026-04-20 10:55:11 +00:00
|
|
|
# Storage
|
|
|
|
|
/storage/uploads/request-url:
|
|
|
|
|
post:
|
|
|
|
|
operationId: requestUploadUrl
|
|
|
|
|
tags: [storage]
|
|
|
|
|
summary: Request a presigned URL for file upload
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/RequestUploadUrlBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Presigned upload URL generated
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/RequestUploadUrlResponse"
|
|
|
|
|
"400":
|
|
|
|
|
description: Invalid input
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
|
|
|
|
2026-04-20 09:20:50 +00:00
|
|
|
# Services
|
|
|
|
|
/services:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listServices
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: List all services
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Services list
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/Service"
|
|
|
|
|
|
|
|
|
|
post:
|
|
|
|
|
operationId: createService
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: Create a service (admin)
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/CreateServiceBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/Service"
|
|
|
|
|
|
|
|
|
|
/services/{id}:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getService
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: Get service by ID
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Service
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/Service"
|
|
|
|
|
|
|
|
|
|
patch:
|
|
|
|
|
operationId: updateService
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: Update service (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UpdateServiceBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Updated
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/Service"
|
|
|
|
|
|
|
|
|
|
delete:
|
|
|
|
|
operationId: deleteService
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: Delete service (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"204":
|
|
|
|
|
description: Deleted
|
|
|
|
|
|
|
|
|
|
/service-categories:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listServiceCategories
|
|
|
|
|
tags: [services]
|
|
|
|
|
summary: List service categories
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Categories
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/ServiceCategory"
|
|
|
|
|
|
|
|
|
|
# Conversations
|
|
|
|
|
/conversations:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listConversations
|
|
|
|
|
tags: [conversations]
|
|
|
|
|
summary: List conversations for current user
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Conversations
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/ConversationWithDetails"
|
|
|
|
|
|
|
|
|
|
post:
|
|
|
|
|
operationId: createConversation
|
|
|
|
|
tags: [conversations]
|
|
|
|
|
summary: Create a conversation
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/CreateConversationBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ConversationWithDetails"
|
|
|
|
|
|
|
|
|
|
/conversations/{id}:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getConversation
|
|
|
|
|
tags: [conversations]
|
|
|
|
|
summary: Get conversation by ID
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Conversation
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/ConversationWithDetails"
|
|
|
|
|
|
|
|
|
|
/conversations/{id}/messages:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listMessages
|
|
|
|
|
tags: [messages]
|
|
|
|
|
summary: List messages in a conversation
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Messages
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/MessageWithSender"
|
|
|
|
|
|
|
|
|
|
post:
|
|
|
|
|
operationId: sendMessage
|
|
|
|
|
tags: [messages]
|
|
|
|
|
summary: Send a message
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/SendMessageBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Message sent
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/MessageWithSender"
|
|
|
|
|
|
|
|
|
|
/conversations/{id}/read:
|
|
|
|
|
post:
|
|
|
|
|
operationId: markConversationRead
|
|
|
|
|
tags: [messages]
|
|
|
|
|
summary: Mark all messages in conversation as read
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Marked as read
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/SuccessResponse"
|
|
|
|
|
|
|
|
|
|
# Notifications
|
|
|
|
|
/notifications:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listNotifications
|
|
|
|
|
tags: [notifications]
|
|
|
|
|
summary: List notifications for current user
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Notifications
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/Notification"
|
|
|
|
|
|
|
|
|
|
/notifications/{id}/read:
|
|
|
|
|
patch:
|
|
|
|
|
operationId: markNotificationRead
|
|
|
|
|
tags: [notifications]
|
|
|
|
|
summary: Mark notification as read
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Marked as read
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/Notification"
|
|
|
|
|
|
|
|
|
|
/notifications/read-all:
|
|
|
|
|
post:
|
|
|
|
|
operationId: markAllNotificationsRead
|
|
|
|
|
tags: [notifications]
|
|
|
|
|
summary: Mark all notifications as read
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Done
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/SuccessResponse"
|
|
|
|
|
|
|
|
|
|
# Users (admin)
|
|
|
|
|
/users:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listUsers
|
|
|
|
|
tags: [users]
|
|
|
|
|
summary: List all users (admin)
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Users
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/UserProfile"
|
|
|
|
|
|
2026-04-20 10:02:09 +00:00
|
|
|
post:
|
|
|
|
|
operationId: createUser
|
|
|
|
|
tags: [users]
|
|
|
|
|
summary: Create a user (admin)
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/RegisterBody"
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created user
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UserProfile"
|
|
|
|
|
"409":
|
|
|
|
|
description: Username already taken
|
|
|
|
|
|
2026-04-20 09:20:50 +00:00
|
|
|
/users/{id}:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getUser
|
|
|
|
|
tags: [users]
|
|
|
|
|
summary: Get user by ID (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: User
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UserProfile"
|
|
|
|
|
|
|
|
|
|
patch:
|
|
|
|
|
operationId: updateUser
|
|
|
|
|
tags: [users]
|
|
|
|
|
summary: Update user (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
requestBody:
|
|
|
|
|
required: true
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UpdateUserBody"
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Updated
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/UserProfile"
|
|
|
|
|
|
|
|
|
|
delete:
|
|
|
|
|
operationId: deleteUser
|
|
|
|
|
tags: [users]
|
|
|
|
|
summary: Delete user (admin)
|
|
|
|
|
parameters:
|
|
|
|
|
- name: id
|
|
|
|
|
in: path
|
|
|
|
|
required: true
|
|
|
|
|
schema:
|
|
|
|
|
type: integer
|
|
|
|
|
responses:
|
|
|
|
|
"204":
|
|
|
|
|
description: Deleted
|
|
|
|
|
|
|
|
|
|
# Stats
|
|
|
|
|
/stats/home:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getHomeStats
|
|
|
|
|
tags: [stats]
|
|
|
|
|
summary: Get home screen stats
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Stats
|
|
|
|
|
content:
|
|
|
|
|
application/json:
|
|
|
|
|
schema:
|
|
|
|
|
$ref: "#/components/schemas/HomeStats"
|
|
|
|
|
|
2026-04-18 02:00:09 +00:00
|
|
|
components:
|
|
|
|
|
schemas:
|
|
|
|
|
HealthStatus:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
status:
|
|
|
|
|
type: string
|
|
|
|
|
required:
|
|
|
|
|
- status
|
|
|
|
|
|
2026-04-20 09:20:50 +00:00
|
|
|
ErrorResponse:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
error:
|
|
|
|
|
type: string
|
|
|
|
|
required:
|
|
|
|
|
- error
|
|
|
|
|
|
|
|
|
|
SuccessResponse:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
success:
|
|
|
|
|
type: boolean
|
|
|
|
|
required:
|
|
|
|
|
- success
|
|
|
|
|
|
|
|
|
|
RegisterBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
username:
|
|
|
|
|
type: string
|
|
|
|
|
email:
|
|
|
|
|
type: string
|
|
|
|
|
password:
|
|
|
|
|
type: string
|
|
|
|
|
displayNameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
displayNameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
preferredLanguage:
|
|
|
|
|
type: string
|
|
|
|
|
default: "ar"
|
|
|
|
|
required:
|
|
|
|
|
- username
|
|
|
|
|
- email
|
|
|
|
|
- password
|
|
|
|
|
|
|
|
|
|
LoginBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
username:
|
|
|
|
|
type: string
|
|
|
|
|
password:
|
|
|
|
|
type: string
|
|
|
|
|
required:
|
|
|
|
|
- username
|
|
|
|
|
- password
|
|
|
|
|
|
|
|
|
|
UpdateLanguageBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
language:
|
|
|
|
|
type: string
|
|
|
|
|
required:
|
|
|
|
|
- language
|
|
|
|
|
|
|
|
|
|
AuthUser:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
username:
|
|
|
|
|
type: string
|
|
|
|
|
email:
|
|
|
|
|
type: string
|
|
|
|
|
displayNameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
displayNameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
preferredLanguage:
|
|
|
|
|
type: string
|
|
|
|
|
avatarUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
roles:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
type: string
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- username
|
|
|
|
|
- email
|
|
|
|
|
- preferredLanguage
|
|
|
|
|
- isActive
|
|
|
|
|
- roles
|
|
|
|
|
- createdAt
|
|
|
|
|
|
|
|
|
|
UserProfile:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
username:
|
|
|
|
|
type: string
|
|
|
|
|
email:
|
|
|
|
|
type: string
|
|
|
|
|
displayNameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
displayNameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
preferredLanguage:
|
|
|
|
|
type: string
|
|
|
|
|
avatarUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
roles:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
type: string
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- username
|
|
|
|
|
- email
|
|
|
|
|
- preferredLanguage
|
|
|
|
|
- isActive
|
|
|
|
|
- roles
|
|
|
|
|
- createdAt
|
|
|
|
|
|
|
|
|
|
UpdateUserBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
displayNameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
displayNameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
preferredLanguage:
|
|
|
|
|
type: string
|
|
|
|
|
|
|
|
|
|
App:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
slug:
|
|
|
|
|
type: string
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
iconName:
|
|
|
|
|
type: string
|
|
|
|
|
route:
|
|
|
|
|
type: string
|
|
|
|
|
color:
|
|
|
|
|
type: string
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
isSystem:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
updatedAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- slug
|
|
|
|
|
- nameAr
|
|
|
|
|
- nameEn
|
|
|
|
|
- iconName
|
|
|
|
|
- route
|
|
|
|
|
- color
|
|
|
|
|
- isActive
|
|
|
|
|
- isSystem
|
|
|
|
|
- sortOrder
|
|
|
|
|
- createdAt
|
|
|
|
|
- updatedAt
|
|
|
|
|
|
|
|
|
|
CreateAppBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
slug:
|
|
|
|
|
type: string
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
iconName:
|
|
|
|
|
type: string
|
|
|
|
|
route:
|
|
|
|
|
type: string
|
|
|
|
|
color:
|
|
|
|
|
type: string
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
isSystem:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
required:
|
|
|
|
|
- slug
|
|
|
|
|
- nameAr
|
|
|
|
|
- nameEn
|
|
|
|
|
- iconName
|
|
|
|
|
- route
|
|
|
|
|
- color
|
|
|
|
|
|
|
|
|
|
UpdateAppBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
iconName:
|
|
|
|
|
type: string
|
|
|
|
|
route:
|
|
|
|
|
type: string
|
|
|
|
|
color:
|
|
|
|
|
type: string
|
|
|
|
|
isActive:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
|
|
|
|
|
Service:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
categoryId:
|
|
|
|
|
type: ["integer", "null"]
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
imageUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
price:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isAvailable:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
updatedAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- nameAr
|
|
|
|
|
- nameEn
|
|
|
|
|
- isAvailable
|
|
|
|
|
- sortOrder
|
|
|
|
|
- createdAt
|
|
|
|
|
- updatedAt
|
|
|
|
|
|
|
|
|
|
CreateServiceBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
categoryId:
|
|
|
|
|
type: ["integer", "null"]
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
imageUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
price:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isAvailable:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
required:
|
|
|
|
|
- nameAr
|
|
|
|
|
- nameEn
|
|
|
|
|
|
|
|
|
|
UpdateServiceBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
categoryId:
|
|
|
|
|
type: ["integer", "null"]
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
descriptionAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
descriptionEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
imageUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
price:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isAvailable:
|
|
|
|
|
type: boolean
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
|
|
|
|
|
ServiceCategory:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
nameAr:
|
|
|
|
|
type: string
|
|
|
|
|
nameEn:
|
|
|
|
|
type: string
|
|
|
|
|
sortOrder:
|
|
|
|
|
type: integer
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- nameAr
|
|
|
|
|
- nameEn
|
|
|
|
|
- sortOrder
|
|
|
|
|
- createdAt
|
|
|
|
|
|
|
|
|
|
ConversationWithDetails:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
nameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
nameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isGroup:
|
|
|
|
|
type: boolean
|
|
|
|
|
createdBy:
|
|
|
|
|
type: integer
|
|
|
|
|
participants:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
$ref: "#/components/schemas/ParticipantInfo"
|
|
|
|
|
lastMessage:
|
|
|
|
|
$ref: "#/components/schemas/MessageWithSender"
|
|
|
|
|
nullable: true
|
|
|
|
|
unreadCount:
|
|
|
|
|
type: integer
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
updatedAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- isGroup
|
|
|
|
|
- createdBy
|
|
|
|
|
- participants
|
|
|
|
|
- unreadCount
|
|
|
|
|
- createdAt
|
|
|
|
|
- updatedAt
|
|
|
|
|
|
|
|
|
|
ParticipantInfo:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
username:
|
|
|
|
|
type: string
|
|
|
|
|
displayNameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
displayNameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
avatarUrl:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isAdmin:
|
|
|
|
|
type: boolean
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- username
|
|
|
|
|
- isAdmin
|
|
|
|
|
|
|
|
|
|
CreateConversationBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
participantIds:
|
|
|
|
|
type: array
|
|
|
|
|
items:
|
|
|
|
|
type: integer
|
|
|
|
|
nameAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
nameEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
isGroup:
|
|
|
|
|
type: boolean
|
|
|
|
|
required:
|
|
|
|
|
- participantIds
|
|
|
|
|
|
|
|
|
|
MessageWithSender:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
conversationId:
|
|
|
|
|
type: integer
|
|
|
|
|
senderId:
|
|
|
|
|
type: integer
|
|
|
|
|
content:
|
|
|
|
|
type: string
|
|
|
|
|
sender:
|
|
|
|
|
$ref: "#/components/schemas/ParticipantInfo"
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
updatedAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- conversationId
|
|
|
|
|
- senderId
|
|
|
|
|
- content
|
|
|
|
|
- sender
|
|
|
|
|
- createdAt
|
|
|
|
|
- updatedAt
|
|
|
|
|
|
|
|
|
|
SendMessageBody:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
content:
|
|
|
|
|
type: string
|
|
|
|
|
required:
|
|
|
|
|
- content
|
|
|
|
|
|
|
|
|
|
Notification:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
id:
|
|
|
|
|
type: integer
|
|
|
|
|
userId:
|
|
|
|
|
type: integer
|
|
|
|
|
titleAr:
|
|
|
|
|
type: string
|
|
|
|
|
titleEn:
|
|
|
|
|
type: string
|
|
|
|
|
bodyAr:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
bodyEn:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
type:
|
|
|
|
|
type: string
|
|
|
|
|
isRead:
|
|
|
|
|
type: boolean
|
|
|
|
|
relatedId:
|
|
|
|
|
type: ["integer", "null"]
|
|
|
|
|
relatedType:
|
|
|
|
|
type: ["string", "null"]
|
|
|
|
|
createdAt:
|
|
|
|
|
type: string
|
|
|
|
|
format: date-time
|
|
|
|
|
required:
|
|
|
|
|
- id
|
|
|
|
|
- userId
|
|
|
|
|
- titleAr
|
|
|
|
|
- titleEn
|
|
|
|
|
- type
|
|
|
|
|
- isRead
|
|
|
|
|
- createdAt
|
|
|
|
|
|
2026-04-20 10:55:11 +00:00
|
|
|
RequestUploadUrlBody:
|
|
|
|
|
type: object
|
|
|
|
|
required: [name, size, contentType]
|
|
|
|
|
properties:
|
|
|
|
|
name:
|
|
|
|
|
type: string
|
|
|
|
|
minLength: 1
|
|
|
|
|
size:
|
|
|
|
|
type: integer
|
|
|
|
|
minimum: 1
|
|
|
|
|
contentType:
|
|
|
|
|
type: string
|
|
|
|
|
minLength: 1
|
|
|
|
|
|
|
|
|
|
RequestUploadUrlResponse:
|
|
|
|
|
type: object
|
|
|
|
|
required: [uploadURL, objectPath]
|
|
|
|
|
properties:
|
|
|
|
|
uploadURL:
|
|
|
|
|
type: string
|
|
|
|
|
format: uri
|
|
|
|
|
objectPath:
|
|
|
|
|
type: string
|
|
|
|
|
metadata:
|
|
|
|
|
$ref: "#/components/schemas/RequestUploadUrlBody"
|
|
|
|
|
|
2026-04-20 09:20:50 +00:00
|
|
|
HomeStats:
|
|
|
|
|
type: object
|
|
|
|
|
properties:
|
|
|
|
|
totalApps:
|
|
|
|
|
type: integer
|
|
|
|
|
totalServices:
|
|
|
|
|
type: integer
|
|
|
|
|
unreadNotifications:
|
|
|
|
|
type: integer
|
|
|
|
|
unreadMessages:
|
|
|
|
|
type: integer
|
|
|
|
|
totalUsers:
|
|
|
|
|
type: integer
|
|
|
|
|
required:
|
|
|
|
|
- totalApps
|
|
|
|
|
- totalServices
|
|
|
|
|
- unreadNotifications
|
|
|
|
|
- unreadMessages
|
|
|
|
|
- totalUsers
|