# Mobile Integration Spec (Stage 1) ## Base URL - Processor endpoints are mounted under `/api/v1/mobile`. ## Headers - Optional: `x-flow-id` for end-to-end trace correlation. - Required for ping/sync endpoints: `x-device-id` with a previously registered `externalDeviceId`. ## Endpoints ### Register Device - Method: `POST` - Path: `/api/v1/mobile/register` - Auth: none (trusted private network assumption) Payload: ```json { "externalDeviceId": "android-1234", "name": "Pixel 8 Pro", "manufacturer": "Google", "model": "Pixel 8 Pro", "androidVersion": "15" } ``` ### Ping Device - Method: `PUT` - Path: `/api/v1/mobile/ping` - Required header: `x-device-id` Payload: ```json { "pingAt": "2026-03-01T10:15:00.000Z" } ``` ### Sync SMS - Method: `PUT` - Path: `/api/v1/mobile/sms/sync` - Required header: `x-device-id` Payload: ```json { "messages": [ { "externalMessageId": "msg-1", "sender": "+358401111111", "recipient": "+358402222222", "body": "Hello from device", "sentAt": "2026-03-01T10:10:00.000Z", "receivedAt": "2026-03-01T10:10:01.000Z", "rawPayload": { "threadId": "7" } } ] } ``` ### Sync Media Assets - Method: `PUT` - Path: `/api/v1/mobile/media/sync` - Required header: `x-device-id` Payload: ```json { "assets": [ { "externalMediaId": "media-1", "fileId": "01JNE3Q1S3KQX9Y7G2J8G7R0A8", "mimeType": "image/jpeg", "filename": "IMG_1234.jpg", "capturedAt": "2026-03-01T10:05:00.000Z", "sizeBytes": 1350021, "hash": "sha256-...", "metadata": { "width": 3024, "height": 4032 } } ] } ``` ## Response Contract Success: ```json { "data": {}, "error": null } ``` Failure: ```json { "data": null, "error": { "flowId": "uuid", "code": "VALIDATION_ERROR", "message": "Human message", "description": "Actionable description", "detail": "Technical detail" } } ``` ## Admin Query Contract - Pagination: - `page`: 1-based integer - `pageSize`: integer - Sorting: - `sortBy`: operation-specific - `sortOrder`: `asc` or `desc` - Paginated response payload: - `data`: rows - `total`: full row count - `page`, `pageSize`, `totalPages` ## Dedup Rules - Device: - Upsert on unique `externalDeviceId`. - SMS: - Dedup key #1: `(deviceId, externalMessageId)` when provided. - Dedup key #2 fallback: `(deviceId, dedupHash)` where dedup hash is SHA-256 of `(deviceId + sentAt + sender + body)`. - Media: - Dedup key: `(deviceId, externalMediaId)` when provided. - `fileId` in `mobile_media_asset` is unique. ## Operator Checklist 1. Register a device. 2. Send ping with `x-device-id` and verify dashboard `lastPingAt` updates. 3. Sync SMS and verify device detail `SMS` tab updates (polling every 5s). 4. Sync media and verify device detail `Media Assets` tab displays rows.