Article

Sending Notification Requests to APNs

Transmit your remote notification payload and device token information to APNs.

Overview

When you have a notification to send to a user, your provider must construct a POST request and send it to Apple Push Notification service (APNs). Your request must include the following information:

  • The JSON payload that you want to send

  • The device token for the user’s device

  • Request-header fields specifying how to deliver the notification

  • For token-based authentication, your provider server’s current authentication token

Upon receiving your server’s POST request, APNs validates the request using either the provided authentication token or your server’s certificate. If validation succeeds, APNs uses the provided device token to identify the user’s device. It then tries to send your JSON payload to that device.

Establish a Connection to APNs

Use HTTP/2 and TLS 1.2 or later to establish a connection between your provider server and one of the following servers:

Use the production server for your shipping apps and the development server for testing. When sending many remote notifications, you can establish multiple connections to these servers to improve performance. For example, if you have multiple provider servers, each one can establish its own connection.

APNs allows multiple concurrent streams for each connection, but don’t assume a specific number of streams. The exact number varies based on server load and whether you use a provider certificate or an authentication token. For example, when using an authentication token, APNs allows only one stream until you post a request with a valid authentication token. APNs ignores HTTP/2 PRIORITY frames, so don’t send them on your streams.

If your provider certificate is revoked, or if you revoke your authentication token, close all connections to APNs, fix the problem, and then open new connections. APNs may also terminate a connection by sending a GOAWAY frame. The payload of the GOAWAY frame includes JSON data with a reason key, indicating the reason for the connection termination. For a list of values for the reason key, see .

Create and Send a POST Request to APNs

To send a notification to a user’s device, construct and send a POST notification to APNs. Send this request over the connection you created using HTTP/2 and TLS. To construct your POST notification, you must already have the following pieces of information:

In addition to the preceding data, add the header fields in Table 1 to your request. Some header fields are required for delivering the notification. Other headers are optional or may be dependent on whether you’re using token-based or certificate-based authentication.

Table 1

Header fields for a POST request

Header field

Description

:method

(Required) The value POST.

:path

(Required) The path to the device token. The value of this header is /3/device/<device_token>, where <device_token> is the hexadecimal bytes that identify the user’s device. Your app receives the bytes for this device token when registering for remote notifications; see Registering Your App with APNs.

authorization

(Required for token-based authentication) The value of this header is bearer <provider_token>, where <provider_token> is the encrypted token that authorizes you to send notifications for the specified topic. APNs ignores this header if you use certificate-based authentication. For more information, see Establishing a Token-Based Connection to APNs.

apns-push-type

(Required for watchOS 6 and later; recommended for macOS, iOS, tvOS, and iPadOS) The value of this header must accurately reflect the contents of your notification’s payload. If there is a mismatch, or if the header is missing on required systems, APNs may return an error, delay the delivery of the notification, or drop it altogether.

apns-id

A canonical UUID that is the unique ID for the notification. If an error occurs when sending the notification, APNs includes this value when reporting the error to your server. Canonical UUIDs are 32 lowercase hexadecimal digits, displayed in five groups separated by hyphens in the form 8-4-4-4-12. An example looks like this: 123e4567-e89b-12d3-a456-42665544000. If you omit this header, APNs creates a UUID for you and returns it in its response.

apns-expiration

The date at which the notification is no longer valid. This value is a UNIX epoch expressed in seconds (UTC). If the value is nonzero, APNs stores the notification and tries to deliver it at least once, repeating the attempt as needed until the specified date. If the value is 0, APNs attempts to deliver the notification only once and doesn’t store it.

apns-priority

The priority of the notification. If you omit this header, APNs sets the notification priority to 10.

Specify 10 to send the notification immediately. A value of 10 is appropriate for notifications that trigger an alert, play a sound, or badge the app’s icon. Specifying this priority for a notification that has a payload containing the content-available key causes an error.

Specify 5 to send the notification based on power considerations on the user’s device. Use this priority for notifications that have a payload that includes the content-available key. Notifications with this priority might be grouped and delivered in bursts to the user’s device. They may also be throttled, and in some cases not delivered.

apns-topic

The topic for the notification. In general, the topic is your app’s bundle ID, but it may have a suffix based on the push notification’s type.

apns-collapse-id

An identifier you use to coalesce multiple notifications into a single notification for the user. Typically, each notification request causes a new notification to be displayed on the user’s device. When sending the same notification more than once, use the same value in this header to coalesce the requests. The value of this key must not exceed 64 bytes.

The apns-push-type header field has six valid values. The descriptions below describe when and how to use these values.

