A few years ago, Apple announced new APIs to interact with their push notification services. In late 2015, these APIs were finally made available for developers to use.

In this post we will talk about the very basics of using Apple’s new Push Notification services, with basic bash cURL code.

1. Advantages

Let’s talk about why Apple decided to make new APIs for push notifications in the first place.

Those who have worked with the first iteration of the system – the one that has existed since the iOS 3.0 days – know how daunting it was to get this to work. You had to provision two different push notification certificates, one for development, and one for production, and you had to keep track of them. Not only that, but the API was entirely socket based, and it was very unreliable. You had to take into account what could happen if you sent a lot of push notifications at once – if you sent more than one notification per second, the notification would often get lost, and many of your users would never get the notification. So developers had to create timers and let the socket “rest” for a little while before sending another notification. For small sets of notifications, this was no issue, but imagine having to send 30,000 push notifications at once – waiting one second per notification would make it take 8 hours to send all the notifications to all the devices!

The new APIs are now HTTP/2 based, and it’s expected that the socket-based implementation will get deprecated soon and eventually removed, so you should start using the new APIs now.

One of the advantages to the new system is that you only need to create one certificate that can be used for production and development deployments of your app. Yes, that’s right, you no longer need to keep track of two sets of public key-pairs to achieve this anymore.

You can simply generate a Production push notification certificate and it will work for both cases. In my tests, creating a Development push notification certificate did not seem to work (I got an error message in the lines of curl: (16) Error in the HTTP2 framing layer).

And yes, if you are using Fastlane as part of your development flow, you can simply use the pem command to generate a production certificate. You never have to specify you want a development certificate because you will never need it anymore. Woot!

Type pem, fill in your Apple ID and app bundle identifier, and you are ready to go. You can use that set of certificates for both development and production push notifications.

And to make things even better, you don’t actually need a push notification certificate for this anymore. It now supports JWT-based authentication tokens. I will try to explore this possibility in a future post. This post will focus on using certificates for your notifications still, but keep that in mind when you decide to implement your own push notifications system.

Another advantage is that the new system is based on HTTP/2. Most developers know how to work with the HTTP protocol instead of using pure raw sockets. This makes it very easy to write a push notification implementation and to test them easily (you can use cURL in your terminal for this).

Finally, one of the biggest advantages is that you no longer need to implement the feedback calls to get a list of devices that no longer exist. The new system gives you back standard HTTP codes. If you are sending a push notification to a device that is no longer valid, the service will return a 410 error, indicating that you can deal with that token in your database accordingly.

All the HTTP status codes return something meaningful to you. Other than 410, you can also receive 413 when your payload is too large, or 403 when there is something wrong with your certificate or authorization token. Thanks to this, debugging your own APNS systems is much easier to do, and this was not very easy to do with the old one.

A full list of status codes can be found Apple’s Developers Website, scrolling down to Table 8-4.

3. A Test Environment for Push Notifications

In order to take advantage of these new APIs in your development environment, you need to install cURL v7.38 or newer, and you need to specify the -with-nghttp2 flag in order to support HTTP/2.

You can do this easily on your Mac by installing Homebrew and typing:

brew install curl --with-nghttp2
brew link curl --force

While macOS does come with cURL installed, it comes with an old version that does not support HTTP/2.

Then you need your push notification certificate. Using Fastlane, you can just write


And follow the next prompts to generate your push notification certificate. The next two prompts will only ask you for your Apple ID and bundle identifier.

That’s it! With this we can send push notifications to your device.

Remember to ensure your deployment server also has a supported version of cURL in order to avoid issues. At the time of this writing, HTTP/2 is not widely used yet, so you may need to compile cURL with the -with-nghttp2 flag yourself.

#4. Playing Around with new Push Notificaitons

Once you have a push notification token received from your app, you can test this on your terminal.

We will use the token 34828574985 here (very pseudo, yeah) and the bundle identifier com.andyibanez.APNSFoobers for this example:

curl -d '{"aps":{"alert":"YOUR ALERT","sound":"default"}}' --cert "PATH_TO_YOUR_PUSH_CERTIFICATE.pem":"" -H "apns-topic: com.andyibanez.APNSFoobers" --http2 https://api.development.push.apple.com/3/device/34828574985

The push notification payload is the same one. It needs the "aps" key. Everything else you need to specify is your bundle ID, device token, and push notification certificate (PEM file).

The above example will send a development push notification. For production, simply change api.development.push.apple.com to api.push.apple.com and that’s it. You can use the same PEM file, and the only thing that could change is the token ID.

You can easily adapt this code to any language. I will try to write the PHP cURL based version of this in the future.

Positive SSL