notifly
Free toolApple Push Notification serviceUpdated

APNs payload builder and validator

Fill in the form to get a valid Apple Push Notification service payload, the request headers that go with it and a curl command you can run against the sandbox. Or paste a payload you already have and the validator checks it against Apple's documented aps keys, value types, push types and size limits.

A payload is a JSON dictionary with an aps dictionary for Apple's keys (alert, badge, sound, ...) and your own keys next to it, never inside it: APNs ignores custom keys in aps. The whole body must stay within 4096 bytes, or 5120 bytes for VoIP.

Valid177 / 4096 bytes0 errors, 0 warnings
payload.json
{
  "aps": {
    "alert": {
      "title": "Your order shipped",
      "body": "Order #1042 is on its way and should arrive Thursday."
    },
    "badge": 1,
    "sound": "default",
    "thread-id": "orders"
  },
  "orderId": "1042"
}
headers
apns-push-type: alert
apns-priority: 10
apns-topic: com.example.app
curl (sandbox)
curl -v --http2 \
  --header 'apns-push-type: alert' \
  --header 'apns-priority: 10' \
  --header 'apns-topic: com.example.app' \
  --header "authorization: bearer $AUTHENTICATION_TOKEN" \
  --data '{"aps":{"alert":{"title":"Your order shipped","body":"Order #1042 is on its way and should arrive Thursday."},"badge":1,"sound":"default","thread-id":"orders"},"orderId":"1042"}' \
  https://api.sandbox.push.apple.com/3/device/$DEVICE_TOKEN

How to use it

  1. Choose the push type. Alert for a visible notification, background for a silent content-available update.
  2. Fill in the content. Title, subtitle, body, badge, sound, thread and any custom keys your app reads.
  3. Read the findings. Errors are things APNs or the device will refuse or ignore; warnings are documented recommendations.
  4. Send it. Copy the curl request, set AUTHENTICATION_TOKEN to your provider JWT and DEVICE_TOKEN to a test device, and run it.

Limits this tool checks

Use it from code, no key

POST /api/tools/validate-apns takes the same input and answers the report as JSON, or as Markdown with Accept: text/markdown. No account or key; 30 requests a minute and 300 a day per address; errors are RFC 9457 problem details. The OpenAPI description covers every free tool API.

curl
curl -s https://notifly.io/api/tools/validate-apns \
  -H "Content-Type: application/json" \
  -d '{"payload":{"aps":{"alert":{"title":"Hi","body":"Your order shipped"},"badge":1}},"headers":{"apns-push-type":"alert","apns-priority":"10"}}'

Frequently asked questions

What is the maximum APNs payload size?

4096 bytes for every push type except VoIP, which allows 5120 bytes. APNs refuses a larger payload. The limit counts the whole JSON body, your custom keys included, as UTF-8 bytes.

How do I send a silent background push?

Set content-available to 1 in aps and leave out alert, badge and sound. Send the apns-push-type header as background and apns-priority as 5: Apple documents priority 10 as an error for background pushes.

Where do custom keys go in an APNs payload?

Next to the aps dictionary, at the top level of the payload. APNs ignores custom keys placed inside aps. Values can be strings, numbers, booleans, arrays or dictionaries.

Which apns-topic do I use?

Your app's bundle ID for alert and background pushes. Other push types append a suffix: .voip for VoIP, .complication for watch complications, .push-type.liveactivity for Live Activities, .pushkit.fileprovider for File Provider, .location-query for location pushes, .voip-ptt for push to talk, .push-type.widgets for widgets and .push-type.controls for controls.

Can I call the validator from my own code?

Yes. POST the payload and headers to https://notifly.io/api/tools/validate-apns. It needs no key and returns the same report as JSON, or Markdown when you send Accept: text/markdown. It allows 30 requests a minute and 300 a day per address.

Sending these for real? Notifly sends push, email, SMS, in-app and chat from one workflow and one API call. Start free.