@myronsi/messenger-api 2.1.0-alpha.14 → 2.1.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/openapi.yaml +572 -3
- package/dist/schema.d.ts +920 -19
- package/dist/ws-docs.json +65 -1
- package/dist/ws-events.d.ts +136 -3
- package/dist/ws-events.schema.json +532 -2
- package/package.json +1 -1
package/dist/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: Messenger API
|
|
4
|
-
version: 2.1.0-alpha.
|
|
4
|
+
version: 2.1.0-alpha.15
|
|
5
5
|
summary: REST contract of the Messenger backend (v2).
|
|
6
6
|
description: |
|
|
7
7
|
Contract for the Go backend. The WebSocket protocol is described in `websocket/` and
|
|
@@ -58,6 +58,8 @@ tags:
|
|
|
58
58
|
description: Approval requests (direct messages and group invites)
|
|
59
59
|
- name: websocket
|
|
60
60
|
description: Realtime connection (see `websocket.md`)
|
|
61
|
+
- name: calls
|
|
62
|
+
description: Audio calls (see `docs/calls.md` and `docs/calls-e2ee.md`)
|
|
61
63
|
|
|
62
64
|
paths:
|
|
63
65
|
/meta:
|
|
@@ -3394,6 +3396,316 @@ paths:
|
|
|
3394
3396
|
schema:
|
|
3395
3397
|
$ref: "#/components/schemas/Problem"
|
|
3396
3398
|
|
|
3399
|
+
/calls/config:
|
|
3400
|
+
parameters:
|
|
3401
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3402
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3403
|
+
get:
|
|
3404
|
+
tags: [calls]
|
|
3405
|
+
operationId: getCallConfig
|
|
3406
|
+
summary: Whether audio calls are available and their limits
|
|
3407
|
+
description: |
|
|
3408
|
+
`enabled` is `false` when the server has no media service configured or calls are switched off; clients then
|
|
3409
|
+
hide every call control. Clients must also check that the browser supports call encryption before offering
|
|
3410
|
+
calls.
|
|
3411
|
+
responses:
|
|
3412
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3413
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3414
|
+
"200":
|
|
3415
|
+
description: Call availability
|
|
3416
|
+
content:
|
|
3417
|
+
application/json:
|
|
3418
|
+
schema: { $ref: "#/components/schemas/CallConfig" }
|
|
3419
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3420
|
+
/me/call-identity:
|
|
3421
|
+
parameters:
|
|
3422
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3423
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3424
|
+
put:
|
|
3425
|
+
tags: [calls]
|
|
3426
|
+
operationId: setCallIdentity
|
|
3427
|
+
summary: Register this session's call identity public key
|
|
3428
|
+
description: |
|
|
3429
|
+
One key per session (see `docs/calls-e2ee.md`). Registering a different key replaces the old one; if the
|
|
3430
|
+
session is in a call, the call's epoch increases. The private key never leaves the client.
|
|
3431
|
+
requestBody:
|
|
3432
|
+
required: true
|
|
3433
|
+
content:
|
|
3434
|
+
application/json:
|
|
3435
|
+
schema: { $ref: "#/components/schemas/CallIdentityRequest" }
|
|
3436
|
+
responses:
|
|
3437
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3438
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3439
|
+
"204":
|
|
3440
|
+
description: Stored
|
|
3441
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3442
|
+
"422": { $ref: "#/components/responses/ValidationFailed" }
|
|
3443
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
3444
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3445
|
+
/calls:
|
|
3446
|
+
parameters:
|
|
3447
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3448
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3449
|
+
get:
|
|
3450
|
+
tags: [calls]
|
|
3451
|
+
operationId: listMyCalls
|
|
3452
|
+
summary: Calls that are not over and involve the current user
|
|
3453
|
+
description: |
|
|
3454
|
+
Calls ringing the user and calls the user has joined, newest first. Clients load this after every
|
|
3455
|
+
(re)connect, because realtime events are best effort.
|
|
3456
|
+
responses:
|
|
3457
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3458
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3459
|
+
"200":
|
|
3460
|
+
description: Current calls
|
|
3461
|
+
content:
|
|
3462
|
+
application/json:
|
|
3463
|
+
schema: { $ref: "#/components/schemas/CallList" }
|
|
3464
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3465
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3466
|
+
/chats/{chat_id}/call:
|
|
3467
|
+
parameters:
|
|
3468
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3469
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3470
|
+
- $ref: "#/components/parameters/ChatId"
|
|
3471
|
+
get:
|
|
3472
|
+
tags: [calls]
|
|
3473
|
+
operationId: getChatCall
|
|
3474
|
+
summary: The chat's call that is not over
|
|
3475
|
+
responses:
|
|
3476
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3477
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3478
|
+
"200":
|
|
3479
|
+
description: The current call of the chat
|
|
3480
|
+
content:
|
|
3481
|
+
application/json:
|
|
3482
|
+
schema: { $ref: "#/components/schemas/Call" }
|
|
3483
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3484
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3485
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3486
|
+
post:
|
|
3487
|
+
tags: [calls]
|
|
3488
|
+
operationId: startChatCall
|
|
3489
|
+
summary: Start a call in the chat, or get the one already running
|
|
3490
|
+
description: |
|
|
3491
|
+
Starts ringing the other members. A chat has at most one call that is not over: when one exists it is
|
|
3492
|
+
returned with `200` and the client joins it instead. `client_request_id` makes retries idempotent for
|
|
3493
|
+
24 hours. Starting does not join: the caller then calls `POST /calls/{call_id}/join`.
|
|
3494
|
+
|
|
3495
|
+
Refused with `403` (`calls_not_allowed`) when the peer of a direct chat has calls turned off or one user
|
|
3496
|
+
blocked the other, `503` (`calls_unavailable`) when calls are off on the server.
|
|
3497
|
+
requestBody:
|
|
3498
|
+
required: true
|
|
3499
|
+
content:
|
|
3500
|
+
application/json:
|
|
3501
|
+
schema: { $ref: "#/components/schemas/StartCallRequest" }
|
|
3502
|
+
responses:
|
|
3503
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3504
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3505
|
+
"200":
|
|
3506
|
+
description: A call was already running in the chat
|
|
3507
|
+
content:
|
|
3508
|
+
application/json:
|
|
3509
|
+
schema: { $ref: "#/components/schemas/Call" }
|
|
3510
|
+
"201":
|
|
3511
|
+
description: The new call, ringing
|
|
3512
|
+
content:
|
|
3513
|
+
application/json:
|
|
3514
|
+
schema: { $ref: "#/components/schemas/Call" }
|
|
3515
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3516
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
3517
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3518
|
+
"422": { $ref: "#/components/responses/ValidationFailed" }
|
|
3519
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
3520
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3521
|
+
/calls/{call_id}:
|
|
3522
|
+
parameters:
|
|
3523
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3524
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3525
|
+
- $ref: "#/components/parameters/CallId"
|
|
3526
|
+
get:
|
|
3527
|
+
tags: [calls]
|
|
3528
|
+
operationId: getCall
|
|
3529
|
+
summary: A call of one of the user's chats
|
|
3530
|
+
description: Ended calls stay readable for 90 days.
|
|
3531
|
+
responses:
|
|
3532
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3533
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3534
|
+
"200":
|
|
3535
|
+
description: The call
|
|
3536
|
+
content:
|
|
3537
|
+
application/json:
|
|
3538
|
+
schema: { $ref: "#/components/schemas/Call" }
|
|
3539
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3540
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3541
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3542
|
+
/calls/{call_id}/join:
|
|
3543
|
+
parameters:
|
|
3544
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3545
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3546
|
+
- $ref: "#/components/parameters/CallId"
|
|
3547
|
+
post:
|
|
3548
|
+
tags: [calls]
|
|
3549
|
+
operationId: joinCall
|
|
3550
|
+
summary: Answer or join a call with this session
|
|
3551
|
+
description: |
|
|
3552
|
+
Answers a ringing call or joins a running group call, and returns a short-lived media grant for this
|
|
3553
|
+
session. The session must have a call identity (`422`, `call_identity_required`). A user is in at most one
|
|
3554
|
+
call with one session: `409` (`already_in_call`) unless `takeover` is `true`, which moves the user's
|
|
3555
|
+
participation to this session (the other session is removed from the media room). Other `409` codes:
|
|
3556
|
+
`call_ended`, `call_full`. The epoch of the call increases. The body is optional: no body, an empty body
|
|
3557
|
+
and `{}` all join without takeover.
|
|
3558
|
+
requestBody:
|
|
3559
|
+
required: false
|
|
3560
|
+
content:
|
|
3561
|
+
application/json:
|
|
3562
|
+
schema: { $ref: "#/components/schemas/JoinCallRequest" }
|
|
3563
|
+
responses:
|
|
3564
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3565
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3566
|
+
"200":
|
|
3567
|
+
description: Joined
|
|
3568
|
+
content:
|
|
3569
|
+
application/json:
|
|
3570
|
+
schema: { $ref: "#/components/schemas/CallJoin" }
|
|
3571
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3572
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
3573
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3574
|
+
"409": { $ref: "#/components/responses/Conflict" }
|
|
3575
|
+
"422": { $ref: "#/components/responses/ValidationFailed" }
|
|
3576
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
3577
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3578
|
+
/calls/{call_id}/grant:
|
|
3579
|
+
parameters:
|
|
3580
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3581
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3582
|
+
- $ref: "#/components/parameters/CallId"
|
|
3583
|
+
post:
|
|
3584
|
+
tags: [calls]
|
|
3585
|
+
operationId: renewCallGrant
|
|
3586
|
+
summary: A fresh media grant for the session that joined
|
|
3587
|
+
description: For reconnecting to the media server. Only the session that joined gets one (`409` otherwise).
|
|
3588
|
+
responses:
|
|
3589
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3590
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3591
|
+
"200":
|
|
3592
|
+
description: The grant
|
|
3593
|
+
content:
|
|
3594
|
+
application/json:
|
|
3595
|
+
schema: { $ref: "#/components/schemas/CallGrant" }
|
|
3596
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3597
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3598
|
+
"409": { $ref: "#/components/responses/Conflict" }
|
|
3599
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
3600
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3601
|
+
/calls/{call_id}/decline:
|
|
3602
|
+
parameters:
|
|
3603
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3604
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3605
|
+
- $ref: "#/components/parameters/CallId"
|
|
3606
|
+
post:
|
|
3607
|
+
tags: [calls]
|
|
3608
|
+
operationId: declineCall
|
|
3609
|
+
summary: Decline a ringing call
|
|
3610
|
+
description: |
|
|
3611
|
+
Stops the ringing on all of the user's devices. In a direct call this ends the call (`declined`); in a group
|
|
3612
|
+
call only this user's invitation ends. Declining a call that no longer rings changes nothing.
|
|
3613
|
+
responses:
|
|
3614
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3615
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3616
|
+
"204":
|
|
3617
|
+
description: Declined
|
|
3618
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3619
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3620
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3621
|
+
/calls/{call_id}/leave:
|
|
3622
|
+
parameters:
|
|
3623
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3624
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3625
|
+
- $ref: "#/components/parameters/CallId"
|
|
3626
|
+
post:
|
|
3627
|
+
tags: [calls]
|
|
3628
|
+
operationId: leaveCall
|
|
3629
|
+
summary: Leave the call
|
|
3630
|
+
description: |
|
|
3631
|
+
A direct call ends when either side leaves. A group call ends when the last participant has left and the
|
|
3632
|
+
short reconnect grace has passed. The caller leaving a call nobody answered cancels it (`cancelled`).
|
|
3633
|
+
responses:
|
|
3634
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3635
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3636
|
+
"204":
|
|
3637
|
+
description: Left
|
|
3638
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3639
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3640
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3641
|
+
/calls/{call_id}/end:
|
|
3642
|
+
parameters:
|
|
3643
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3644
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3645
|
+
- $ref: "#/components/parameters/CallId"
|
|
3646
|
+
post:
|
|
3647
|
+
tags: [calls]
|
|
3648
|
+
operationId: endCall
|
|
3649
|
+
summary: End the call for everyone
|
|
3650
|
+
description: |
|
|
3651
|
+
Allowed for the initiator, for both members of a direct call, and for the owner, admins and moderators of a
|
|
3652
|
+
group (`403` otherwise). Everyone is removed from the media room.
|
|
3653
|
+
responses:
|
|
3654
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3655
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3656
|
+
"204":
|
|
3657
|
+
description: Ended
|
|
3658
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3659
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
3660
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3661
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3662
|
+
/calls/{call_id}/keys:
|
|
3663
|
+
parameters:
|
|
3664
|
+
- $ref: "#/components/parameters/ClientVersion"
|
|
3665
|
+
- $ref: "#/components/parameters/ClientApiVersion"
|
|
3666
|
+
- $ref: "#/components/parameters/CallId"
|
|
3667
|
+
get:
|
|
3668
|
+
tags: [calls]
|
|
3669
|
+
operationId: getCallKeys
|
|
3670
|
+
summary: Key envelopes addressed to this session in the current epoch
|
|
3671
|
+
description: For catching up after a reconnect; the same envelopes also arrive as `call_keys` events.
|
|
3672
|
+
responses:
|
|
3673
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3674
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3675
|
+
"200":
|
|
3676
|
+
description: The envelopes
|
|
3677
|
+
content:
|
|
3678
|
+
application/json:
|
|
3679
|
+
schema: { $ref: "#/components/schemas/CallKeyEnvelopeList" }
|
|
3680
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3681
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3682
|
+
"409": { $ref: "#/components/responses/Conflict" }
|
|
3683
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3684
|
+
post:
|
|
3685
|
+
tags: [calls]
|
|
3686
|
+
operationId: sendCallKeys
|
|
3687
|
+
summary: Send this session's sealed sender key to the other participants
|
|
3688
|
+
description: |
|
|
3689
|
+
Relays opaque HPKE envelopes (see `docs/calls-e2ee.md`). Only the session that joined may send, only for the
|
|
3690
|
+
current epoch (`409`, `stale_epoch`), and only to sessions on the roster of that epoch (`422`). The server
|
|
3691
|
+
never sees a plaintext key.
|
|
3692
|
+
requestBody:
|
|
3693
|
+
required: true
|
|
3694
|
+
content:
|
|
3695
|
+
application/json:
|
|
3696
|
+
schema: { $ref: "#/components/schemas/SendCallKeysRequest" }
|
|
3697
|
+
responses:
|
|
3698
|
+
"426": { $ref: "#/components/responses/ClientOutdated" }
|
|
3699
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
3700
|
+
"204":
|
|
3701
|
+
description: Relayed
|
|
3702
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
3703
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
3704
|
+
"409": { $ref: "#/components/responses/Conflict" }
|
|
3705
|
+
"422": { $ref: "#/components/responses/ValidationFailed" }
|
|
3706
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
3707
|
+
"503": { $ref: "#/components/responses/CallsUnavailable" }
|
|
3708
|
+
|
|
3397
3709
|
components:
|
|
3398
3710
|
securitySchemes:
|
|
3399
3711
|
bearerAuth:
|
|
@@ -3459,6 +3771,11 @@ components:
|
|
|
3459
3771
|
in: path
|
|
3460
3772
|
required: true
|
|
3461
3773
|
schema: { type: string, format: uuid }
|
|
3774
|
+
CallId:
|
|
3775
|
+
name: call_id
|
|
3776
|
+
in: path
|
|
3777
|
+
required: true
|
|
3778
|
+
schema: { $ref: "#/components/schemas/Id" }
|
|
3462
3779
|
|
|
3463
3780
|
ClientVersion:
|
|
3464
3781
|
name: X-Client-Version
|
|
@@ -3539,6 +3856,18 @@ components:
|
|
|
3539
3856
|
content:
|
|
3540
3857
|
application/problem+json:
|
|
3541
3858
|
schema: { $ref: "#/components/schemas/Problem" }
|
|
3859
|
+
CallsUnavailable:
|
|
3860
|
+
description: |
|
|
3861
|
+
Calls are switched off on the server, or the server is at its call capacity (both `calls_unavailable`), or
|
|
3862
|
+
the media service or a store is away for a moment (`internal_error`). Retry after `Retry-After` when it is
|
|
3863
|
+
present; without it calls stay off until `GET /calls/config` reports them enabled.
|
|
3864
|
+
headers:
|
|
3865
|
+
Retry-After:
|
|
3866
|
+
description: Seconds until a retry may succeed
|
|
3867
|
+
schema: { type: integer, minimum: 0 }
|
|
3868
|
+
content:
|
|
3869
|
+
application/problem+json:
|
|
3870
|
+
schema: { $ref: "#/components/schemas/Problem" }
|
|
3542
3871
|
|
|
3543
3872
|
schemas:
|
|
3544
3873
|
NotificationPreferences:
|
|
@@ -3691,6 +4020,13 @@ components:
|
|
|
3691
4020
|
- invalid_client_version
|
|
3692
4021
|
- blocked_by_user
|
|
3693
4022
|
- approval_required
|
|
4023
|
+
- calls_unavailable
|
|
4024
|
+
- calls_not_allowed
|
|
4025
|
+
- call_identity_required
|
|
4026
|
+
- call_full
|
|
4027
|
+
- call_ended
|
|
4028
|
+
- already_in_call
|
|
4029
|
+
- stale_epoch
|
|
3694
4030
|
- internal_error
|
|
3695
4031
|
Problem:
|
|
3696
4032
|
type: object
|
|
@@ -3971,6 +4307,7 @@ components:
|
|
|
3971
4307
|
- direct_messages
|
|
3972
4308
|
- group_invites
|
|
3973
4309
|
- search_visibility
|
|
4310
|
+
- calls_enabled
|
|
3974
4311
|
- exceptions
|
|
3975
4312
|
properties:
|
|
3976
4313
|
avatar_visibility: { $ref: "#/components/schemas/Visibility" }
|
|
@@ -3980,6 +4317,9 @@ components:
|
|
|
3980
4317
|
direct_messages: { $ref: "#/components/schemas/DirectMessagePolicy" }
|
|
3981
4318
|
group_invites: { $ref: "#/components/schemas/GroupInvitePolicy" }
|
|
3982
4319
|
search_visibility: { $ref: "#/components/schemas/SearchVisibility" }
|
|
4320
|
+
calls_enabled:
|
|
4321
|
+
type: boolean
|
|
4322
|
+
description: Whether others may ring this user. Calls are only possible from an existing direct chat or a shared group.
|
|
3983
4323
|
exceptions: { $ref: "#/components/schemas/PrivacyExceptions" }
|
|
3984
4324
|
UpdatePrivacySettingsRequest:
|
|
3985
4325
|
type: object
|
|
@@ -3992,6 +4332,7 @@ components:
|
|
|
3992
4332
|
direct_messages: { $ref: "#/components/schemas/DirectMessagePolicy" }
|
|
3993
4333
|
group_invites: { $ref: "#/components/schemas/GroupInvitePolicy" }
|
|
3994
4334
|
search_visibility: { $ref: "#/components/schemas/SearchVisibility" }
|
|
4335
|
+
calls_enabled: { type: boolean }
|
|
3995
4336
|
PrivacyExceptionsRequest:
|
|
3996
4337
|
type: object
|
|
3997
4338
|
required: [user_ids]
|
|
@@ -4242,13 +4583,14 @@ components:
|
|
|
4242
4583
|
height: { type: [integer, "null"], minimum: 1 }
|
|
4243
4584
|
SystemEventKind:
|
|
4244
4585
|
type: string
|
|
4245
|
-
enum: [group_created, member_added, member_joined, member_removed, member_left]
|
|
4586
|
+
enum: [group_created, member_added, member_joined, member_removed, member_left, call]
|
|
4246
4587
|
SystemEvent:
|
|
4247
4588
|
type: object
|
|
4248
4589
|
description: |
|
|
4249
4590
|
What a `system` message records; set on system messages only, whose `content` is then `null`. The names
|
|
4250
4591
|
are the display names at the time of the event. `target` fields are set for `member_added` and
|
|
4251
|
-
`member_removed`.
|
|
4592
|
+
`member_removed`. `call` is set for `call` messages: one per call, posted when the call ends, `actor` is the
|
|
4593
|
+
initiator.
|
|
4252
4594
|
required: [kind, actor_id, actor_name]
|
|
4253
4595
|
properties:
|
|
4254
4596
|
kind: { $ref: "#/components/schemas/SystemEventKind" }
|
|
@@ -4259,6 +4601,7 @@ components:
|
|
|
4259
4601
|
actor_name: { type: string }
|
|
4260
4602
|
target_id: { $ref: "#/components/schemas/Id" }
|
|
4261
4603
|
target_name: { type: string }
|
|
4604
|
+
call: { $ref: "#/components/schemas/CallSummary" }
|
|
4262
4605
|
MessagePage:
|
|
4263
4606
|
type: object
|
|
4264
4607
|
required: [items, next_cursor, prev_cursor]
|
|
@@ -4862,3 +5205,229 @@ components:
|
|
|
4862
5205
|
properties:
|
|
4863
5206
|
message:
|
|
4864
5207
|
type: string
|
|
5208
|
+
|
|
5209
|
+
# ----------------------------------------------------------- calls
|
|
5210
|
+
CallConfig:
|
|
5211
|
+
type: object
|
|
5212
|
+
required: [enabled, max_participants, ring_timeout_seconds]
|
|
5213
|
+
properties:
|
|
5214
|
+
enabled: { type: boolean }
|
|
5215
|
+
max_participants:
|
|
5216
|
+
type: integer
|
|
5217
|
+
minimum: 2
|
|
5218
|
+
description: Most sessions joined to one call at the same time.
|
|
5219
|
+
ring_timeout_seconds:
|
|
5220
|
+
type: integer
|
|
5221
|
+
minimum: 1
|
|
5222
|
+
description: How long an invitation rings before it counts as missed.
|
|
5223
|
+
CallIdentityRequest:
|
|
5224
|
+
type: object
|
|
5225
|
+
required: [public_key]
|
|
5226
|
+
properties:
|
|
5227
|
+
public_key: { $ref: "#/components/schemas/CallIdentityKey" }
|
|
5228
|
+
CallIdentityKey:
|
|
5229
|
+
type: string
|
|
5230
|
+
description: |
|
|
5231
|
+
P-256 public key as an uncompressed point (65 bytes, first byte `0x04`), base64url without padding.
|
|
5232
|
+
minLength: 87
|
|
5233
|
+
maxLength: 87
|
|
5234
|
+
pattern: "^[A-Za-z0-9_-]+$"
|
|
5235
|
+
CallState:
|
|
5236
|
+
type: string
|
|
5237
|
+
description: "`ringing` until someone answers, `active` while people are in it, `ended` afterwards."
|
|
5238
|
+
enum: [ringing, active, ended]
|
|
5239
|
+
CallEndReason:
|
|
5240
|
+
type: string
|
|
5241
|
+
description: |
|
|
5242
|
+
Why the call ended: `completed` (people talked), `missed` (nobody answered in time), `declined` (the peer of a
|
|
5243
|
+
direct call declined), `cancelled` (the caller hung up before an answer), `failed` (the media service lost
|
|
5244
|
+
the call).
|
|
5245
|
+
enum: [completed, missed, declined, cancelled, failed]
|
|
5246
|
+
CallParticipantState:
|
|
5247
|
+
type: string
|
|
5248
|
+
description: "`left` and `declined` can become `joined` again in a group call."
|
|
5249
|
+
enum: [ringing, joined, declined, missed, left]
|
|
5250
|
+
CallParticipant:
|
|
5251
|
+
type: object
|
|
5252
|
+
required: [user_id, state, session_id, identity_key, joined_at]
|
|
5253
|
+
properties:
|
|
5254
|
+
user_id: { $ref: "#/components/schemas/Id" }
|
|
5255
|
+
state: { $ref: "#/components/schemas/CallParticipantState" }
|
|
5256
|
+
session_id:
|
|
5257
|
+
description: The session that joined; `null` unless `state` is `joined`.
|
|
5258
|
+
oneOf:
|
|
5259
|
+
- { type: string, format: uuid }
|
|
5260
|
+
- type: "null"
|
|
5261
|
+
identity_key:
|
|
5262
|
+
description: Call identity of the joined session; `null` unless `state` is `joined`.
|
|
5263
|
+
oneOf:
|
|
5264
|
+
- $ref: "#/components/schemas/CallIdentityKey"
|
|
5265
|
+
- type: "null"
|
|
5266
|
+
joined_at:
|
|
5267
|
+
description: When the participant last joined; `null` if never.
|
|
5268
|
+
oneOf:
|
|
5269
|
+
- $ref: "#/components/schemas/Timestamp"
|
|
5270
|
+
- type: "null"
|
|
5271
|
+
Call:
|
|
5272
|
+
type: object
|
|
5273
|
+
required:
|
|
5274
|
+
- id
|
|
5275
|
+
- chat_id
|
|
5276
|
+
- kind
|
|
5277
|
+
- state
|
|
5278
|
+
- end_reason
|
|
5279
|
+
- initiator_id
|
|
5280
|
+
- created_at
|
|
5281
|
+
- started_at
|
|
5282
|
+
- ended_at
|
|
5283
|
+
- ring_expires_at
|
|
5284
|
+
- epoch
|
|
5285
|
+
- version
|
|
5286
|
+
- max_participants
|
|
5287
|
+
- participants
|
|
5288
|
+
properties:
|
|
5289
|
+
id: { $ref: "#/components/schemas/Id" }
|
|
5290
|
+
chat_id: { $ref: "#/components/schemas/Id" }
|
|
5291
|
+
kind:
|
|
5292
|
+
type: string
|
|
5293
|
+
enum: [direct, group]
|
|
5294
|
+
state: { $ref: "#/components/schemas/CallState" }
|
|
5295
|
+
end_reason:
|
|
5296
|
+
oneOf:
|
|
5297
|
+
- $ref: "#/components/schemas/CallEndReason"
|
|
5298
|
+
- type: "null"
|
|
5299
|
+
initiator_id: { $ref: "#/components/schemas/Id" }
|
|
5300
|
+
created_at: { $ref: "#/components/schemas/Timestamp" }
|
|
5301
|
+
started_at:
|
|
5302
|
+
description: First answer; `null` while nobody answered.
|
|
5303
|
+
oneOf:
|
|
5304
|
+
- $ref: "#/components/schemas/Timestamp"
|
|
5305
|
+
- type: "null"
|
|
5306
|
+
ended_at:
|
|
5307
|
+
oneOf:
|
|
5308
|
+
- $ref: "#/components/schemas/Timestamp"
|
|
5309
|
+
- type: "null"
|
|
5310
|
+
ring_expires_at:
|
|
5311
|
+
description: When ringing invitations of this call turn into `missed`.
|
|
5312
|
+
$ref: "#/components/schemas/Timestamp"
|
|
5313
|
+
epoch:
|
|
5314
|
+
type: integer
|
|
5315
|
+
minimum: 0
|
|
5316
|
+
description: Key epoch; increases whenever the set of joined sessions or their identity keys change.
|
|
5317
|
+
version:
|
|
5318
|
+
type: integer
|
|
5319
|
+
minimum: 1
|
|
5320
|
+
description: Increases with every change of the call; ignore events with a lower version than one already seen.
|
|
5321
|
+
max_participants: { type: integer, minimum: 2 }
|
|
5322
|
+
participants:
|
|
5323
|
+
type: array
|
|
5324
|
+
description: Everyone invited or joined, the initiator first.
|
|
5325
|
+
items: { $ref: "#/components/schemas/CallParticipant" }
|
|
5326
|
+
CallList:
|
|
5327
|
+
type: object
|
|
5328
|
+
required: [items]
|
|
5329
|
+
properties:
|
|
5330
|
+
items:
|
|
5331
|
+
type: array
|
|
5332
|
+
items: { $ref: "#/components/schemas/Call" }
|
|
5333
|
+
StartCallRequest:
|
|
5334
|
+
type: object
|
|
5335
|
+
required: [client_request_id]
|
|
5336
|
+
properties:
|
|
5337
|
+
client_request_id:
|
|
5338
|
+
type: string
|
|
5339
|
+
format: uuid
|
|
5340
|
+
description: Idempotency key chosen by the client.
|
|
5341
|
+
JoinCallRequest:
|
|
5342
|
+
type: object
|
|
5343
|
+
properties:
|
|
5344
|
+
takeover:
|
|
5345
|
+
type: boolean
|
|
5346
|
+
default: false
|
|
5347
|
+
description: Move the user's participation from another session to this one.
|
|
5348
|
+
CallGrant:
|
|
5349
|
+
type: object
|
|
5350
|
+
required: [url, token, identity, expires_at]
|
|
5351
|
+
properties:
|
|
5352
|
+
url:
|
|
5353
|
+
type: string
|
|
5354
|
+
description: WebSocket URL of the media server (`wss://`).
|
|
5355
|
+
token:
|
|
5356
|
+
type: string
|
|
5357
|
+
description: Media access token for this call and session only; microphone audio only.
|
|
5358
|
+
identity:
|
|
5359
|
+
type: string
|
|
5360
|
+
description: The participant identity inside the media room (`<user_id>:<session_id>`).
|
|
5361
|
+
expires_at: { $ref: "#/components/schemas/Timestamp" }
|
|
5362
|
+
CallJoin:
|
|
5363
|
+
type: object
|
|
5364
|
+
required: [call, grant]
|
|
5365
|
+
properties:
|
|
5366
|
+
call: { $ref: "#/components/schemas/Call" }
|
|
5367
|
+
grant: { $ref: "#/components/schemas/CallGrant" }
|
|
5368
|
+
CallKeyEnvelope:
|
|
5369
|
+
type: object
|
|
5370
|
+
description: An HPKE Auth-mode envelope carrying one sender key (see `docs/calls-e2ee.md`).
|
|
5371
|
+
required: [epoch, sender_user_id, sender_session_id, recipient_session_id, enc, ciphertext]
|
|
5372
|
+
properties:
|
|
5373
|
+
epoch: { type: integer, minimum: 0 }
|
|
5374
|
+
sender_user_id: { $ref: "#/components/schemas/Id" }
|
|
5375
|
+
sender_session_id: { type: string, format: uuid }
|
|
5376
|
+
recipient_session_id: { type: string, format: uuid }
|
|
5377
|
+
enc:
|
|
5378
|
+
type: string
|
|
5379
|
+
description: HPKE encapsulated key, base64url without padding.
|
|
5380
|
+
maxLength: 128
|
|
5381
|
+
pattern: "^[A-Za-z0-9_-]+$"
|
|
5382
|
+
ciphertext:
|
|
5383
|
+
type: string
|
|
5384
|
+
description: Sealed sender key, base64url without padding.
|
|
5385
|
+
maxLength: 256
|
|
5386
|
+
pattern: "^[A-Za-z0-9_-]+$"
|
|
5387
|
+
CallKeyEnvelopeList:
|
|
5388
|
+
type: object
|
|
5389
|
+
required: [call_id, epoch, items]
|
|
5390
|
+
properties:
|
|
5391
|
+
call_id: { $ref: "#/components/schemas/Id" }
|
|
5392
|
+
epoch: { type: integer, minimum: 0 }
|
|
5393
|
+
items:
|
|
5394
|
+
type: array
|
|
5395
|
+
items: { $ref: "#/components/schemas/CallKeyEnvelope" }
|
|
5396
|
+
SendCallKeysRequest:
|
|
5397
|
+
type: object
|
|
5398
|
+
required: [epoch, envelopes]
|
|
5399
|
+
properties:
|
|
5400
|
+
epoch: { type: integer, minimum: 0 }
|
|
5401
|
+
envelopes:
|
|
5402
|
+
type: array
|
|
5403
|
+
minItems: 1
|
|
5404
|
+
maxItems: 64
|
|
5405
|
+
items: { $ref: "#/components/schemas/OutgoingCallKeyEnvelope" }
|
|
5406
|
+
OutgoingCallKeyEnvelope:
|
|
5407
|
+
type: object
|
|
5408
|
+
required: [recipient_session_id, enc, ciphertext]
|
|
5409
|
+
properties:
|
|
5410
|
+
recipient_session_id: { type: string, format: uuid }
|
|
5411
|
+
enc:
|
|
5412
|
+
type: string
|
|
5413
|
+
maxLength: 128
|
|
5414
|
+
pattern: "^[A-Za-z0-9_-]+$"
|
|
5415
|
+
ciphertext:
|
|
5416
|
+
type: string
|
|
5417
|
+
maxLength: 256
|
|
5418
|
+
pattern: "^[A-Za-z0-9_-]+$"
|
|
5419
|
+
CallSummary:
|
|
5420
|
+
type: object
|
|
5421
|
+
description: The call a `call` system message records.
|
|
5422
|
+
required: [call_id, kind, outcome, duration_seconds]
|
|
5423
|
+
properties:
|
|
5424
|
+
call_id: { $ref: "#/components/schemas/Id" }
|
|
5425
|
+
kind:
|
|
5426
|
+
type: string
|
|
5427
|
+
enum: [direct, group]
|
|
5428
|
+
outcome: { $ref: "#/components/schemas/CallEndReason" }
|
|
5429
|
+
duration_seconds:
|
|
5430
|
+
description: From the first answer to the end; `null` if nobody answered.
|
|
5431
|
+
oneOf:
|
|
5432
|
+
- { type: integer, minimum: 0 }
|
|
5433
|
+
- type: "null"
|