In this tutorial series, you'll build a Zendesk integration for Slack. The integration listens for Ticket Created events in Zendesk. When it detects an event with a specific ticket priority, the integration posts a related message to a provided Slack channel.

As part of the series, you'll also build a Zendesk app. The app's user interface (UI) lets admins connect the integration to their Zendesk and Slack instances. The app also lets admins configure settings for the integration. The app uses Zendesk Integration Services (ZIS) APIs to manage the connections and configurations.

This tutorial covers the first steps for setting up the integration and the Zendesk app. Other tutorials in the series teach you how to finish building the app and install the integration:

Disclaimer: Zendesk provides this article for instructional purposes only. The integration and examples are not meant for production environments. Zendesk does not provide support for this integration or app. Post any issue in the Zendesk developer community or search for a solution online.

What you'll need

To complete this tutorial, you’ll need the following:

Register the integration

First, register the integration's name using the Create Integration endpoint.

Integration names must be globally unique. For this tutorial, use an integration name of {subdomain}_zendesk_to_slack. Replace {subdomain} with your Zendesk subdomain.

  1. In your command-line interface, run:

    curl -X POST https://{subdomain}.zendesk.com/api/services/zis/registry/{subdomain}_zendesk_to_slack \  -u {email_address}:{password} \  -H "Content-type: application/json" \  -d '{"description": "An example integration"}'

    The integration uses an OAuth access token to make Zendesk API requests on the admin's behalf. To get this token, your Zendesk app uses ZIS APIs to start an OAuth flow. To start an OAuth flow, ZIS first requires an OAuth client. The client contains details used to pass data between ZIS and the other system during the OAuth flow.

    When you register an integration, the request automatically creates an OAuth client for Zendesk. The client is named "zendesk." The response contains information about your integration and its OAuth client. For example:

    {  "description": "An example integration",  "jwt_public_key": "***RSA Public Key to save***",  "zendesk_oauth_client": {    "id": 00001,    "identifier": "zis_{subdomain}_zendesk_to_slack",    "secret": "***secret***"  }}
  2. Save the response securely. You’ll use these details later in this tutorial.

Create a Zendesk app

Next, use ZCLI to create starter files for a Zendesk app named Zendesk to Slack Notifier.

  1. In your command-line interface, navigate to the folder you'll use to store the app. For example:

    cd projects
  2. In the folder, run the following ZCLI command:

    zcli apps:new
  3. At the prompts, enter the following values:

    • Directory name: zendesk_to_slack_app
    • Author's name: Your name
    • Author's email: Your email address
    • App name: Zendesk to Slack Notifier

    ZCLI creates app starter files in the zendesk_to_slack_app folder.

Set app location

Update your app to run in the nav bar of the Zendesk Support UI. This location lets admins access the app from any Support page.

  1. In the zendesk_to_slack_app folder, open manifest.json in your text editor.

  2. Replace the location property with the following:

    "location": {  "support": {    "nav_bar": "assets/iframe.html"  }},
  3. Save manifest.json.

Test the app

Your app doesn't do much yet, but you can already use ZCLI to run it. Run your app often to test changes.

  1. In your command-line interface, navigate to the zendesk_to_slack_app folder. For example:

    cd projects/zendesk_to_slack_app
  2. Start a ZCLI local web server by running the following command:

    zcli apps:server

    After a moment, a status message appears informing you that the server has started.

    Note: To stop the server, press Ctrl+C.

  3. In your browser's private or incognito window, sign in to Zendesk Support and go to the Agent Dashboard. The URL should look like this:

    https://{subdomain}.zendesk.com/agent/dashboard

  4. Append ?zcli_apps=true to the URL and press Enter. The URL should now look like this:

    https://{subdomain}.zendesk.com/agent/dashboard?zcli_apps=true

    An app icon is displayed in the left nav bar.

  5. Click the icon to launch the app.

    The app displays a "Hello, World!" heading.

Connect to Zendesk

The app's UI should include a Connect to Zendesk button. When an admin clicks the button, the app uses ZIS APIs to start an OAuth flow with Zendesk. When done, the OAuth flow sends a Zendesk access token to ZIS for storage.

