A Slack slash command lets someone trigger your Python code by typing a command such as /hello in Slack. This guide shows how to register a command, receive and verify its HTTP request in Flask, and send a response back without exposing secrets or making users wait unnecessarily.
What You’ll Need
- A Slack workspace where you can create or install apps, plus permission to add an app if your workspace restricts that.
- Python 3 and Flask installed in a virtual environment.
- A public HTTPS URL for your Flask app. For local development, use a reputable HTTPS tunnel; for ongoing use, deploy to a host that supports HTTPS.
- A place to store environment variables, including the Slack signing secret. Do not commit secrets to source control.
Step-by-Step
- Create a Slack app. In Slack’s API app management, create an app for your workspace. Open Slash Commands and choose Create New Command. Enter a command such as
/hello, a short description, and a request URL placeholder. You will replace the placeholder after exposing your Flask endpoint. Choose whether the command is available in message composers or other contexts if Slack offers those options for your app. - Set up the Python project. Create and activate a virtual environment, then install Flask:
python -m venv .venv, activate it using the command for your operating system, and runpip install Flask. Save dependencies withpip freeze > requirements.txtif you plan to deploy. Keep local configuration out of version control. - Build the Flask endpoint. Slack sends slash command requests as form-encoded POST data. A minimal starting point is:
from flask import Flask, request, jsonifyapp = Flask(__name__)@app.post("/slack/commands")def slash_command():command = request.form.get("command", "")text = request.form.get("text", "")if command != "/hello":return "Unknown command", 400return jsonify(response_type="ephemeral", text=f"Hello! You entered: {text}")
This returns a JSON response immediately. Anephemeralreply is visible only to the person who invoked the command; usein_channelwhen the reply should be visible to everyone in the channel. - Verify that requests really come from Slack. Before processing a command, validate Slack’s signature using the raw request body, the
X-Slack-Request-Timestampheader, and your app’s signing secret. Reject missing or invalid signatures, and reject requests whose timestamp is too old to reduce replay risk. Use Slack’s documented signing procedure and a constant-time signature comparison; do not treat a secret URL or a submitted user ID as authentication. Store the signing secret in an environment variable and never log it. For a quick prototype, you can first test the route without verification locally, but do not expose an unverified endpoint as a working integration. - Expose the endpoint securely. Run Flask locally and provide an HTTPS tunnel URL for development, or deploy the app behind HTTPS. A tunnel’s address can change, so check it before configuring Slack. Do not use Flask’s development server as a public production server; use a suitable production WSGI server and hosting setup.
- Configure the command URL. In the command settings in Slack, set the request URL to the public address ending in
/slack/commands, save the command, and install or reinstall the app if prompted. Slack sends a verification request when you save settings. Your endpoint must accept that request successfully before Slack can use it. - Test the command in Slack. Type
/hello, optionally followed by text, and check the response. Confirm both that your Flask app receives the request and that Slack displays the reply. Test with an empty argument, ordinary text, and unexpected input. Use Slack’s request logs and your server logs to diagnose failures, while avoiding sensitive data in logs. - Handle longer work asynchronously. Slack expects a quick acknowledgement, commonly within about three seconds. If a task may take longer, acknowledge promptly and do the work in a background worker; then use the response URL included in Slack’s request to send a follow-up. Treat that URL as a secret, validate input, and avoid doing slow network calls before acknowledging.
Common Mistakes
Using a localhost URL is a frequent cause of failed requests: Slack cannot reach your computer directly. Another common mistake is configuring a URL that does not match the Flask route or using HTTP instead of HTTPS. Check the full path, method, and public address.
Do not parse the request as JSON by default. Slash commands are form-encoded, so read values from request.form. Do not skip signature verification in production, hard-code the signing secret, or assume a request is trustworthy because it contains a Slack-looking user name. Also avoid returning a slow response: Slack can report a timeout even if your code eventually finishes.
Tips
Keep the route small: validate the command, parse its arguments, acknowledge, and hand off any substantial work. Return helpful messages for missing or invalid arguments rather than stack traces. Use ephemeral responses for private feedback and channel-visible responses only when that is appropriate.
Separate development and production secrets, and rotate exposed credentials through Slack’s app settings. Add tests for signature validation and input parsing. Log request IDs or useful error details, but avoid logging tokens, signing secrets, full response URLs, or private command text unless there is a clear need and appropriate handling.
Troubleshooting
Slack says the request URL could not be verified: Confirm the app can reach the HTTPS URL, that your route accepts the verification request, and that the server is running. Check tunnel logs and Flask logs for connection errors or a wrong path.
The command reports a timeout: Return an acknowledgement quickly. Move slow operations to background work and send a follow-up through Slack’s response URL. Check for blocking calls or long database queries on the request path.
Your app returns an authorization error: Compare the signing secret in your environment with the app’s current secret. Make sure you calculate the signature from the exact raw request body and original timestamp header, and account for server clock accuracy. Do not disable verification to conceal a mismatch.
The endpoint runs but no message appears: Check that the response is valid JSON with a text field, and that the route returns an appropriate HTTP status promptly. Confirm the command is saved and the app is installed in the workspace where you are testing.
Frequently Asked Questions
Can I test a Slack slash command on my computer?
Yes. Run Flask locally and expose it through an HTTPS development tunnel, then use the tunnel URL in the command settings. Keep the tunnel running while testing.
Does a slash command send JSON to Flask?
Usually no. Slack sends form-encoded fields in a POST request. Read them with Flask’s request.form.
What is the difference between ephemeral and in-channel replies?
An ephemeral reply is visible only to the person who invoked the command. An in-channel reply is visible to people in the channel.
Why do I need to verify Slack’s request signature?
Signature verification lets your app check that a request was signed with your app’s secret and was not simply sent by an arbitrary client. It should be part of production handling.
Can a slash command take longer than a few seconds?
It can start longer work, but your endpoint should acknowledge quickly. Process the task asynchronously and send a later response using Slack’s response URL.
Can I use Flask’s built-in server in production?
It is intended for development. Deploy Flask behind HTTPS using a production WSGI server and an appropriate hosting configuration.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Skype Messaging Updates: What Changed
- Filter Values Within Tolerance: How It Works
- Why Chromecast Still Good Purchase
- Programming Skills for Job: What You Need120 hours
- Asus ProArt P16 Laptops: Specs, Pros, Cons & Buying Tips
- Analytical Database Engine: What It Does & When to Use