Open Channels

Introduction

Open Channels support notifications to any medium that can accept a JSON payload, through either the Urban Airship API or dashboard UI.

Unlike natively supported channels such as iOS, Android and web, Open Channels are not backed by an Urban Airship SDK. In the absence of an SDK, it's up to you, the developer, to A) register end users with our Open Channels API and B) determine how to parse and display the notification payloads in the available interface.

Leverage the features of our Engage platform, such as segmentation, scheduling, and local time delivery, while sending notifications to any messaging channels you choose. You can send to natively supported channels, e.g., Android or iOS, and open messaging channels in combination or in isolation, using our familiar device_types selector and platform-specific payloads.

Open Channels is an extension of the Channels API. See the Intro to Channels for more information.

Use Cases

The simplest use case for a notification is the one we are all familiar with: displaying the text of an alert. But there are many other uses for a notification payload, which, depending on the target interface or OS, may be handled in different ways. For example, our SDKs for iOS and Android support the interactive features of those operating systems through our API. Our API also supports an extra field, which lets you to pass any key/value pair to handle how you see fit, e.g., update a config file or trigger a different process.

An open channel can be any non-native platform or interface where you'd like to reach users, or for that matter any client capable of receiving a payload over the Internet. The end message doesn't need to be human-readable alert text as you might see on an iPhone. Alerts are usually intended for people, but in the case of a machine, you could tell it to update its firmware, increment a counter in a database, or perform some other action.

Open channel example use cases

  • Automated Slack Message using Slack incoming webhooks
  • Chatbot notifications
  • Firmware updates for IOT devices
  • Integrate with third-party messaging APIs, e.g, Twitter

Integration Points

There are three integration points required to set up a new Open Channel:

  1. Webhook Server
    Accepts the Urban Airship Open Channels payload, translates and routes your request.

  2. Channel Registration API
    Because Open Channels aren't supported by a client SDK, you must register new open channels in the Urban Airship system directly.

  3. Push API
    Deliver message payloads using our Engage API, specifying open channels in your request.

API Resources

Open Delivery Payload

Webhook POST Request Body

Here is an example request body with two objects, each containing all possible keys:

POST /hooks/ua/example_hook/push HTTP/1.1
Content-encoding: gzip
Data-Attribute: values
Content-Type: application/vnd.urbanairship+json; version=3;

{
   "values": [
      {
         "send_id": "ff76bb85-74bc-4511-a3bf-11b6117784db",
         "app_key": "ZGIwZTY3YjEtZTRiMi00ZG",
         "target": {
            "address": "221B Baker Street",
            "channel_id": "a61448e1-be63-43ee-84eb-19446ba743f0",
            "identifiers": {
               "cid": "1234567",
               "com.example.test_token": "a61448e1-be63-43ee-84eb-19446ba743f0"
            }
         },
         "payload": {
            "alert": "Giant StayPuft Marshmallow Man On a Rampage",
            "title": "Breaking News!",
            "extra": {
               "url": "https://www.example.com/"
            }
         }
      },
      {
         "send_id": "647e799e-3b15-46f0-b4f1-12360d51ce4a",
         "app_key": "ZGIwZTY3YjEtZTRiMi00ZG",
         "target": {
            "address": "1600 Pennsylvania Avenue",
            "channel_id": "5b7e9f63-df28-43f4-8182-b762c628c4c4",
            "identifiers": {
               "cid": "7654321",
               "com.example.test_token": "503640e8-88f7-4dee-9245-7479ac1a8501"
            }
         },
         "payload": {
            "alert": "Giant StayPuft Marshmallow Man On a Rampage",
            "title": "Breaking News!",
            "extra": {
               "url": "https://www.example.com/"
            }
         }
      }
   ]
}

Here is an example request body with one object, containing only the required keys:

POST /hooks/ua/example_hook/push HTTP/1.1
Content-encoding: gzip
Data-Attribute: values
Content-Type: application/vnd.urbanairship+json; version=3;

