# Push Notifications ```mermaid --- Push lifecycle --- sequenceDiagram actor Andrea participant API participant Broker Note over Andrea, Broker : Creating a push subscription Andrea ->>+ API : Client Boot API ->>- Andrea : Boot message with VAPID keys Andrea ->>+ API : Subscribe to events Andrea ->>+ Broker : New Push Subscription Broker ->>- Andrea : Subscription URL Andrea ->>+ API : Subscribe API ->>- Andrea : Created API ->>- Andrea : Disconnect Note over Andrea, Broker : Asynchronous notification API ->> Broker : Push Publication Broker ->> Andrea : Push Delivery Andrea ->>+ API : Resume event subscription API ->>- Andrea : Disconnect Note over Andrea, Broker : VAPID key rotation Andrea ->>+ API : Subscribe to events API -) Andrea : VAPID key changed Andrea ->>+ Broker : Unsubscribe Broker ->>- Andrea : Unsubscribed Andrea ->>+ Broker : New Push Subscription Broker ->>- Andrea : Subscription URL Andrea ->>+ API : Subscribe API ->>- Andrea : Created API ->>- Andrea : Disconnect ``` Pilcrow uses [Web Push] to notify clients asynchronously of interesting events, to allow clients to disconnect from [the event stream](events.md) while keeping their users informed of updates to conversations. Clients are _not required_ to implement push subscriptions. Pilcrow's primarily channel for communicating real-time communications data to clients is the [event stream](events.md). [Web Push]: https://developer.mozilla.org/en-US/docs/Web/API/Push_API ## VAPID keys Pilcrow uses a generated Voluntary Application Server Identification (VAPID) key to authenticate to push brokers. Clients do not generally need to handle VAPID authentication themselves, but, due to the design of the Web Push protocol, clients are responsible for providing Pilcrow's VAPID key to push brokers when subscribing to notifications. To make this possible, Pilcrow delivers its VAPID key to clients via the event stream. See the [VAPID key events](events.md#vapid-key-events) section for details of these events. Pilcrow rotates the VAPID key periodically, and sends all clients an event when this occurs. This immediately invalidates all existing subscriptions, as the previous VAPID key is destroyed. Clients that wish to continue receiving messages must re-subscribe using the new VAPID key when this happens, and will miss any Web Push messages sent during this interval. ## Receiving Web Push messages Pilcrow sends web push messages to subscriptions. A Pilcrow user may have many subscriptions - in principle, generally one per client, but Pilcrow does not enforce any such limit. Clients create subscriptions as needed, and inform the Pilcrow server of those subscriptions to begin the flow of push messages. The specific taxonomy and structure of push messages is still under development. This API is even more experimental than the rest of Pilcrow. Pilcrow keeps track of the token used to create a web push subscription, and abandons subscriptions when that token is invalidated. This prevents the server from inadvertently sending information to a client after the user for which that information is intended has logged out, or after another user has taken over the client. Clients are responsible for re-establishing subscriptions on login if they wish to resume push messaging. ## `POST /api/push/subscribe` Inform the Pilcrow server of a push subscription. ### Request ```json { "subscription": { "endpoint": "https://example.push.com/P1234", "keys": { "p256dh": "base64-encoded key", "auth": "base64-encoded authentication secret" } } "vapid": "BKILjh0SzTiHOZ5P_sfduv-iqtOg_S18nR7ePcjnDivJaOY6nOG1L3OmvjXjNnthlRDdVnawl1_owfdPCvmDt5U=" } ``` The request must have the following fields: | Field | Type | Description | | :------------- | :----- | :------------------------------------------------------ | | `subscription` | object | The push subscription object created by the user agent. | | `vapid` | string | The VAPID key used to create the subscription. | The `subscription` field should be the result of calling `toJSON()` on a `PushSubscription` object in the DOM API. For details, see [the WebPush specification](https://w3c.github.io/push-api/#dom-pushsubscription-tojson) or [MDN](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription/toJSON). The `vapid` field should be set to the key used when creating the subscription, which should in turn be obtained from the event stream. [wp-example]: https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription#sending_coding_information_to_the_server This request can be retried on any non-400 response, including any network-related errors. A duplicate subscription with the same endpoint, the same public key and the same authentication secret will be accepted by the server even if the subscription has already been created. ### Success This endpoint will respond with a status of `201 Created` when successful. The response body is empty. ### Duplicate endpoint If the push subscription's endpoint URL is already associated with a subscription with different keys, then Pilcrow will return a `409 Conflict` response. ### Stale VAPID key If the provided `vapid` key is not the server's current VAPID key, then the client has created a subscription which is not usable. This may happen if Pilcrow rotates its key while a client is negotiating with a Web Push broker to set up a subscription using the old key. Pilcrow will respond a `400 Bad Request` response. **This response includes a JSON body**, unlike other errors, and will have a `content-type: application/json` header. The response will include the following fields: | Field | Type | Description | | :-------- | :----- | :------------------------------ | | `message` | string | A human-readable error message. | | `key` | string | Pilcrow's new VAPID key. | Clients should immediately destroy the push subscription they were attempting to create, and may try again using the new VAPID key (either immediately, using the key from the response, or asynchronously, using the key when it is delivered via the event stream).