# Kosmi Image Upload Protocol ## Summary Kosmi uses a **simple HTTP POST** to upload images, **NOT the WebSocket**. Images are uploaded to a dedicated CDN endpoint. ## Upload Endpoint ``` POST https://img.kosmi.io/ ``` ## Request Details ### Method `POST` ### Headers ``` Content-Type: multipart/form-data; boundary=----WebKitFormBoundary... Origin: https://app.kosmi.io Referer: https://app.kosmi.io/ ``` **Important:** No authentication required! The endpoint accepts anonymous uploads. ### Request Body Standard `multipart/form-data` with a single field: ``` ------WebKitFormBoundary... Content-Disposition: form-data; name="file"; filename="blurt.jpg" Content-Type: image/jpeg [binary image data] ------WebKitFormBoundary...-- ``` ### CORS The endpoint has CORS enabled for `https://app.kosmi.io`: ``` Access-Control-Allow-Origin: https://app.kosmi.io ``` ## Response ### Status `200 OK` ### Headers ``` Content-Type: application/json Access-Control-Allow-Origin: https://app.kosmi.io ``` ### Response Body (CONFIRMED) ```json { "filename": "8d580b3a-905d-4bc9-909b-ccc6743edbdc.webp" } ``` **Note:** The response contains only the filename, not the full URL. The full URL must be constructed as: ``` https://img.kosmi.io/{filename} ``` Example: ```json { "filename": "3460a8e1-fe19-4371-a735-64078e9923a4.webp" } ``` → Full URL: `https://img.kosmi.io/3460a8e1-fe19-4371-a735-64078e9923a4.webp` ## Implementation Notes ### For Go Client 1. **No authentication needed** - This is a public upload endpoint 2. **Use standard multipart/form-data** - Go's `mime/multipart` package 3. **Set CORS headers**: - `Origin: https://app.kosmi.io` - `Referer: https://app.kosmi.io/` 4. **Parse JSON response** to get the image URL 5. **Send the URL to Kosmi chat** via the existing WebSocket `sendMessage` mutation ### Workflow 1. Generate room code PNG image (already implemented in `roomcode_image.go`) 2. Upload PNG to `https://img.kosmi.io/` via HTTP POST 3. Parse response to get image URL 4. Send message to Kosmi chat with the image URL 5. Kosmi will automatically display the image as a thumbnail ### Security Considerations - The endpoint is public (no auth required) - Files are likely rate-limited or size-limited - Images are served from `img.kosmi.io` CDN - The upload is CORS-protected (only works from `app.kosmi.io` origin) ## Example Implementation (Pseudocode) ```go func UploadImageToKosmi(imageData []byte, filename string) (string, error) { // Create multipart form body := &bytes.Buffer{} writer := multipart.NewWriter(body) // Add file field part, err := writer.CreateFormFile("file", filename) if err != nil { return "", err } part.Write(imageData) writer.Close() // Create request req, err := http.NewRequest("POST", "https://img.kosmi.io/", body) if err != nil { return "", err } // Set headers req.Header.Set("Content-Type", writer.FormDataContentType()) req.Header.Set("Origin", "https://app.kosmi.io") req.Header.Set("Referer", "https://app.kosmi.io/") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", err } defer resp.Body.Close() // Parse response var result struct { URL string `json:"url"` } json.NewDecoder(resp.Body).Decode(&result) return result.URL, nil } ``` ## Testing To test the upload, we can: 1. Generate a test room code image 2. Upload it to `https://img.kosmi.io/` 3. Verify we get a URL back 4. Send the URL to Kosmi chat 5. Verify the image displays as a thumbnail ## References - HAR capture: `image_upload_HAR-sanitized.har` (lines 3821-4110) - Upload request: Line 3910-4018 - Upload response: Line 4019-4092