Handling push notifications (Webhook API)

This feature is only available on the Team, Professional, and Enterprise plans.

You can use push notifications with the Support SDK using the Webhook API.

The Zendesk Support SDK can be set up to notify the end user when an agent posts a public comment on their request.

Before you start

Before you start, the following information is useful to know:

  • You can use either the Webhook API or Urban Airship to send push notifications.
  • If you already have a push notifications service we recommend you use the Webhook API option. On the other side, if you don't have your own push notifications service or you are not willing to develop one, you should use the Urban Airship alternative.
  • You will only receive notifications on requests that were created through the Support SDK.
  • The configuration of your app in Zendesk Support must include the push notification details for your chosen option.
  • If you switch from one integration to another, register the devices again. Otherwise the push notifications will not be delivered properly.

Use the Webhook API for push notifications

Zendesk Support notifies an endpoint that you set up when a notification needs to be sent. After that, your service must handle sending the push notification for the end user's device.

You must set up a push notification service and then register an end user's interest in receiving push notifications on the app side.

When Zendesk Support sends a notification to the end user, it sends a POST request to the URI set in the app configuration.

For a full webhook integration, you need to do three things:

  1. Configure your Support SDK App in your account
  2. Set up your backend to handle our callback API
  3. Set up your app to handle the push notification and ticket deep-linking
Account Configuration

In the Zendesk Support admin interface, select the "Webhook" option in the push notifications combo box in the Customization tab on the Mobile SDK page.

You'll be prompted to provide the Webhook URI.

Push Notifications Webhook Configuration

Server Integration
Webhook API

As explained above, Zendesk Support sends an HTTP POST request to the URI of your service. The payload looks like this:

POST <your_push_notification_callback_uri>
Content-Type: application/json
Accept: application/json

{
  "devices": [
    {
      "identifier": "oiuytrdsdfghjk",
      "type": "ios"
    },
    {
      "identifier": "iuytfrdcvbnmkl",
      "type": "android"
    }
  ],
  "notification": {
    "body": "Agent replied something something",
    "title": "Agent replied",
    "ticket_id": "5"
  }
}

The request body is a JSON object containing the following parameters:

Name Type Comment
devices array List of devices
notification object The details for the notification
devices

Parse the devices array to get the devices that need to receive a push notification.

Name Type Comment
identifier string The device identifier/token that was registered through the Support SDK
type string The device type. Possible values: "ios" or "android"
notification

Use the notification object to pass along the title or body of the message, or you can customize it yourself. If you want the client app to handle deep-linking, pass the ticket_id value in the push payload.

Name Type Comment
title string The short message of the notification
body string The long message of the notification
ticket_id string The identifier of the ticket that was updated. Pass this along as zendesk_sdk_request_id if you want ticket deep-linking in the app

Note: As a best practice, provide a callback URL that's not guessable and make sure you can easily change it.

Device Delete

Apple Push Notification Service (APNS) will let you know if a user unregistered from push notifications. You need to let us know.

You can use the Push Notification Devices Bulk Unregister API to delete the devices of customers who deleted the app or are no longer registered.

Application Integration

You need to handle the following four scenarios in the app code:

You must also enable Background fetch and Remote notifications in the Background Modes section of your apps Capabilities in your project configuration.

Push Notifications Setup Background Modes

Device registration

First, you need to ask the user for permission, as per the iOS docs.

Swift

if #available (iOS 8.0, *) {
  let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound],
                                            categories: nil)
  application.registerUserNotificationSettings(settings)
  application.registerForRemoteNotifications()
} else {
  application.registerForRemoteNotifications(matching:[.alert, .badge, .sound])
}

Objective-C

// Register the app for remote notifications in application:didFinishLaunchingWithOptions:
if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) {

    UIUserNotificationType types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;

    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotifications];

} else if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotificationTypes:)]) {

    UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;

    [application registerForRemoteNotificationTypes:types];
}

This should result in a call to the app delegates didRegisterForRemoteNotificationsWithDeviceToken method. The device token returned by this method is what you'll pass as the identifier parameter to the following Support SDK method:

Swift

NSLocale.preferredLanguages.first ?? "en"
ZDKPushProvider(zendesk: Zendesk.instance).register(deviceIdentifier: identifier, locale: locale) { (pushResponse, error) in
    print("Couldn't register device: \(identifier). Error: \(error)")
  } else {
    print("Successfully registered device: \(identifier)")
  }
}