{
   "values": [
      {
          "send_id": "ff76bb85-74bc-4511-a3bf-11b6117784db",
          "app_key": "ZGIwZTY3YjEtZTRiMi00ZG",
          "target": {
              "address": "test@example.com",
              "channel_id": "a61448e1-be63-43ee-84eb-19446ba743f0",
          },
          "payload": {
              "alert":"Giant StayPuft Marshmallow Man On a Rampage",
          }
      }
  ]
}

The request body itself is a JSON object containing a single top level key, "values", pointing to an array of up to 1,000 JSON objects. Urban Airship will break up large pushes into groups of 1000.

Each object in the array is required to have the following keys:

  • "send_id"—UUID version 4 string. Uniquely identifies the object.
  • "app_key"—22 character string containing the characters: [-_A-Za-z0-9].
  • "payload"—push payload with all "open" overrides for the delivery type applied.
  • "target"—A target object containing the address and a string->string map of alternative identifiers.

Target Object

{
   "identifiers": {
      "com.urbanairship.aaid": "94b0c28e-0f00-4601-af28-e70322f46a75",
      "friend": "ship",
      "ice": "cream",
      "session_id": "5abe6b52-7dcf-4fec-b0a5-d24cb4deaafe",
      "com.urbanairship.limited_ad_tracking_enabled": "false"
   },
   "channel_id": "1e215090-e692-4d89-ab7f-1f2ace2a229b",
   "address": "+1 5558675309"
}

Information pertaining to the target related to a webhook payload is defined under the "target" key in each response item.

Target objects are required to have both of following keys:

  • "channel_id"—string, the channel identifier for the target.
  • "address"— string, the customer-provided delivery address for the target.

Target objects may have the following keys:

  • "identifiers"—A JSON object with identifiers specified by the app. Common uses are IDFA or the primary key in your CMS. The values of the keys and values in this object are up to you, however Urban Airship may make additional functionality available using keys prefixed with "com.urbanairship." so keys using that prefix should be avoided.

Payload Object

The payload to deliver to the target.

  • "alert"—required, string. The primary message to deliver to the target.
  • "title"—optional, string. The title of the payload. A good example use case would be an email header for an open email notification.
  • "extra"—optional, a string-to-string map of additional values to deliver to the target. Can contain any additional information that users want to deliver to the target.

Getting Started

These are the steps to setting up your open channels integration:

  1. Set up your webhook server.
  2. Configure your new webhook in the Urban Airship dashboard.
  3. Register a channel to your Open Platform.
  4. Send a push.

Set Up Your Webhook Server

Important

You need to do this first because the Open Channel configuration in the next step requires your webhook URL.

The webhook server must:

  1. Accept HTTPS connections. Accepted Cipher Suites:

    • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384

  2. When receiving an authorized GET request to <webhook_root>/validate:

    • Return a 200 response code.
    • Return a Content-Type of "application/json".
    • Return a JSON body with the form: {"confirmation_code":"559384cd-6284-4e3e-9e4e-7c260019a251"}.

  3. When receiving an authorized POST request to <webhook_root>/push:

    • Return a 200 response code.

The webhook server should:

Sample Payload:

{
   "values": [
      {
         "send_id": "ff76bb85-74bc-4511-a3bf-11b6117784db",
         "app_key": "ZGIwZTY3YjEtZTRiMi00ZG",
         "target": {
            "address": "SOME_INTERNAL_ID",
            "channel_id": "a61448e1-be63-43ee-84eb-19446ba743f0",
            "identifiers": {
               "cid": "1234567",
               "com.example.token": "a61448e1-be63-43ee-84eb-19446ba743f0"
            }
         },
         "payload": {
            "alert": "Giant StayPuft Marshmallow Man On a Rampage",
            "title": "Breaking News!",
            "extra": {
               "url": "https://www.example.com/"
            }
         }
      },
      {
         "send_id": "647e799e-3b15-46f0-b4f1-12360d51ce4a",
         "app_key": "ZGIwZTY3YjEtZTRiMi00ZG",
         "target": {
            "address": "SOME_OTHER_INTERNAL_ID",
            "channel_id": "5b7e9f63-df28-43f4-8182-b762c628c4c4",
            "identifiers": {
               "cid": "7654321",
               "com.example.token": "503640e8-88f7-4dee-9245-7479ac1a8501"
            }
         },
         "payload": {
            "alert": "Giant StayPuft Marshmallow Man On a Rampage",
            "title": "Breaking News!",
            "extra": {
               "url": "https://www.example.com/"
            }
         }
      }
   ]
}
  1. Expect to process payloads in the format of the samples to the right.

  2. Point to an array of Send Objects with the top level "values" key.

    Send Object

