Push Notification API

General

All data is transferred in JSON, and needs the content-type application/json. All data must be sent to the API in JSON.

Each application has an Application Key and both an Application Secret and an Application Master Secret (formerly known as the Application Push Secret). Credentials are supplied in HTTP Basic Auth (with the key as the username and the secret as the password), always over our HTTPS connection. The application secret is to be included on in the application to perform registration, and the master secret should only be used on a remote server and not included in the application.

You can find your credentials on your application’s detail page at https://go.urbanairship.com/ .

All URLs listed here are based at https://go.urbanairship.com/ (e.g., https://go.urbanairship.com/api/push/).

We also have a push notification test client which uses our push services.

Registration

An HTTP PUT to /api/device_tokens/<device_token> registers a device token on our end. This lets us know that the device token is active, and should happen every time the application is opened to ensure that the list of device tokens remains up-to-date. A successful registration returns HTTP 201 Created for first registrations and 200 OK for any updates.

Why use the registration call? We query Apple’s feedback service for you, marking any device tokens they tell us as inactive so that you don’t accidentally send anything to them any more. The registration call tells us that the device token is valid as of this time, so if a user turns push notifications back on for your application they can receive them successfully again.

Use the Application Key and Application Secret to authenticate these requests.

Device tokens should be represented as an uppercase string, 64 characters long, without spaces or other separators. An example device token is:

FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660

Optionally, include a JSON payload to specify an alias, tag, badge value, or quiet time setting for this device token:

{
    "alias": "your_user_id",
    "tags": [
        "tag1",
        "tag2"
    ],
    "badge": 2,
    "quiettime": {
        "start": "22:00",
        "end": "8:00"
    },
    "tz": "America/Los_Angeles"
}

If a JSON payload isn’t included, don’t set the Content-Type header, or the registration will fail.

Not including one of these keys removes it from the device token. In other words:

  • A PUT without an alias will remove any associated alias if the device token already exists.
  • A PUT with an empty tag list will remove any associated tags.
  • A PUT without a badge value will set the badge to 0.
  • A PUT without a quiet time (quiettime) and timezone (tz) will remove the quiet time setting.

Here’s an example using curl, a command line URL fetching tool:

curl -X PUT -u "<application key>:<application secret>" \
    -H "Content-Type: application/json" \
    --data '{"alias": "myalias"}' \
    https://go.urbanairship.com/api/device_tokens/<token>/

You can read a device token’s alias with an HTTP GET to /api/device_tokens/<device_token>, which returns application/json:

{
    "device_token": "some device token",
    "alias": "your_user_id",
    "last_registration": "2009-11-06 20:41:06",
    "tags": [
        "tag1",
        "tag2"
    ],
    "badge": 4
}

An HTTP DELETE to /api/device_tokens/<device_token> will mark the device token as inactive; no notifications will be delivered to it until a PUT is executed again. The DELETE returns HTTP 204 No Content, and needs no payload.

When a token is DELETEd in this manner, any alias or tags will be cleared.

If at any point you want to get a list of your device tokens from our database, you can - check out our Device Token List API.

Quiet Time

Often end users don’t want to receive push notifications at certain times, such as when they’re asleep. Urban Airship supports setting a “quiet time” via the device registration API during which time no push notifications for your app will be delivered to that device token. Push notifications containing a badge update will still be sent during quiet time, but the alert and sound will be removed.

Quiet times are specified using the following keys in the JSON sent to the device registration API:

  • quiettime: A JSON object containing:
    • start: When the quiet time begins as a string containing a time in 24 hour format. e.g., “20:30”
    • end: When the quiet time ends as a string containing a time in 24 hour format. e.g., “6:45”
  • tz: The end user’s timezone as a timezone name like “Europe/Berlin”. That way daylight saving time changes will be automatically taken into account.

You should specify these settings on every device registration and update the timezone according to the device’s location (in case the end user is traveling across timezones).

If the start time is greater than the end time (e.g., 20:30 and 6:30), then the quiet time is overnight. This is the most common case, but quiet times during the day (e.g., 9:00 and 17:00) work as well.

