.. _http-push: Push Notifications over HTTP ============================ .. contents:: :local: :depth: 3 Overview -------- The HTTP gateway for pushes allows you to send Push Notifications directly. It accepts POST request with JSON formatted body and transfers push notifications to the device using appropriate Apple's or Google's notification services. .. note:: Our :doc:`old HTTP service` that accepts ``application/x-www-form-urlencoded`` data will continue to be available on its address. As of iOS13, the app uses two application ID / push token pairs. One for pushkit pushes which are now only allowed for notifying incoming calls and the app needs to present the incoming call screen as soon as it receives them. The other for remote-notification pushes which should be used for all other scenarios. You can still use the pushkit pushes for mission critical command/reprovision pushes but the callkit incoming call screen will flash for a brief moment. The drawback of silent remote-notifications is that they won't be delivered to the app if it was force quit, or they may take longer to deliver based on the battery saving policy. Single push ----------- To send a single push, use the address ``https://pnm.cloudsoftphone.com/pnm2/send``. It accepts POST requests with JSON body. The sent JSON should be an object that has the following attributes: Attributes ~~~~~~~~~~~~~~~~~~~ ``verb`` Type of the Push notification. See `Message Types`_ for more information. ``AppId`` Application ID. This parameter is required ``DeviceToken`` Identifies the device that will receive the Push. This parameter is required. ``Selector`` Identifies the account that should process the Push notification. Not required for ``NotifyGenericTextMessage``, required for other Push types. ``Message`` The displayed message for ``NotifyGenericTextMessage`` Push type. The required attributes are ``verb``, ``AppId``, ``DeviceToken``. Leaving any of them out will not send a push notification. You can find DeviceToken in your SIPIS :doc:`database<../../sipis/database>` or you can get it from :doc:`Push Token Reporter<../client/push_token_reporter>`. Return values ~~~~~~~~~~~~~ The return value for a properly formatted input is a HTTP 2xx response with JSON object containing two items: ``status`` Integer that is 200 if everything is OK or non 200 (400, 404 or 500 if there was an error). ``response`` A string that describes the error. If the request is not a valid JSON, is not a POST request or does not have proper Content-Type, Non 400 HTTP response ``Bad Request`` is returned. You may also get HTTP response 5xx (500 Internal Server Error). That means there is a problem with the service. ``status`` field ```````````````` The value 200 means everything was OK. Other values signify an error. Notable code is 404. This means that your request was valid but the ``DeviceToken`` is no longer registered at Google and you should not more pushes to this ``DeviceToken``. Message Types ~~~~~~~~~~~~~ The ``verb`` attribute can have the following values. ``NotifyTextMessage`` This message type is used to notify user about incoming message. On iOS 13 and higher, the notification may not wake up the application to actually fetch the messages from the server, so the notification itself has to contain the badge count, the sound and the message preview and content type. Upon receiving this notification and displying it to the user the iOS may also automatically deliver the notification to the application which will perform the fetch in the background using the :ref:`fetch_messages_webservice` and will replace the notifiction body with the actual message content. On the older iOSes and Android the app receives this type of push message silently, it runs the fetch web service in the background and when the new messages are fetched, the notification about them is presented to user. .. note:: This verb needs additional parameter ``Selector`` which identifies the user's account. It is reported in the same way as ``DeviceToken``. iOS 13+ additional parameters ````````````````````````````` ``Badge`` This is required for iOS 13+ and it should contain the total number of unread messages. This is the number that will appear in the badge on the application icon. ``Sound`` It should either contain ``default`` to play default iOS notification sound, it can be omitted or set to empty string for notification without a sound, or it can be a name of any bundled sound like ``s1.caf``, ``s2.caf`` etc to play the specific sound. ``UserName`` or ``UserDisplayName`` The name of the sender. ``Message`` The message preview. ``ContentType`` The content type of the message. Some content types are turned into a silent notification that is not presented to the user but it *may* by delivered to the app in the background to initiate the fetch. ``Id`` The ID of the message that is later used in the fetch response as ``sms_id``. If it is not specified it can result in double notifications for the message. One when the push is received on the device and second when the message is actually fetched in the background. ``ThreadId`` Identifier of the thread (stream) so the messages can be grouped together in the iOS notification center. ``NotifyGenericTextMessage`` The simplest message type which is used to show a text notification to user. The app doesn't process this message in other way other than displaying the text on screen. This can be used for various marketing messages, reminders etc. iOS 13+ additional parameters ````````````````````````````` ``Sound`` It should either contain ``default`` to play default iOS notification sound, it can be omitted or set to empty string for notification without a sound, or it can be a name of any bundled sound like ``s1.caf``, ``s2.caf`` etc to play the specific sound. ``NotifyReprovision`` This push causes the application to reprovision – reload its configuration from the portal and from external provisioning URL – immediately. No notification to the user is presented. Multiple Pushes ------------------------------- To send multiple pushes you can use the address ``https://pnm.cloudsoftphone.com/pnm2/multisend``. This endpoint accepts POST requests with JSON body (and appropriate content type). The body of the request is a list of objects for individual pushes. The format of the objects is described in `Single push_` section. The response for a properly formatted input is a list of responses described in the previous section. See examples below. Sending a non POST request, a request without JSON content type or a request with invalid JSON will return non 2xx HTTP response with no guarantees as to a specific code or content type of the response. .. note:: If you send one JSON object to this endpoint representing your Push notification, it will be accepted as if it was a one element list. That means the response will come as a one element list. Examples -------- For these examples we will use ``NotifyGenericTextMessage`` verb. Single Push ~~~~~~~~~~~ Valid request ````````````` .. code-block:: bash curl --header "Content-Type: application/json" \ --request POST \ --data '{"DeviceToken": "ValidToken", "Selector": "ValidSelector", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "Some message"}' \ https://pnm.cloudsoftphone.com/pnm2/send Response with HTTP code 200: .. code-block:: json {"code": 200, "response": "Your message was sent."} This reply means that the request was accepted by upstream service. It does not mean that the push was delivered. Example response with HTTP code 200 with upstream error: .. code-block:: json {"code": 404, "response": "Pnmediator returned unknown error: ERR:404 Not Found"} These errors include missing data in objects, AppIds not registered at our push service or error responses from upstream services. Multiple pushes ~~~~~~~~~~~~~~~ Partially valid request ``````````````````````` The following request has two valid JSON objects and one non-object (``null``). .. code-block:: bash curl --header "Content-Type: application/json" \ --request POST \ --data '[{"DeviceToken": "ValidToken1", "Selector": "ValidSelector1", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "some message"}, {"DeviceToken": "ValidToken2", "Selector": "ValidSelector2", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "some other message"}, null]'\ https://pnm.cloudsoftphone.com/pnm2/multisend Response with code 200: .. code-block:: json [{"code": 200, "response": "Your message was sent."}, {"code": 404, "response": "Pnmediator returned an error: ERR:404 Not Found\n"}, {"code": 400, "response": "Bad object you sent here"}] For a convenience, sending a valid JSON object is equivalent to sending it in a list with one element: .. code-block:: bash curl --header "Content-Type: application/json" \ --request POST \ --data '{"DeviceToken": "ValidToken", "Selector": "ValidSelector", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "Some message"}' \ https://pnm.cloudsoftphone.com/pnm2/multisend Response with HTTP code 200: .. code-block:: json [{"code": 200, "response": "Your message was sent."}] Note that reply is in a list. If the JSON is not an object, the responses will differ. Sending ``null`` responds with HTTP error code 400, sending ``[null]`` responds with a list with one response.