Push Notifications over HTTP


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.


Our 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:


Type of the Push notification. See Message Types for more information.
Application ID. This parameter is required
Identifies the device that will receive the Push. This parameter is required.
Identifies the account that should process the Push notification. Not required for NotifyGenericTextMessage, required for other Push types.
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 database or you can get it from Push Token Reporter.

Return values

The return value for a properly formatted input is a HTTP 2xx response with JSON object containing two items:

Integer that is 200 if everything is OK or non 200 (400, 404 or 500 if there was an error).
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.


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 Fetch Messages 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.


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

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.
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.
The message preview.
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.
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.
Identifier of the thread (stream) so the messages can be grouped together in the iOS notification center.


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.

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.


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.


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.


For these examples we will use NotifyGenericTextMessage verb.

Single Push

Valid request

curl --header "Content-Type: application/json" \
--request POST \
--data '{"DeviceToken": "ValidToken", "Selector": "ValidSelector", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "Some message"}' \

Response with HTTP code 200:

{"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": 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).

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]'\

Response with code 200:

[{"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:

curl --header "Content-Type: application/json" \
--request POST \
--data '{"DeviceToken": "ValidToken", "Selector": "ValidSelector", "AppId": "valid.appid", "verb": "NotifyGenericTextMessage", "Message": "Some message"}' \

Response with HTTP code 200:

[{"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.