Push

An HTTP POST to /api/push/ performs a push notification to one or more users. The payload is in JSON with the content-type header set to application/json. The following structure shows all of the options – but all you need is one recipient and some data to send:

{
    "device_tokens": [
        "some device token",
        "another device token"
    ],
    "aliases": [
        "user1",
        "user2"
    ],
    "tags": [
        "tag1",
        "tag2"
    ],
    "schedule_for": [
        "2010-07-27 22:48:00",
        "2010-07-28 22:48:00"
    ],
    "exclude_tokens": [
        "device token you want to skip",
        "another device token you want to skip"
    ],
    "aps": {
         "badge": 10,
         "alert": "Hello from Urban Airship!",
         "sound": "cat.caf"
    }
}

The response is an HTTP 200 OK with no content, or an HTTP 400 Bad Request if the structure was invalid.

Here’s an example using curl, and sending “Hello” to one device token:

curl -X POST -u "<application key>:<master secret>" \
    -H "Content-Type: application/json" \
    --data '{"device_tokens": ["<token>"], "aps": {"alert": "Hello!"}}' \
    https://go.urbanairship.com/api/push/

This POST is authenticated with the Application Key and Master Secret (unless “Allow push from device” is checked in the administrative interface for the application - see Allow Push From Device).

A push notification can contain any combination of device_tokens, aliases, and/or tags, as long as there is at least one recipient. These recipient lists are additive. For example, if you send to:

{
    "tags": ["tag1", "tag2"],
    "device_tokens": ["FFFF..."]
}

then the notification will go to any device token tagged with tag1 or tag2, plus the device token FFFF....

aps is a dictionary which follows the same format as the notification payload required by the Apple Push Notification Service.

exclude_tokens (optional) is a list of tokens to not send to. This is useful for broadcasts and group delivery, e.g. when a user in group wants to send a notification to everyone in the group but themselves.

For more information on tags, see Tag API.

Sounds

By default, push notifications are silent, seen but not heard. To specify an alert sound to be played when the push notification is received, add a sound key to aps.

Example, playing the default sound:

{
    "aliases": "foo",
    "aps": {
        "alert": "Hello, I came with an alert sound!",
        "sound": "default"
    }
}

Unless you ship custom sounds with your app, only the default alert sound is available. Custom alert sounds should be included in your main application bundle; see Preparing Custom Alert Sounds for more.

Custom alert sounds cannot be longer than 30 seconds. If a sound exceeds this limit, the default sound will be played instead. Keep this limitation in mind when including rickroll Easter eggs in your app.

Autobadge

The badge is the number within a red circle that appears on an application’s home screen icon. Apple requires an integer be sent as the badge value in the APS payload. However, you can have Urban Airship keep track of what badge value the user should have. This provides the advantage of being able to use advanced badge values, which Urban Airship will translate into the proper badge for you. This is called an autobadge.

There are three types of autobadge that Urban Airship supports: auto, increment, and decrement. With a badge value of auto, we will take the current stored badge value and insert that. With +1 (an increment), we will take the badge value from the database, increment by the number after the + sign, and also increment our stored badge by that number. With -1, we decrement instead of increment. Note that you must include a number after + or - - a badge value of +1 will increment by one, but a value of just + will be passed on to Apple without any transformation.

The following example push payloads use an alias of “foo” and a current badge value of 4.

Auto example:

{
     "alias": "foo",
     "aps": {
         "badge": "auto",
         "alert": "My badge is now 4!"
    }
}

After this payload, the “foo” user still has a badge of 4 and the badge value sent on to Apple was also 4.

Increment example:

{
    "alias": "foo",
    "aps": {
        "badge": "+1",
        "alert": "My badge is now 5!"
    }
}

After this push, the “foo” user has a badge of 5, and the badge value sent on to Apple was 5.

Decrement example (starting with a badge value of 4):

{
    "alias": "foo",
    "aps": {
        "badge": "-1",
        "alert": "My badge is now 3!"
    }
}

After this push, the “foo” user has a badge of 3, and the badge value sent on to Apple was 3.