"send_id"
Required, UUID uniquely identifying the send. Can be used for de-duplication in the event of a retry, logging, or tracing.
"app_key"
Required, the 22-character identifier of the Urban Airship project associated with the open channel.
"target"

required, a Target Object with the following attributes:

  • “address” Required, string. The address of the open channel.
  • “channel_id” Required, the Urban Airship Channel ID of the Open Channel.
  • “identifiers” Optional, an Object with up to 100 string:string identifiers associated with the Open Channel.
"payload"

Required, a Payload Object with the following attributes:

  • “alert” Required, string. The alert message for the notification.
  • “title” Optional, string. Optional title, useful for email subject lines or headers.
  • “extra” Optional, an object of user-supplied string:string key:value pairs associated with the push.

Signature Hash and Security

Request headers with secret key

POST /hooks/ua/sendgrid_hook/push HTTP/1.1
Content-Type: application/vnd.urbanairship+json; version=3;
Content-encoding: gzip
X-UA-TIMESTAMP: 1536947409
X-UA-SIGNATURE: 68688b9dbd5c381851d3cd51dba3093c6633ceef58e6fee6ad4757f857f59aea
Data-Attribute: values

Rather than basic authentication, you can configure open channels to include a signature that your webhook server can use to verify that requests come from Urban Airship.

To enable this signature, select Signature Hash authorization and set a secret_key when configuring your open channel in the Urban Airship dashboard. See the Configure Open Channels page for help configuring an open channel and enabling Signature Hash authentication in the dashboard.

When you enable and set a secret_key, outgoing requests include a hash-based message authentication code, computed using the sha256 hash function in an X- UA-SIGNATURE header. You can use this same algorithm to verify the signature on the receiving server.

X-UA-SIGNATURE is composed of the secret_key and a message, both of which must be UTF-8 encoded. The message is a concatenation of the following string values:

  • The X-UA-TIMESTAMP header — the unix timestamp when the request was sent.
  • The : character.
  • The JSON request body.

To prevent replay attacks, you should validate the X-UA-TIMESTAMP within a threshold of the current time. It is recommended that you use a 5-minute threshold to account for time drift, though Urban Airship uses NTP and it is recommended that your webhook servers do the same.

To prevent timing attacks, you should employ a constant time-compare function when checking signatures.

Urban Airship Setup

Begin by configuring your new webhook in the dashboard. Complete the steps in Configure Open Channels.

When you complete the steps, you will receive a validation code that must be returned by the webhook server at <webhook_root>/validate. See: Set Up Your Webhook Server.

Important

When completing the configuration steps above, be sure to check the "Check to enable this for API use" box for your new open platform. If it is not enabled for the platform, you will be able to register a new open channel with the corresponding platform type but you will not be able to send a push to that platform using our API.

Register a Channel to Your Open Platform

Sample Payload:

{
   "channel": {
      "type": "open",
      "opt_in": true,
      "address": "Number Four",
      "tags": [
         "toaster",
         "caprica"
      ],
      "timezone": "America/Los_Angeles",
      "locale_country": "US",
      "locale_language": "en",
      "open": {
         "open_platform_name": "cylon",
         "identifiers": {
            "model": "4"
         }
      }
   }
}

Next, you’ll need to populate your audience in our system.

This registration step is handled automatically in our mobile and web SDKs, but you are responsible for populating the Urban Airship system with users on open platforms.