Add a "Connect to Zendesk" button

  1. In the app's assets folder, open iframe.html. Replace the file's contents with the following:

    <html>  <head>    <meta name="viewport" content="width=device-width, initial-scale=1" />    <!-- Loads Zendesk Garden CSS components -->    <link      href="https://cdn.jsdelivr.net/combine/npm/@zendeskgarden/css-bedrock,npm/@zendeskgarden/css-grid,npm/@zendeskgarden/css-buttons,npm/@zendeskgarden/css-forms,npm/@zendeskgarden/css-utilities"      rel="stylesheet"    />  </head>  <body>    <div class="u-m u-fg-grey-800">      <div class="u-mb">        <div class="row">          <div class="col-6">            <div class="c-txt u-mb">              <button id="btnConnect" class="c-btn c-btn--primary">                Connect to Zendesk              </button>            </div>          </div>        </div>      </div>    </div>    <script      type="text/javascript"      src="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js"    ></script>
        <!-- Bootstrap the app -->    <script type="text/javascript" src="bootstrap.js"></script>
        <!-- Establish connections -->    <script type="text/javascript" src="connect.js"></script>  </body></html>

    The HTML includes the following:

    • A stylesheet for the app's UI. This app uses Garden, Zendesk's design system. For simplicity, the app uses Zendesk Garden's CSS components. For a real-world app, we recommend using Garden's React components.

    • Markup for the Connect to Zendesk button.

    • A <script> tag that imports the ZAF SDK library.

    • <script> tags that load bootstrap.js and connect.js. You'll create these files in the next steps.

  2. In the assets folder, create a bootstrap.js file. Paste the following into the file:

    // Bootstrap the app when the DOM is ready(function () {  // Initialize the Zendesk JavaScript API client  // https://developer.zendesk.com/apps/docs/developer-guide/getting_started  window.client = ZAFClient.init();
      // OAuth flow kick-off requires a subdomain  let subdomain = undefined;
      // Integration name is the unique identifier for your integration app  let integrationName = undefined;
      client    .context()    .then(function (context) {      // Derive subdomain & integration name      subdomain = context["account"]["subdomain"];      integrationName = subdomain + "_zendesk_to_slack";    })    .then(function () {      // Bind button to start a Zendesk OAuth flow      document        .getElementById("btnConnect")        .addEventListener("click", function () {          startOAuth(integrationName, subdomain);        });    });})();

    The code contains an anonymous, self-invoking function. This function runs when the app loads. The top part of the function initializes a ZAF client. The ZAF client lets your app use the current browser session to authenticate Zendesk API requests.

    The second part of the function binds the Connect to Zendesk button to the startOAuth function. When an admin clicks the button, the code calls the function. You'll define the function in the next step.

  3. In the assets folder, create a connect.js file. Paste the following into the file:

    // Starts a Zendesk OAuth flowfunction startOAuth(integrationName, subdomain) {  // Human-readable name for the Zendesk OAuth client  // ZIS creates this client when you register an integration  const zendeskOAuthClientName = "zendesk";
      // Human-readable name for the Zendesk OAuth connection  const zendeskConnectionName = "zendesk";
      let data = JSON.stringify({    name: zendeskConnectionName,    oauth_client_name: zendeskOAuthClientName,    oauth_url_subdomain: subdomain,    origin_oauth_redirect_url: window.location.href,    permission_scopes: "read write",  });
      let request = {    type: "POST",    url: "/api/services/zis/connections/oauth/start/" + integrationName,    contentType: "application/json",    data: data,  };
      client.request(request).then(    function (response) {      console.log("Zendesk OAuth started");      authorize(response.redirect_url);    },    function (response) {      console.log("Failed to start Zendesk OAuth: ", response);    }  );}
    function authorize(redirectURL) {  let authWindow = window.open(redirectURL, "_blank");  setTimeout(watchToken, 1500);  // Poll token from the newly opened window  function watchToken() {    try {      let params = new URL(authWindow.location.href).searchParams;      // Cross-origin access will cause an error.      // When the OAuth flow completes, the authWindow's location      // redirects back to the same origin.      // This lets ZIS get the verification token.      let verificationToken = params.get("verification_token");      console.log("Established connection to Zendesk");      authWindow.close();    } catch (err) {      console.log(        "DOM error expected during cross domain authorization: " + err      );      setTimeout(watchToken, 500);    }  }}

    The code defines the startOAuth function. When called, startOAuth makes a Start OAuth Flow request to kick off an OAuth flow with Zendesk. The request uses the "zendesk" client you created earlier. When the OAuth flow completes, ZIS stores the resulting access token in a connection object.

    The Start OAuth Flow endpoint requires a name for the connection object. startOAuth uses a connection name of "zendesk." Later, you'll reference the connection's properties in your integration's ZIS flow. For example, in a ZIS flow, $.connections.zendesk.access_token references the "zendesk" connection's access token.

  4. Save iframe.html, bootstrap.js, and connect.js. To review your changes, click the refresh icon above the app.

    Your app now displays a Connect to Zendesk button.

Get a Zendesk access token

Next, it's time to test your app. Use the Connect to Zendesk button to start a Zendesk OAuth flow in the same way an admin would.

  1. In your app, click Connect to Zendesk.

    A Zendesk OAuth page opens in a new tab.

  2. Click Allow.

    The OAuth page closes and redirects back to the app.

    Behind the scenes, ZIS creates a "zendesk" connection that contains an access token for your Zendesk instance.

Verify the Zendesk access token

Next, use a Show Connection request to get the "zendesk" connection you created. This lets you verify that you can use the connection's access token in your integration.

  1. The Show Connection endpoint requires an OAuth access token for authentication.

    To get an OAuth access token, follow the steps in Obtaining an OAuth access token. Provide the client identifier and secret you saved when you registered the integration. Then return here.

  2. In your command-line interface, run:

    curl -X GET https://{subdomain}.zendesk.com/api/services/zis/connections/{subdomain}_zendesk_to_slack?name=zendesk \  -H "Authorization: Bearer {access_token}"

    The response contains details about the "zendesk" connection, including its access token. For example:

    {  "uuid": "***uuid***",  "name": "zendesk",  "zendesk_account_id": 00000001,  "integration": "example_zendesk_to_slack",  "permission_scope": "read write",  "access_token": "***access token***",  "token_type": "bearer",  "refresh_token": "",  "token_expiry": "0001-01-01T00:00:00Z",  "oauth_access_token_response_body": "",  "oauth_url_subdomain": "example",  "created_by": "1234567890123",  "created_at": "2099-05-16T15:33:19Z"}

In the next tutorial, you'll add a Connect to Slack button to your app. Refer to Part 2: Connect to Slack.