# VOTIANLT Realtime & Photo Upload API This document describes how mobile/Flutter apps can interact with the backend via STOMP (WebSocket) and how to upload photos via HTTP POST (new flow). ## 1) STOMP Overview - Connect to one of the WebSocket endpoints: - `/ws` (SockJS fallback supported) - `/websocket` (native WebSocket) - `/stomp` (native WebSocket, alternate path) - Application destination prefix: `/app` - Broker destinations: - Broadcast: `/topic/...` - User specific: `/user/queue/...` Examples: - Send a generic message: send to `/app/message`, receive on `/topic/messages` - Job updates: send to `/app/job/status`, receive on `/topic/job-updates` - Device locations: send to `/app/device/location`, receive on `/topic/device-locations` - Task updates (broadcast): `/topic/task-updates` - Task specific topic: `/topic/tasks/{taskId}` ## 2) Photo Task – New HTTP Upload Flow In the future, photos for a PHOTO task must NOT be embedded in the STOMP message anymore. Instead, upload the photos via HTTP POST and only send the task-completion event via STOMP without large payloads. ### Endpoint - URL: `POST /api/tasks/{taskId}/photos` - Purpose: Upload one or many photos for a task of type `PHOTO`. - Path params: - `taskId` (required): The MongoDB ObjectId of the task. - Auth: (same as your app uses today; if you have a session/cookie or token, include it accordingly) - CORS: Enabled for `*` by default on this controller. ### Content Types (choose one) 1) Multipart form data (recommended for binary images) - `Content-Type: multipart/form-data` - Fields: - `files`: one or multiple image files (repeat the field for multiple images) - `completedBy` (optional): username/id of the completing user - `note` (optional): any note (currently stored on the task when you mark it as completed via STOMP) Example (curl): ```bash curl -X POST "http://localhost:8080/api/tasks/66f5c2f1a3b6e27a1a234567/photos" \ -H "Content-Type: multipart/form-data" \ -F "files=@/path/to/photo1.jpg" \ -F "files=@/path/to/photo2.jpg" \ -F "completedBy=driver01" \ -F "note=Anlieferung dokumentiert" ``` 2) JSON with base64 strings (kept for compatibility) - `Content-Type: application/json` - Body: ```json { "completedBy": "driver01", "note": "Anlieferung dokumentiert", "photos": [ "", "" ] } ``` Example (curl): ```bash curl -X POST "http://localhost:8080/api/tasks/66f5c2f1a3b6e27a1a234567/photos" \ -H "Content-Type: application/json" \ -d '{ "completedBy":"driver01", "note":"Anlieferung dokumentiert", "photos":["iVBORw0KGgo...","iVBORw0KGgo..."] }' ``` ### Simple JSON endpoint (single photo per call) - URL: `POST /api/photos` - Content-Type: `application/json` - Body: ```json { "taskId": "66f5c2f1a3b6e27a1a234567", "photo": "", "completedBy": "driver01", "note": "optional" } ``` - Multiple photos: call this endpoint multiple times (one image per request). Example (curl): ```bash curl -X POST "http://localhost:8080/api/photos" \ -H "Content-Type: application/json" \ -d '{ "taskId":"66f5c2f1a3b6e27a1a234567", "photo":"iVBORw0KGgo...", "completedBy":"driver01", "note":"Anlieferung dokumentiert" }' ``` ### Response Both content types return the same JSON structure on success: ```json { "timestamp": "2025-09-13T21:27:00", "type": "photoUploadAck", "success": true, "photoId": "66f5c400b1a1b05b1c123abc", "photosCount": 2, "taskId": "66f5c2f1a3b6e27a1a234567", "jobId": "66f5c2f1a3b6e27a1a200000" } ``` Error responses use HTTP status codes with: ```json { "timestamp": "...", "type": "photoUploadAck", "success": false, "message": "..." } ``` ### Server-side side-effect (notification) After a successful upload, a small event is broadcast to the specific task topic: - Destination: `/topic/tasks/{taskId}` - Payload: ```json { "event": "photoUploaded", "taskId": "...", "jobId": "...", "photosCount": 2, "timestamp": "..." } ``` Use this to update UI (e.g., show that photos have arrived) without transferring large images via STOMP. ### Limits - Multipart limits (configurable in `application.properties`): - `spring.servlet.multipart.max-file-size=32MB` - `spring.servlet.multipart.max-request-size=64MB` - Tomcat limits adjusted accordingly. If you need higher limits, we can raise these values. ## 3) Marking Task as Completed (STOMP) Continue to mark a task as completed via STOMP without embedding images: - Send to: `/app/task/photo/completed` - Payload (no photos inside): ```json { "taskId": "66f5c2f1a3b6e27a1a234567", "completedBy": "driver01", "note": "Anlieferung dokumentiert" } ``` - Broadcasts an update to `/topic/task-updates` and `/topic/tasks/{taskId}`. ## 4) Retrieval of Photos (optional) Currently, the backend stores uploaded photos as base64 in the `photos` collection referencing the `taskId` and `jobId`. If you need a download/list endpoint, let us know—we can expose `/api/tasks/{taskId}/photos` (GET) to return metadata and/or images. --- If anything is unclear or you need different formats (e.g., presigned URLs, chunked uploads), please reach out.