# API для разработчиков: DM, push и сигналы звонков Документ описывает WebSocket-операции для подписанных личных сообщений, WebPush и realtime-сигналов звонков. Логика личных сообщений дополнительно описана в `Dev_Docs/Personal_Messages/README.md`; этот файл фиксирует именно публичные `op`, поля запросов и поля ответов. ## 1. `UpsertPushToken` Требует авторизации. ### Запрос ```json { "op": "UpsertPushToken", "requestId": "push-upsert-001", "payload": { "sessionId": "SESSION_ID", "endpoint": "https://push.example/...", "p256dhKey": "BASE64", "authKey": "BASE64", "platform": "web", "userAgent": "Mozilla/5.0 ..." } } ``` ### Успешный ответ ```json { "op": "UpsertPushToken", "requestId": "push-upsert-001", "status": 200, "ok": true, "payload": { "tokenId": "token-1", "updatedAtMs": 1774700000123 } } ``` --- ## 2. `SendTestWebPush` Требует авторизации. Если `login` передан, он должен совпадать с логином текущей сессии. ### Запрос ```json { "op": "SendTestWebPush", "requestId": "push-test-001", "payload": { "login": "alice", "sessionId": "SESSION_ID", "title": "Test", "text": "Push body" } } ``` ### Успешный ответ ```json { "op": "SendTestWebPush", "requestId": "push-test-001", "status": 200, "ok": true, "payload": { "targetLogin": "alice", "attemptedSessions": 1, "sessionsWithPushConfig": 1, "delivered": 1, "failed": 0, "sentAtMs": 1774700000123 } } ``` --- ## 3. `SendDirectMessage` Отправляет один подписанный DM-пакет. ### Запрос ```json { "op": "SendDirectMessage", "requestId": "dm-001", "payload": { "blobB64": "BASE64_SIGNED_DM_PACKET" } } ``` ### Успешный ответ ```json { "op": "SendDirectMessage", "requestId": "dm-001", "status": 200, "ok": true, "payload": { "messageId": "dm-1", "deliveredWsSessions": 1, "deliveredWebPushSessions": 0, "sessionNotFound": false } } ``` --- ## 4. `SendMessagePair` и `ReceiveOutcomingMessage` `ReceiveOutcomingMessage` сейчас является алиасом `SendMessagePair` и использует тот же request/handler. ### Запрос ```json { "op": "SendMessagePair", "requestId": "dm-pair-001", "payload": { "incomingBlobB64": "BASE64_INCOMING_SIGNED_BLOCK", "outgoingBlobB64": "BASE64_OUTGOING_SIGNED_BLOCK" } } ``` ### Успешный ответ ```json { "op": "SendMessagePair", "requestId": "dm-pair-001", "status": 200, "ok": true, "payload": { "baseKey": "base-key", "incomingKey": "incoming-key", "outgoingKey": "outgoing-key", "deliveredWsSessions": 1, "deliveredWebPushSessions": 0 } } ``` --- ## 5. `ReceiveIncomingMessage` Принимает входящий подписанный DM-блок. ### Запрос ```json { "op": "ReceiveIncomingMessage", "requestId": "dm-in-001", "payload": { "incomingBlobB64": "BASE64_INCOMING_SIGNED_BLOCK" } } ``` ### Успешный ответ ```json { "op": "ReceiveIncomingMessage", "requestId": "dm-in-001", "status": 200, "ok": true, "payload": { "messageKey": "incoming-key", "baseKey": "base-key", "deliveredWsSessions": 1, "deliveredWebPushSessions": 0 } } ``` --- ## 6. `AckSessionDelivery` Требует авторизации. Подтверждает доставку сообщения в текущую сессию. ### Запрос ```json { "op": "AckSessionDelivery", "requestId": "ack-001", "payload": { "messageKey": "incoming-key" } } ``` ### Успешный ответ ```json { "op": "AckSessionDelivery", "requestId": "ack-001", "status": 200, "ok": true, "payload": { "messageKey": "incoming-key" } } ``` --- ## 7. `CallInviteBroadcast` Требует авторизации. Отправляет приглашение к звонку на активные сессии пользователя `toLogin`. ### Запрос ```json { "op": "CallInviteBroadcast", "requestId": "call-invite-001", "payload": { "toLogin": "bob", "callId": "call-1", "type": 100 } } ``` ### Успешный ответ ```json { "op": "CallInviteBroadcast", "requestId": "call-invite-001", "status": 200, "ok": true, "payload": { "callId": "call-1", "deliveredWsSessions": 1, "deliveredFcmSessions": 0, "deliveredWebPushSessions": 0 } } ``` --- ## 8. `CallSignalToSession` Требует авторизации. Отправляет сигнал звонка в конкретную сессию получателя. ### Запрос ```json { "op": "CallSignalToSession", "requestId": "call-signal-001", "payload": { "toLogin": "bob", "targetSessionId": "SESSION_ID", "callId": "call-1", "type": 101, "data": "{\"sdp\":\"...\"}" } } ``` ### Успешный ответ ```json { "op": "CallSignalToSession", "requestId": "call-signal-001", "status": 200, "ok": true, "payload": { "delivered": true } } ``` Если целевая сессия не найдена или доставка не удалась, сервер может вернуть `404`. ## Типовые ошибки - `422 / NOT_AUTHENTICATED` — требуется авторизация. - `400 / BAD_FIELDS` — не заполнены обязательные поля. - `404 / USER_NOT_FOUND` — пользователь не найден. - `404 / SESSION_NOT_FOUND` — сессия не найдена. - `422 / BAD_SIGNATURE` — подпись DM не прошла проверку. - `422 / BAD_DEVICE_KEY` — некорректный device key отправителя. - `422 / BAD_TIME_WINDOW` — время подписанного сообщения вне допустимого окна. - `422 / REPLAY` — повторное сообщение заблокировано.