Autobadge has been implemented across the entire system, so you can use it everywhere.

Scheduled Notifications

schedule_for is always optional. If it’s included, we will delay sending the message until the time given. If schedule_for is not included the message will be delivered immediately. The time should be ISO 8601 format in UTC. If schedule_for is included, the response body will be application/json with the following structure:

{
    "scheduled_notifications": [
        "https://go.urbanairship.com/api/push/scheduled/XX",
        "https://go.urbanairship.com/api/push/scheduled/XY"
    ]
}

To cancel these scheduled notifications, use HTTP DELETE on that URL. A successful delete will have an HTTP status code of 204. If the scheduled notification does not exist, has already been successfully deleted, or was sent, the status code will be 404.

To bulk delete scheduled notifications, send an HTTP POST to https://go.urbanairship.com/api/push/scheduled/ with the following format:

{
    "cancel": [
        "https://go.urbanairship.com/api/push/scheduled/XX",
        "https://go.urbanairship.com/api/push/scheduled/XY"
    ],
    "cancel_aliases": [
        "some_alias",
        "another_alias"
    ],
    "cancel_device_tokens": [
        "example_device_token",
        "other_example_device_token"
    ]
}

If you include URLs or aliases for scheduled notifications that don’t exist or have already been sent, they will be ignored.

Any device token in the cancel_device_tokens payload will have every notification that is sent to it removed. This will not prevent it from receiving scheduled notifications to tags or broadcast messages.

You can also alias scheduled notifications. In your push payload, you can do the following:

{
    ...
    "schedule_for": [
        {"alias": "some_alias", "scheduled_time": "2010-07-16 11:22:00"},
        {"alias": "another_alias", "scheduled_time": "2010-08-12 08:05:00"}
    ]
}

If a scheduled notification is aliased, it can be removed or updated at a known URL: https://go.urbanairship.com/api/push/scheduled/alias/<your alias>

A PUT to an aliased URL will allow you to change the data, and a DELETE will delete it. If you attempt to schedule an aliased scheduled notification with an alias that already exists for your application, it will overwrite the existing one.

Example JSON to update an existing aliased scheduled notification:

{
    "alias": "some_alias",
    "schedule_for": "2010-06-05 22:15:00",
    "payload": {
        "device_tokens": ["some_device_token"],
        "aps": {
            "alert": "Hello from the past!",
            "sound": "cat.caf"
        }
    }
}

Aliases for scheduled notifications are unique per Urban Airship application, so you might want to hash the aliases with a device ID or use some other mechanism to ensure uniqueness. The only other limit is that they must be 255 characters or less.

Batch Push

For certain large operations that require unique messages to a variety of users it is inconvenient to send multiple requests. We have a batch API that takes care of that.

An HTTP POST to /api/push/batch/ sends the given notification to all listed device tokens. The payload is in JSON with content-type application/json, with this structure:

[
    {
        "device_tokens": [
            "some_device_token",
            "another_device_token"
        ],
        "aps": {
             "badge": 15,
             "alert": "Hello from Urban Airship!",
             "sound": "cat.caf"
        }
    },
    {
        "device_tokens": [
            "yet_another_device_token"
        ],
        "aliases": [
            "some_alias",
            "another_alias"
        ],
        "aps": {
            "badge": 12
        }
    }
]

The response is an HTTP 200 OK with no content, or an HTTP 400 Bad Request if the structure was invalid.

This POST is authenticated with the Application Key and Master Secret. Each item in the list can contain 0 or many device_tokens and 0 or many aliases, and the ‘aps’ payload is in the same format as Apple’s push notification system.

Broadcast

An HTTP POST to /api/push/broadcast/ sends the given notification to all registered device tokens for the application. The payload is in JSON with content-type application/json, with this structure:

{
    "aps": {
         "badge": 15,
         "alert": "Hello from Urban Airship!",
         "sound": "cat.caf"
    },
    "exclude_tokens": [
        "device token you want to skip",
        "another device token you want to skip"
    ]
}

The response is an HTTP 200 OK with no content, or an HTTP 400 Bad Request if the structure was invalid.