alert

Use the alert push type for notifications that trigger a user interaction—for example, an alert, badge, or sound. If you set this push type, the apns-topic header field must use your app’s bundle ID as the topic. For more information, see Generating a Remote Notification.

The alert push type is required on watchOS 6 and later. It is recommended on macOS, iOS, tvOS, and iPadOS.

background

Use the background push type for notifications that deliver content in the background, and don’t trigger any user interactions. If you set this push type, the apns-topic header field must use your app’s bundle ID as the topic. For more information, see Pushing Background Updates to Your App.

The background push type is required on watchOS 6 and later. It is recommended on macOS, iOS, tvOS, and iPadOS.

voip

Use the voip push type for notifications that provide information about an incoming Voice-over-IP (VoIP) call. For more information, see Responding to VoIP Notifications from PushKit.

If you set this push type, the apns-topic header field must use your app’s bundle ID with .voip appended to the end. If you’re using certificate-based authentication, you must also register the certificate for VoIP services. The topic is then part of the 1.2.840.113635.100.6.3.4 or 1.2.840.113635.100.6.3.6 extension.

The voip push type is not available on watchOS. It is recommended on macOS, iOS, tvOS, and iPadOS.

complication

Use the complication push type for notifications that contain update information for a watchOS app’s complications. For more information, see Updating Your Timeline.

If you set this push type, the apns-topic header field must use your app’s bundle ID with .complication appended to the end. If you’re using certificate-based authentication, you must also register the certificate for WatchKit services. The topic is then part of the 1.2.840.113635.100.6.3.6 extension.

The complication push type is recommended for watchOS and iOS. It is not available on macOS, tvOS, and iPadOS.

fileprovider

Use the fileprovider push type to signal changes to a File Provider extension. If you set this push type, the apns-topic header field must use your app’s bundle ID with .pushkit.fileprovider appended to the end. For more information, see Using Push Notifications to Signal Changes.

The fileprovider push type is not available on watchOS. It is recommended on macOS, iOS, tvOS, and iPadOS.

mdm

Use the mdm push type for notifications that tell managed devices to contact the MDM server. If you set this push type, you must use the topic from the UID attribute in the subject of your MDM push certificate. For more information, see Device Management.

The mdm push type is not available on watchOS. It is recommended on macOS, iOS, tvOS, and iPadOS.

APNs requires the use of HPACK (header compression for HTTP/2), which prevents repeatedly storing header keys and values. APNs maintains a small dynamic table for HPACK. To avoid filling up that table, encode your headers in the following way—especially when using many streams:

  • Encode the :path and authorization values as literal header fields without indexing.

  • Encode the apns-id, apns-expiration, and apns-collapse-id values differently based on whether this is an initial or subsequent request.

    • The first time you send these headers, encode them with incremental indexing to add the header fields to the dynamic table.

    • For subsequent requests, encode these headers as literal header fields without indexing.

  • Encode all other fields as literal header fields with incremental indexing.

Put the JSON payload with the notification’s content into the body of your request. The JSON payload must not be compressed and is limited to a maximum size of 4 KB (4096 bytes). For a Voice over Internet Protocol (VoIP) notification, the maximum size is 5 KB (5120 bytes).

Listing 1 shows a sample request constructed with an authentication token.

Listing 1

A POST request with an authentication token

HEADERS
  - END_STREAM
  + END_HEADERS
  :method = POST
  :scheme = https
  :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
  host = api.sandbox.push.apple.com
  authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
		 jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6
		 Lxw7LZtEQcH6JENhJTMArwLf3sXwi
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  apns-push-type = alert
  apns-expiration = 0
  apns-priority = 10
  apns-topic = com.example.MyApp
DATA
  + END_STREAM
  { "aps" : { "alert" : "Hello" } }

Listing 2 shows a sample request constructed for use with a certificate. APNs uses the app’s bundle ID as the default topic.

Listing 2

A POST request relying on a certificate

HEADERS
  - END_STREAM
  + END_HEADERS
  :method = POST
  :scheme = https
  :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
  host = api.sandbox.push.apple.com
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  apns-push-type = alert
  apns-expiration = 0
  apns-priority = 10
DATA
  + END_STREAM
  { "aps" : { "alert" : "Hello" } }

See Also

Server Tasks

Generating a Remote Notification

Send notifications to the user’s device with a JSON payload.

Handling Notification Responses from APNs

Respond to the status codes returned by the APNs servers.

Pushing Background Updates to Your App

Deliver notifications that wake your app and update it in the background.