skip to Main Content

To use Events API for Slack App development, there is a setting for “Events API Request URLs” as described in doc:

In the Events API, your Events API Request URL is the target location
where all the events your application is subscribed to will be
delivered, regardless of the team or event type.

There is a UI for changing the URL “manually” at api.slack.com under
“Event Subscriptions” section in settings. There is also url_verification event after changing the Request URL described here.

My question – Is there an API call (method) so I can update the endpoint (Request URL) from my server code?

For example, in Facebook API there is a call named subscriptions where I can change webhook URL after initial setup – link

Making a POST request with the callback_url, verify_token, and object
fields will reactivate the subscription.

PS. To give a background, this is needed for development using outbound tunnel with dynamic endpoint URL, e.g. ngrok free subscription. By the way, ngrok is referenced in sample “onboarding” app by slack here

Update. I checked Microsoft Bot Framework, and they seems to use RTM (Real Time Messaging) for slack which doesn’t require Request URL setup, and not Events API. Same time, e.g. for Facebook they (MS Bot) instruct me to manually put their generated URL to webhook settings of a FB app, so there is no automation on that.

2

Answers


  1. No, such a method does not exist in the official documentation. There might be an unofficial method – there are quite a few of them actually – but personally I doubt it.

    But you don’t need this feature for developing Slack apps. Just simulate the POST calls from Slack on your local dev machine with a script and then do a final test together with Slack on your webserver on the Internet.

    Login or Signup to reply.
  2. Since this question was originally asked, Slack has introduced app manifests, which enable API calls to change app configurations. This can be used to update URLs and other parameters, or create/delete apps.

    At the time of writing, the manifest / manifest API is in beta:

    Beta API — this API is in beta, and is subject to change without the usual notice period for changes.

    so the this answer might not exactly fit the latest syntax as they make changes.


    A programatic workflow might look as follows:

    1. Pull a ‘template’ manifest from an existing version of the application, with most of the settings as intended (scopes, name, etc.)
    2. Change parts of the manifest to meet the needs of development
    3. Verify the manifest
    4. Update a slack app or create a new one for testing

    API List

    Basic API list

    Most of these API requests are Tier 1 requests, so only on the order of 1+ per minute.

    API Access

    You’ll need to create and maintain "App Configuration Tokens". They’re created in the "Your Apps" dashboard. More info about them here.

    Example NodeJS Code

    const axios = require('axios');
    
    // Change these values:
    const TEMPLATE_APP_ID = 'ABC1234XYZ';
    const PUBLIC_URL = 'https://www.example.com/my/endpoint';
    let access = {
        slackConfigToken: "xoxe.xoxp-1-MYTOKEN",
        slackConfigRefreshToken: "xoxe-1-MYREFRESHTOKEN",
        slackConfigTokenExp: 1648550283
    };
    
    // Helpers ------------------------------------------------------------------------------------------------------
    // Get a new access token with the refresh token
    async function refreshTokens() {
        let response = await axios.get(`https://slack.com/api/tooling.tokens.rotate?refresh_token=${access.slackConfigRefreshToken}`);
        if (response.data.ok === true) {
            access.slackConfigToken = response.data.token;
            access.slackConfigRefreshToken = response.data.refresh_token;
            access.slackConfigTokenExp = response.data.exp;
            console.log(access);
        } else {
            console.error('> [error] The token could not be refreshed. Visit https://api.slack.com/apps and generate tokens.');
            process.exit(1);
        }
    }
    
    // Get an app manifest from an existing slack app
    async function getManifest(applicationID) {
        const config = {headers: { Authorization: `Bearer ${access.slackConfigToken}` }};
        let response = await axios.get(`https://slack.com/api/apps.manifest.export?app_id=${applicationID}`, config);
        if (response.data.ok === true) return response.data.manifest;
        else {
            console.error('> [error] Invalid could not get manifest:', response.data.error);
            process.exit(1);
        }
    }
    
    // Create a slack application with the given manifest
    async function createDevApp(manifest) {
        const config = {headers: { Authorization: `Bearer ${access.slackConfigToken}` }};
        let response = await axios.get(`https://slack.com/api/apps.manifest.create?manifest=${encodeURIComponent(JSON.stringify(manifest))}`, config);
        if (response.data.ok === true) return response.data;
        else {
            console.error('> [error] Invalid could not create app:', response.data.error);
            process.exit(1);
        }
    }
    
    // Verify that a manifest is valid
    async function verifyManifest(manifest) {
        const config = {headers: { Authorization: `Bearer ${access.slackConfigToken}` }};
        let response = await axios.get(`https://slack.com/api/apps.manifest.validate?manifest=${encodeURIComponent(JSON.stringify(manifest))}`, config);
        if (response.data.ok !== true) {
            console.error('> [error] Manifest did not verify:', response.data.error);
            process.exit(1);
        }
    }
    
    // Main ---------------------------------------------------------------------------------------------------------
    async function main() {
        // [1] Check token expiration time ------------
        if (access.slackConfigTokenExp < Math.floor(new Date().getTime() / 1000))
            // Token has expired. Refresh it.
            await refreshTokens();
    
        // [2] Load a manifest from an existing slack app to use as a template ------------
        const templateManifest = await getManifest(TEMPLATE_APP_ID);
        
        // [3] Update URLS and data in the template ------------
        let devApp = { name: 'Review App', slashCommand: '/myslashcommand' };
    
        templateManifest.settings.interactivity.request_url = `${PUBLIC_URL}/slack/events`;
        templateManifest.settings.interactivity.message_menu_options_url = `${PUBLIC_URL}/slack/events`;
        templateManifest.features.slash_commands[0].url = `${PUBLIC_URL}/slack/events`;
        templateManifest.oauth_config.redirect_urls[0] = `${PUBLIC_URL}/slack/oauth_redirect`;
        templateManifest.settings.event_subscriptions.request_url = `${PUBLIC_URL}/slack/events`;
        templateManifest.display_information.name = devApp.name;
        templateManifest.features.bot_user.display_name = devApp.name;
        templateManifest.features.slash_commands[0].command = devApp.slashCommand;
        
        // [5] Verify that the manifest is still valid ------------
        await verifyManifest(templateManifest);
    
        // [6] Create our new slack dev application ------------
        devApp.data = await createDevApp(templateManifest);
        console.log(devApp);
    }
    
    main();
    

    Hope this helps anyone else looking to update Slack applications programatically.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search