To register a channel, send request to the Open Channel Registration API> The request body must contain an the following keys:

"type"
Required, string. Currently the only only valid value for type is "open".
"opt_in"
Required, boolean. A flag to determine if the owner of this device still wants to receive notifications. If false, no open channels payloads will be delivered to the webhook for this channel.
"address"
Required, string. The primary identifier of a record. For example, in an SMS integration, it could be the end user's phone number. 128 character maximum.
"tags"
Optional, array of strings. Can be used for audience segmentation.
"timezone"
Optional, string. An IANA tzdata identifier for the timezone as a string, e.g., "America/Los Angeles". Will set the timezone tag group tag with the specified value.
“locale_country”
Optional, string. The two-letter country locale shortcode. Will set the ua_locale_country tag group to the specified value.
“locale_language”
Optional, string. Tthe two-letter language locale shortcode. Will set the ua_locale_language tag group to the specified value.
"open"

Required, object. Open Platform Options Object. Contains the following keys:

  • "open_platform_name": Required, string. The name of the open platform to which you are registering this channel.
  • "identifiers" - Optional map of string values. These will be delivered in open channels payloads, but cannot be used for segmentation. Maximum of 100 pairs of string values. This map should be exhaustive whenever this key is present. Values will not be unioned with existing identifiers; they will replace them.

Push To Your New Channel

Example Request:

{
   "notification": {
      "alert": "Pop!"
   },
   "audience": {
      "open_channel": "32c99a88-0df1-4eed-9ac3-abc8ee5314ed"
   },
   "device_types": [
      "open::toaster"
   ]
}

To push to your channel, simply push like you would to any other channel, using the open_channel identifier as your audience selector. See Audience Selection for more detail.

The key difference in an Open Channels API push is the namespacing of the device_types identifier for your configured platform. Prepend the new device_types identifier with open::, e.g., for your new toaster's channel, use "open::toaster".

Associate a Named User

Associate Channel ID with Named User:

POST /api/named_users/associate HTTP/1.1
Authorization: Basic <application or master authorization string>
Accept: application/vnd.urbanairship+json; version=3;
Content-type: application/json

{
   "channel_id": "5b7e9f63-df28-43f4-8182-b762c628c4c4",
   "named_user_id": "igorstravinsky"
}

You can also associate your channel with a named user using the Association endpoint, and then use that for targeting.

Fan out

Fan out a message to all devices associated with the named user:

{
   "notification": {
      "alert": "Pop!"
   },
   "audience": {
      "named_user": "igorstravinsky"
   },
   "device_types": [
      "ios",
      "android",
      "open::toaster"
   ]
}

Now that you have registered your channel, and mapped a named user to it, you need only target the named user and enumerate the configured device_types on which you would like to reach your named user. The named user mapping will fan out to all devices on supported platforms for the given named user.

View Send Counts

Example Push Response. Use the push_id in your request

{
    "ok": true,
    "operation_id": "6b5e94f5-9c85-486a-a76e-67d18b3eaf05",
    "push_ids": [
        "362b7e8d-af82-4a67-ac76-49e5ea2f7f59"
    ],
    "message_ids": [],
    "content_urls": []
}

Response API request, using push_id from previous example:

GET /api/reports/responses/362b7e8d-af82-4a67-ac76-49e5ea2f7f59 HTTP/1.1
Authorization: Basic <master authorization string>

Example response returns the open_channels_sends, broken out by open platform

{
    "push_uuid": "362b7e8d-af82-4a67-ac76-49e5ea2f7f59",
    "push_time": "2017-08-08 16:41:59",
    "push_type": "SEGMENTS_PUSH",
    "direct_responses": 0,
    "sends": 0,
    "open_channels_sends": {
        "platforms": [
            {
                "id": "sms",
                "sends": 1
            },
            {
                "id": "toaster",
                "sends": 1
            }
        ]
    }
}

After you've sent a push notification to your open channel, use the Push Response Report endpoint to retrieve send counts broken out by open platform.