Objective-C

...
NSString * locale = [[NSLocale preferredLanguages] firstObject];
[[[ZDKPushProvider alloc] initWithZendesk:[ZDKZendesk instance]] registerWithDeviceIdentifier:identifier locale:locale completion:^(NSString * _Nullable registrationResponse, NSError * _Nullable error) {
  if (error) {
    NSLog(@"Couldn't register device: %@. Error: %@ in %@", identifier, error, self.class);
  } else if (registrationResponse) {
    NSLog(@"Successfully registered device: %@ in %@", identifier, self.class);
  }
}];
...

Note: Certain characters should be stripped from the deviceIdentifier before registering for push notifications with Zendesk. Spaces and occurances of < and > should be removed.

To register for push notifications with Zendesk Support, a valid identity must be set in the Support SDK. Depending on how your app is configured, you probably won't have an identity ready in the AppDelegate. We suggest you store the device identifier returned by Apple and register for push notifications with Zendesk Support once an identity becomes available, such as when the user signs into your app.

Device unregistration

When the user signs out or doesn't want push notifications anymore, call the following API to remove the device identifier from Zendesk Support:

Swift

ZDKPushProvider(zendesk: Zendesk.instance!).unregisterForPush()

Objective-C

[[[ZDKPushProvider alloc] initWithZendesk:[ZDKZendesk instance]] unregisterForPush];
Notification payload handling

Set up the delegate methods to handle the payload received as described in the iOS Notification Programming Guide on the Apple site.

When a notification is received you can handle it using the Support-SDK's deep-linking feature or handle it yourself. If you choose to handle it yourself you can retrieve the ticket and fetch its comments using an API provider.

Ticket deep-linking

You can use the Support SDK's deep linking functionality to show the ticket directly in response to a notification tap.

Presenting the Request UI

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler:
               @escaping () -> Void) {
  let requestID = response.notification.request.content.userInfo["tid"]
}

//Inside a UIViewController
func presentRequest(with requestID: String) {
  let viewController = RequestUi.buildRequestUi(requestId: requestID)
  self.navigationController?.pushViewController(viewController, animated: true)
}

Objective-C

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler  {
    NSString * requestID = [[[[response notification] request] content] userInfo[@"tid"]];
}

//Inside a UIViewController
-(void) presentRequest:(NSString *)requestID {
    UIViewController * requestController = [ZDKRequestUi buildRequestUiWithRequestId:requestID];
    [self.navigationController pushViewController:requestController animated:YES];
}
Refresh comment stream

You can refresh the comment stream if it is visible. refreshRequest returns a boolean that indicates if the refresh was successful, e.g. the user had the ticket open at the time. If it returns false you will need to handle the notification yourself.

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler:
               @escaping () -> Void) {
  let requestID = response.notification.request.content.userInfo["tid"]
  if SupportUI.instance?.refreshRequest(requestId: requestID) {
    return
  } else {
    //Handle the notification
  }
}

Objective-C

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    NSString * requestID = [[[[response notification] request] content] userInfo[@"tid"]];
    if ([[ZDKSupportUI instance] refreshRequestWithRequestId:requestID]) {
        return;
    } else {
        // Handle push
    }
}

If you're only using the API providers and building the UI yourself:

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter,
            didReceive response: UNNotificationResponse,
            withCompletionHandler completionHandler:
               @escaping () -> Void) {
  let requestID = response.notification.request.content.userInfo["tid"]
  if Support.instance?.refreshRequest(requestId: requestID) {
    return
  } else {
    //Handle the notification
  }
}

Objective-C

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler {
    NSString * requestID = [[[[response notification] request] content] userInfo[@"tid"]];
    if ([[ZDKSupport instance] refreshRequestWithRequestId:requestID]) {
        return;
    } else {
        // Handle push
    }

}

Make sure your service is sending the zendesk_sdk_request_id parameter to the application in the extra section of the message you send to APNS. It should look something like this:

{
    aps = {
        ...
        alert = "There has been a reply to your message.";
        ...
    };
    ...
    "zendesk_sdk_request_id" = <the-request-id>;
    ...
}