exclude_tokens (optional) is a list of tokens to not send to.

You can optionally include schedule_for to send a broadcast message at a future date:

{
    "schedule_for": "2010-07-27 22:48:29",
    "aps": {
        "alert": "Hi!"
    }
}

This POST is authenticated with the Application Key and Master Secret. The ‘aps’ payload is in the same format as Apple’s push notification system.

Feedback Service

Apple informs us when a push notification is sent to a device that can’t receive it because the application has been uninstalled. We mark the device token as inactive and immediately stop sending notifications through to avoid angering Apple.

To query what device tokens are now invalid, do an HTTP GET to /api/device_tokens/feedback/?since=<timestamp> with the master secret; the query argument since is required, and is a timestamp in ISO 8601 format, e.g. /api/device_tokens/feedback/?since=2009-06-01+13:00:00. The return value is application/json with the following structure:

[
   {
       "device_token": "1234123412341234123412341234123412341234123412341234123412341234",
       "marked_inactive_on": "2009-06-22 10:05:00",
       "alias": "bob"
   },
   {
       "device_token": "ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD",
       "marked_inactive_on": "2009-06-22 10:07:00",
       "alias": null
   }
]

Once a day is a good interval for querying the feedback service, but you can do it more often to save on bandwidth from unnecessary notifications if you’d like.

What does marked_inactive_on mean? Apple sends a timestamp for each device token returned via the feedback service. Since a device can be off the network for a while, this can be a point in the recent past. But in order to make this API work smoothly for you, we record the timestamp we marked it as inactive. This means you only need to query for data since the last time you queried. Once a day is a good timeframe, or once a week for very small or infrequently used applications. A few times a day is good for applications with heavy use.

Statistics

An HTTP GET to /api/push/stats/?start=<timestamp>&end=<timestamp> with the master secret returns hourly message counts for your application. By default, results are returned in JSON. For CSV, either add the header: Accept: text/csv or append &format=csv to the query string.

Times are in UTC, and data is provided for each push platform. (Currently: iOS, BlackBerry, Android, and C2DM, in that order.)

Here’s an example use with curl:

curl -u <application key> "https://go.urbanairship.com/api/push/stats/?start=2009-06-22&end=2009-06-22+06:00&format=csv"
Enter host password for user '<application key>':
2009-06-22 00:00:00,0,0,0,0
2009-06-22 01:00:00,0,0,4,0
2009-06-22 02:00:00,0,0,2,0
2009-06-22 03:00:00,0,0,1,0
2009-06-22 04:00:00,8,0,0,0
2009-06-22 05:00:00,1,0,0,0

The statistics system is updated every 15 minutes, so the final count for an hour will be done at the latest 15 minutes after the hour is done.

Device Token List API

You can easily get information about all of your device tokens from our device token list API.

An HTTP GET to /api/device_tokens/ authenticated with the master secret will return JSON data about your device tokens.

Example data:

{
    "device_tokens_count": 100,
    "device_tokens": [
        {
            "device_token": "1234123412341234123412341234123412341234123412341234123412341234",
            "active": true,
            "alias": null,
            "last_registration": "2009-06-26 19:04:43"
        },
        ...
    ],
    "current_page": 1,
    "num_pages": 1,
    "active_device_tokens_count": 98
}

If your application has a large number of device tokens, we’ll paginate the request for you. By default, we paginate at 5000 device tokens.

Here’s an example response for an app with many thousands of device tokens:

{
    "next_page": "https://go.urbanairship.com/api/device_tokens/?page=2&limit=5000"
    "num_pages": 60,
    "active_device_tokens_count": 300000,
    "current_page": 1,
    "device_tokens": [
        ...
    ],
    "device_tokens_count": 300100,
}

You can receive the next page simply by retrieving the URL from next_page - in this way it is easy to export all of your device tokens and all their data.

If all you’re interested in is the number of device tokens you have registered, you can perform an HTTP GET to /api/device_tokens/count/, again authenticated with the master secret.

Example response:

{
    "device_tokens_count": 300100,
    "active_device_tokens_count": 300000
}