If you are not familiar with how the Apple Push Notificaion System (APNS) works, it is recommended that you read the [Local and Push Notification Programming Guide][pg] in particular the section on [A Push Notification and Its Path][pnpath].
### Sending a Push Notification
Sending push notifications is as simple as creating a new connection to APNS using the `Connection` class which should be configured, at minimum, with your applications' certificate and private key. The `Connection` class manages underlying sockets automatically.
Pushing a notification to a device is as simple as creating an instance of `Notification` which you then configure with the payload and call `Connection#pushNotification` with the notification object and the device token you wish to send it to. It is also possible to send the same notification object to multiple devices very efficiently please consult the documentation for `Connection#pushNotification` for more details.
The status of the `Connection` object, including underlying connections, can be observed by the events emitted. It is particularly important that you read the section below on *Handling Errors*.
### Monitoring the Feedback Service.
Apple provides the "Feedback Service" to inform you when devices you have attempted to send notifications to are no longer reachable - usually because the app has been deleted from the users device. The `Feedback` class will handle connecting to the Feedback service periodically and providing the results to your application for processing. More information on the correct usage of the Feedback service is included below.
Creates a new connection to the Apple Push Notification Service.
Options:
-`cert` {String} The filename of the connection certificate to load from disk (Defaults to: `cert.pem`)
-`certData` {Buffer|String} The certificate data. If supplied, will be used instead of loading from disk.
-`key` {String} The filename of the connection key to load from disk (Defaults to: `key.pem`)
-`keyData` {Buffer|String} The key data. If supplied will be used instead of loading from disk.
-`ca` An Array of Strings or Buffers of trusted certificates. If this is omitted several well known "root" CAs will be used, like VeriSign. - You may need to use option, this as some environments don't include the CA used by Apple.
-`pfx` {String} File path for private key, certificate and CA certs in PFX or PKCS12 format. If supplied will be used instead of certificate and key above
-`pfxData` {Buffer|String} PFX or PKCS12 format data containing the private key, certificate and CA certs. If supplied will be used instead of loading from disk.
-`passphrase` {String} The passphrase for the connection key, if required
-`gateway` {String `gateway.push.apple.com`} The gateway server to connect to.
-`port` {Number} Gateway port (Defaults to: `2195`)
-`rejectUnauthorized` {Boolean} Reject Unauthorized property to be passed through to tls.connect() (Defaults to `true`)
-`enhanced` {Boolean} Whether to use the enhanced notification format (recommended, defaults to: `true`)
-`cacheLength` {Number} Number of notifications to cache for error purposes (See "Handling Errors" below, (Defaults to: 100)
-`autoAdjustCache` {Boolean} Whether the cache should grow in response to messages being lost after errors. (Will still emit a 'cacheTooSmall' event) (Defaults to: `false`)
-`maxConnections` {Number} The maximum number of connections to create for sending messages. (Defaults to: `1`)
-`connectionTimeout` {Number} The duration the socket should stay alive with no activity in milliseconds. 0 = Disabled. (Defaults to: `0`)
-`buffersNotifications` {Boolean} Whether to buffer notifications and resend them after failure. (Defaults to: `true`)
-`fastMode` {Boolean} Whether to aggresively empty the notification buffer while connected - if set to true node-apn may enter a tight loop under heavy load while delivering notifications. (Defaults to: `false`)
Creates a new connection to the Apple Push Notification Feedback Service and if `interval` isn't disabled automatically begins polling the service. Many of the options are the same as `apn.Connection()`
Attach an event to the `feedback` event to receive output.
-`cert` {String} The filename of the connection certificate to load from disk (Defaults to: `cert.pem`)
-`certData` {Buffer|String} The certificate data. If supplied, will be used instead of loading from disk.
-`key` {String} The filename of the connection key to load from disk (Defaults to: `key.pem`)
-`keyData` {Buffer|String} The key data. If supplied will be used instead of loading from disk.
-`ca` An Array of Strings or Buffers of trusted certificates. If this is omitted several well known "root" CAs will be used, like VeriSign. - You may need to use option, this as some environments don't include the CA used by Apple.
-`pfx` {String} File path for private key, certificate and CA certs in PFX or PKCS12 format. If supplied will be used instead of certificate and key above
-`pfxData` {Buffer|String} PFX or PKCS12 format data containing the private key, certificate and CA certs. If supplied will be used instead of loading from disk.
-`passphrase` {String} The passphrase for the connection key, if required
-`gateway` {String `feedback.push.apple.com`} The gateway server to connect to.
-`port` {Number} Gateway port (Defaults to: `2196`)
-`rejectUnauthorized` {Boolean} Reject Unauthorized property to be passed through to tls.connect() (Defaults to `true`)
-`batchFeedback` {Boolean} Sets the behaviour for triggering the `feedback` event. When `true` the event will be triggered once per connection with an array of timestamp and device token tuples. Otherwise a `feedback` event will be emitted once per token received. (Defaults to: true)
Returns a new `Device` object. `deviceToken` can be a `Buffer` or a `String` containing a "hex" representation of the token. Throws an error if the deviceToken supplied is invalid.
Returns a new `Notification` object. You can optionally pass in an object representing the payload, or configure properties on the returned object. See below.
This is the business end of the module. Create a `Notification` object and pass it in, along with a single recipient or an array of them and node-apn will take care of the rest, delivering the notification to each recipient.
A "recipient" is either a `Device` object, a `String`, or a `Buffer` containing the device token. `Device` objects are used internally and will be created if necessary. Where applicable, all events will return a `Device` regardless of the type passed to this method.
If you wish to send notifications containing emoji or other multi-byte characters you will need to ensure they are encoded correctly within the string. Notifications can be transmitted to Apple in either UTF-8 or UTF-16 and strings passed in for the Alert will be converted accordingly. UTF-8 is recommended for most cases as it can represent exactly the same characters as UTF-16 but is usually more space-efficient. When manually encoding strings as above with `\uD83D\uDCE7` the character (in this case a surrogate pair) is escaped in UTF-16 form because Javascript uses UTF-16 internally for Strings but does not handle surrogate pairs automatically.
If in doubt, leave the encoding as default. If you experience any problems post a question in the [node-apn Google Group][googlegroup].
Used to manually adjust the "cacheLength" property in the options. This is ideal if you choose to use the `cacheTooSmall` event to tweak your environment. It is safe for increasing and reducing cache size.
Emitted when an error occurs during initialisation of the module, usually due to a problem with the keys and certificates.
### Event: 'socketError'
`function (error) { }`
Emitted when the connection socket experiences an error. This may be useful for debugging but no action should be necessary.
### Event: 'transmitted'
`function (notification, device) { }`
Emitted when a notification has been sent to Apple - not a guarantee that it has been accepted by Apple, an error relating to it may occur later on. A notification may also be "transmitted" several times if a preceding notification caused an error requiring retransmission.
### Event: 'cacheTooSmall'
`function (sizeDifference) { }`
Emitted when Apple returns a notification as invalid but the notification has already been expunged from the cache - usually due to high throughput and indicates that notifications will be getting lost. The parameter is an estimate of how many notifications have been lost. You should experiment with increasing the cache size or enabling ```autoAdjustCache``` if you see this frequently.
**Note**: With ```autoAdjustCache``` enabled this event will still be emitted when an adjustment is triggered.
### Event: 'connected'
`function (openSockets) { }`
Emitted when a connection to Apple is successfully established. The parameter indicates the number of open connections. No action is required as the connection is managed internally.
### Event: 'disconnected'
`function (openSockets) { }`
Emitted when the connection to Apple has been closed, this could be for numerous reasons, for example an error has occurred or the connection has timed out. The parameter is the same as for `connected` and again, no action is required.
### Event: 'timeout'
`function() { }`
Emitted when the connectionTimeout option has been specified and no activity has occurred on a socket for a specified duration. The socket will be closed immediately after this event and a `disconnected` event will also be emitted.
Emitted when a message has been received from Apple stating that a notification was invalid. If the notification is still in the cache it will be passed as the second argument, otherwise null. Where possible the associated `Device` object will be passed as a third parameter, however in cases where the token supplied to the module cannot be parsed into a `Buffer` the supplied value will be returned.
For further information please read the section below on "Handling Errors".
## Class: apn.Notification
As of version 1.2.0 it is possible to use a set of methods provided by Notification object (`setAlertText`, `setActionLocKey`, `setLocKey`, `setLocArgs`, `setLaunchImage`) to aid the creation of the alert parameters. For applications which provide Newsstand capability there is a new boolean parameter `note.newsstandAvailable` to specify `content-available` in the payload.
For iOS 7 applications which support Silent Remote Notifications you can use the `note.contentAvailable` property. This is identical in functionality to `note.newsstandAvailable` without the confusion of the "Newstand" terminology.
A `Notification` enapsulates the data to be compiled down to JSON and pushed to a device. See the [payload documentation][pl] for more details. At present the total length of the payload accepted by Apple is 256 bytes.
The maximum number of retries which should be performed when sending a notification if an error occurs. A value of 0 will only allow one attempt at sending (0 retries). Set to -1 to disable (default).
The encoding to use when transmitting the notification to APNS, defaults to `utf8`. `utf16le` is also possible but as each character is represented by a minimum of 2 bytes, will at least halve the possible payload size. If in doubt leave as default.
This object represents the root JSON object that you can add custom information for your application to. The properties below will only be added to the payload (under `aps`) when the notification is prepared for sending.
### notification.badge
The value to specify for `payload.aps.badge`
### notification.sound
The value to specify for `payload.aps.sound`
### notification.alert
The value to specify for `payload.apns.alert` can be either a `String` or an `Object` as outlined by the payload documentation.
The value to specify for the `mdm` field where applicable.
### notification.setAlertText(alert)
Set the `aps.alert` text body. This will use the most space-efficient means.
### notification.setActionLocKey(key)
Set the `action-loc-key` property of the `aps.alert` object.
### notification.setLocKey(key)
Set the `loc-key` property of the `aps.alert` object.
### notification.setLocArgs(args)
Set the `loc-args` property of the `aps.alert` object.
### notification.setLaunchImage(image)
Set the `launch-image` property of the `aps.alert` object.
### notification.trim()
Attempt to automatically trim the notification alert text body to meet the payload size limit of 256 bytes.
## Class: apn.Feedback
### feedback.start()
Trigger a query of the feedback service. If `interval` is non-zero then this method will be called automatically.
### feedback.cancel()
You can cancel the interval by calling `feedback.cancel()`. If you do not wish to have the service automatically queried then set `interval` to 0 and use `feedback.start()` to manually invoke it one time.
Emitted when an error occurs initialising the module. Usually caused by failing to load the certificates.
### Event: 'feedbackError'
`function (error) { }`
Emitted when an error occurs receiving or processing the feedback and in the case of a socket error occurring. These errors are usually informational and node-apn will automatically recover.
Emitted when data has been received from the feedback service, typically once per connection. `feedbackData` is an array of objects, each containing the `time` returned by the server (epoch time) and the `device` a `Buffer` containing the device token.
If `batchFeedback` has been disabled this will be emitted once per item, with two parameters, the `time` and the `device`.
The documentation on [The Feedback Service][feedback] explains how you should use the data emitted from the 'feedback' event. The most important part is quoted here:
> Query the feedback service daily to get the list of device tokens. Use the timestamp to verify that the device tokens haven’t been reregistered since the feedback entry was generated. For each device that has not been reregistered, stop sending notifications. APNs monitors providers for their diligence in checking the feedback service and refraining from sending push notifications to nonexistent applications on devices.
Typically you should record the timestemp when a device registers with your service along with the token and update it every time your app re-registers the token. When the feedback service returns a token with an associated timestamp which is newer than that stored by you then you should disable, or remove, the token from your system and stop sending notifications to it.
When an error occurs while pushing a notification and the enhanced interface is enabled Apple sends a message back to node-apn containing the "identifier" of the notification which caused the error and an associated error code (See: [The Binary Interface and Notification Formats][errors]). Apple does not return the entire message so node-apn caches a number of notifications after they are sent, so in the event an error occurs node-apn can find the one with the correct identifier from the cache and trigger the `transmissionError` event with the appropriate `Notification` object and `Device` it should have been delivered to.
Apple guarantees that if one notification causes an error none of the following notifications will be processed, so if node-apn can find the correct notification which caused the error in the cache, then it can automatically re-send all the ones afterward.
It's not a good idea to cache notifications indefinitely because after a certain length of time has passed we can be confident that Apple have received the notification without problem so it is implemented as a fixed size FIFO queue internally. Depending on how high-volume your environment is it's possible that many notifications will be successfully sent to Apple before the error response is sent.
The cache size defaults to 100 which will have neglible impact on memory usage and will suit low-volume environments. Testing has shown that an error response can take as long as 200ms, while the module has proven the ability to send over 5000 notifications per second, so it may necessary to increase the size of the cache to ensure node-apn can find the problematic one and resend all the following ones. The `autoAdjustCache` option is designed to address this problem but it risks losing notifications until the size has automatically increased accordingly, for best results manual adjustment according to your requirements is recommended.
If the cache is too small then node-apn wont be able to return the bad notification to through the `transmissionError` event and will pass `null` instead. The module _will_ resend all notifications in the cache but some may have been lost between the bad notification and the first one in the cache.
If you wish to disable the automatic resending functionality please consult the `buffersNotifications` configuration option.
[pg]:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html#//apple_ref/doc/uid/TP40008194-CH1-SW1 "Local and Push Notification Programming Guide"
[pnpath]:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW10 "A Push Notification and Its Path"
[errors]:https://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4 "The Binary Interface and Notification Formats"
[feedback]:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW3 "The Feedback Service"
[pl]:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1 "Local and Push Notification Programming Guide: Apple Push Notification Service"