Build a Slack app and submit to the Slack Marketplace
10-step playbook from 'manifest.yml on my laptop' to 'live in the Slack Marketplace.' Real OAuth gotchas, real review traps, real agent prompts.
Open in Dock→Developers shipping a multi-workspace Slack app
Building a Slack app is straightforward; getting into the Marketplace is a process. The Marketplace requires a working OAuth install flow, minimum-scope justifications, a security questionnaire, an in-product onboarding video, and a privacy + terms review. This playbook walks the 10 gates with the official Slack docs, the Bolt SDK snippets that work, and agent prompts for the parts agents do well: drafting the listing, picking minimal scopes, designing slash command argument schemas, drafting the security questionnaire.
Outcome
Your Slack app live in the Slack Marketplace, installable to any workspace via OAuth, with reviewer-approved scope minimisation and a sound onboarding flow.
Time3-6 weeks (most of it Marketplace review iterations)DifficultyadvancedForDevelopers shipping a multi-workspace Slack app for distribution.
Top to bottom. Each step has tasks, pointers, gotchas.
01 / 10
Create the app from a manifest YAML
1 hr
Slack apps are best created from a manifest.yml: declarative config for scopes, slash commands, event subscriptions, OAuth redirects. The manifest is checked in to your repo; create from manifest gives you reproducible app config across dev / staging / prod.
Tasks
Open https://api.slack.com/apps → Create New App → From an app manifest
Pick a workspace (your dev workspace is fine for now)
Paste a starter manifest.yml with display_information, bot scopes, slash commands stubs
Open the new app's Basic Information tab; copy the Signing Secret + App ID into your env vars
Check the manifest.yml into your repo; treat it as the canonical source
The manifest.yml is the source of truth ONLY if you remember to re-export from the dashboard after changes. Edit in the YAML; apply via the dashboard.
Scopes added via the dashboard but not added to the YAML get stripped on next manifest apply. Always edit YAML first.
App ID and Signing Secret are different from the OAuth Client ID / Secret. Don't mix them up in env vars.
02 / 10
Implement OAuth install with state + token storage
3-5 hr
Public Slack apps install via OAuth v2: workspace admin clicks Install, lands on api.slack.com, picks scopes, redirects to your /slack/oauth/redirect with a code, you exchange the code for a bot token, then store it keyed by team_id. Bolt's official ExpressReceiver / FastAPI handlers do this for you. Don't roll your own.
Tasks
Set the OAuth redirect URL in the app dashboard (e.g. https://yourapp.com/slack/oauth/redirect)
Use Bolt's ExpressReceiver (Node) or AsyncSlackRequestHandler (Python) for the OAuth flow
Store the bot token + team_id + enterprise_id in your DB on installation
Implement an installationStore.fetchInstallation(teamId, enterpriseId) — Bolt calls it on every event
Implement an uninstall webhook (app_uninstalled event) and zero out tokens for that team
Test the install flow end-to-end on a brand new dev workspace
OAuth redirect URLs are an exact-match list. http vs https + trailing slash differences get rejected. Whitelist BOTH staging and prod URLs.
When you store bot tokens, encrypt at rest. Slack's review reads your security questionnaire and looks for this.
On app_uninstalled, you MUST stop using the token + delete or invalidate it. Continued API calls with revoked tokens hit rate limits + flag your app on review.
03 / 10
Subscribe to events via Events API or Socket Mode
2-4 hr
Slack pushes events (messages, app_mention, app_home_opened) two ways: Events API (HTTP POST to your endpoint) or Socket Mode (WebSocket from your server). Events API is the only option for distributed apps; Socket Mode is dev-only / single-workspace. Public apps go through Events API.
Tasks
Set Request URL on the Event Subscriptions tab (Bolt verifies the URL automatically)
Subscribe to the events your app handles: app_mention, message.channels, app_home_opened, etc.
Verify Slack's signing secret on every incoming POST (Bolt does this automatically)
Respond within 3 seconds (Slack retries up to 3x on timeout). Off-load slow work to a queue.
Implement event handlers in your Bolt app
Test with the Block Kit / Events API tester on api.slack.com
Events API endpoints must respond with HTTP 200 within 3 seconds. Heavy work (LLM calls, slow DB queries) must run on a background queue; ack the event first.
Slack retries failed events up to 3 times. Make handlers idempotent; key on event_id.
Socket Mode apps cannot be submitted to the Marketplace. If you built on Socket Mode for dev, plan to rewrite to Events API for distribution.
04 / 10
Pick the absolute minimum OAuth scopes
2-3 hr
The Marketplace review hammers on scopes. For every scope you request, the reviewer asks: does the user-visible feature literally require this? Bot scopes (chat:write) are easier to justify than User scopes (channels:history). Avoid User Token scopes unless absolutely necessary; avoid wildcard scopes (groups:read) when narrower exists.
Tasks
List every scope in your manifest.yml
For each, write the user-visible feature it powers
Flag any scope where the feature could work with a narrower scope (chat:write.public vs chat:write)
Move every User Token scope to a Bot Token scope if your bot can do the work as itself
Drop any scope you can't justify with a real feature
Re-test the install flow with the trimmed scope list
Adding scopes after install doesn't auto-grant them; users have to re-authorize. Plan scope changes for major versions.
User Token scopes (e.g. channels:history) are heavily scrutinised on review. If your feature needs message history, prefer reading per-message via app_mention rather than scanning channels.
The 'admin' scope set is enterprise-only. Don't request it unless you specifically build for Enterprise Grid.
Agent prompt for this step
Audit this Slack app's manifest.yml + source code, then output the minimum-scope list.
For each scope currently in the manifest:
1. Find the API call(s) in the source that require it.
2. Name the user-visible feature behind those calls.
3. Decide: keep, narrow (e.g. channels:read → chat:write.public), or drop.
Output:
- Recommended manifest scopes block
- Per-scope justification (2-3 sentences each, naming the feature + why a narrower scope wouldn't work)
Constraint: bias toward Bot Token scopes. User Token scopes need a much harder justification.
05 / 10
Build the slash commands + Block Kit interactions
1-2 days
Slash commands and Block Kit messages are how users interact with your app. Both are declared in the manifest, both POST to your endpoints, both respond within 3 seconds. Block Kit Builder is the visual designer; copy the JSON to your code.
Tasks
Declare slash commands in manifest.yml (name, description, usage_hint, request URL)
Implement each slash command handler in Bolt
Use Block Kit for rich responses (sections, dividers, buttons, datepickers)
For multi-step flows: open a Modal (views.open) and handle view_submission
For long-running operations: respond with an in-channel ack message + update later via response_url
Slash commands have a 3-second response window. ack() first, then do the slow work and update via response_url.
Slack truncates slash command messages over 40k characters. Use threads or Block Kit pagination for long output.
Modals must be acknowledged with response_action 'clear' or 'update' or they hang the UI. Bolt's view_submission helpers handle this.
06 / 10
Build the App Home + onboarding experience
1 day
Every public app has an App Home — the tab a user sees when they click your app's name in their sidebar. Reviewers want a polished App Home: who you are, what the app does, how to get started, link to docs. Empty App Home is a Marketplace rejection on its own.
Tasks
Subscribe to the app_home_opened event
On the first app_home_opened per user: render a Block Kit view with a welcome + 3-step onboarding
Subsequent app_home_opened: render the user's current state (favourites, recent activity, settings)
Add buttons that link to /slash commands or external docs
Add a 'Help & Support' button that opens a modal with FAQ + contact email
App Home views are per-user-per-workspace. Don't render a generic view — personalise based on what the user has done.
App Home must update without user action. Re-publish the view on relevant events (e.g. they invited a teammate, completed a task).
Discovery: if your bot has chat:write, send a single welcome DM on install in addition to the App Home. The DM is what most users see first.
07 / 10
Set up Privacy Policy, Terms of Service, and security headers
4-6 hr
Slack reviews require a public Privacy Policy URL + Terms of Service URL. The Privacy Policy must specifically cover Slack data: what you collect from messages / events / OAuth, retention, deletion-on-request. Generic web app templates fail review.
Tasks
Audit what Slack data your app reads (channels, message contents, user profiles, file uploads)
Write or update the Privacy Policy with a Slack-specific section
Write or update the Terms of Service
Host both at public URLs (e.g. yourapp.com/privacy, yourapp.com/terms)
Set the URLs in App Directory metadata
Add a Data Retention + Deletion section explaining how a customer can request data removal
Privacy policies that say 'we may collect data' without specifics fail review. List concrete data types: channel IDs, message text, user emails, etc.
Data retention must have a clear time bound (e.g. '90 days' or 'until uninstall'). 'As long as needed' fails review.
If your backend integrates with third parties (OpenAI, Anthropic, Stripe), the policy must list them. Sub-processor lists are reviewed too.
08 / 10
Make the app distributable + activate Public Distribution
1-2 hr
By default a Slack app is single-workspace. To distribute to other workspaces, you toggle Public Distribution on the Manage Distribution tab. This requires: OAuth working with state parameter, no hard-coded team IDs, and no use of dev-only features (Socket Mode).
Tasks
Manage Distribution tab → activate Public Distribution
Slack runs an automated check (OAuth state, redirect URLs, no Socket Mode)
Fix any flagged issues
Add yourself or a teammate as a 'collaborator' so multiple humans can manage the listing
Generate the 'Add to Slack' button HTML and embed it on your landing page
Public Distribution is a one-way switch. Once on, you can't go back to single-workspace without losing all installations.
OAuth state parameter is mandatory for public distribution. Bolt handles it; raw code must implement state.
Slack rejects 'Add to Slack' embeds that don't follow the brand guidelines (specific colour, specific logo). Use the official button HTML.
09 / 10
Submit to the Slack Marketplace + survive review
1 week to prepare, 3-6 weeks of review iterations
The Marketplace submission has 5 sections: app description, screenshots, demo video, security questionnaire, and policy URLs. Reviewers come back with scope questions, security questions, and onboarding feedback. Plan for 2-4 review iterations over 3-6 weeks.
Tasks
Draft the listing: title, short description, long description, categories
Take 3-5 screenshots showing real workflows in real Slack workspaces
Record a 60-90 second onboarding video (loom or screencast)
Complete the security questionnaire (data flow diagram, encryption, retention, sub-processors)
Submit via the App Directory → Submit to App Directory button
On reviewer response: address each comment, never argue, resubmit
On approval: confirm listing is searchable + Add-to-Slack flow works from the directory
Screenshots from your dev workspace ('Test workspace' channel names visible) get sent back. Use a polished demo workspace.
Demo videos that include personal/customer data fail review on privacy grounds. Use synthetic data.
Reviewers cite specific Marketplace guidelines (e.g. 'Onboarding 1.2'). Look up the guideline in the docs and match the wording in your fix.
Agent prompt for this step
Draft the Slack Marketplace submission for this app.
Read the Brief, the manifest.yml, and the source. Output:
1. **Short description** (140 chars): single-sentence elevator pitch.
2. **Long description** (markdown, 600-1200 words): lead with the user benefit, then 3-5 features as headed sections with screenshots interleaved, end with security + privacy notes.
3. **Onboarding video script** (60-90 seconds): a screen-by-screen narration. Open with the install flow, hit the first slash command, end with App Home.
4. **Security questionnaire answers**: data flow diagram description, encryption at rest + in transit, sub-processors, data retention, GDPR + CCPA delete-on-request flow.
Tone: B2B SaaS. No emoji, no exclamation marks. Reviewers are admins evaluating risk.
10 / 10
Post-launch: monitor installs, OAuth failures, and review responses
Ongoing, 3-5 hr/week for the first month
After approval, the operations layer matters: OAuth install errors (typically misconfigured firewalls / corp networks), uninstalls, and rate limits. Slack rate-limits per app per workspace; a noisy app can get its tokens revoked.
Tasks
Set up monitoring on /slack/oauth/redirect — log every install + every error
Set up monitoring on rate limit headers (X-Rate-Limit-Remaining, Retry-After)
Subscribe to admin emails on the App Directory submission so updates trigger re-review
Read every review on the App Directory and respond publicly
Track install → first event → 7-day retention; iterate on the leakiest step
Plan scope changes for a new major version; users have to re-authorize
Rate limits are per app + per workspace, with different tiers per method. A bulk-update job that fires 100 chat.update calls in a minute will trip Tier 2 limits.
Tokens can be revoked silently if the workspace owner uninstalls. Your code must handle 401 invalid_auth gracefully.
Updating manifest scopes triggers re-review for the listing. Plan scope changes carefully or batch them.
Hand the template to your agent
Workspace-wide agent prompt.
Paste this into your agent's permanent system prompt so the agent reads, writes, and maintains the template's surfaces as you work through the steps.
Agent system prompt
You are an agent on the "Build a Slack app" playbook workspace at your-org/build-a-slack-app.
Your role: maintain the four surfaces (Steps, Pointers, Brief, Submission log) as the user works through the 10-step playbook.
Cadence:
- When the user marks a step Done, append a line to the Brief.
- When Slack reviewers respond, capture the response (scope question, security follow-up, approval) as a row in Submission log + draft the next-action note in the Brief.
- When the user adds a new pointer (link), mirror it into Pointers.
First MCP tool calls:
1. list_surfaces(workspace_slug="build-a-slack-app")
2. list_rows(workspace_slug="build-a-slack-app", surface_slug="steps")
3. get_doc(workspace_slug="build-a-slack-app", surface_slug="brief")
Do NOT modify canonical step titles. Append substeps as new rows.
FAQ
Common questions on this template.
How long does Slack Marketplace review take?
Typical: 3-6 weeks across 2-4 iterations. Reviewers usually come back with 5-15 comments per round (scope questions, security clarifications, onboarding fixes). The most common time-sinks are rewriting the Privacy Policy, recording a new onboarding video, and answering the security questionnaire properly. Plan for the round-trip; first-pass approvals are rare.
Do I need to be in the Marketplace to distribute my app?
No. Public Distribution lets any workspace install your app via your 'Add to Slack' button without the Marketplace listing. The Marketplace adds discoverability + the trust signal of being reviewed. Many B2B apps stay 'distributed but unlisted' for the first 6-12 months while customer count is small.
What gets Slack apps rejected from the Marketplace?
The top three: (1) over-broad scopes that the reviewer can't justify against the app's features (User Token scopes are top offender), (2) insufficient onboarding (empty App Home, no demo video, vague slash command help), (3) Privacy Policy that doesn't specifically cover Slack data flows. Read each reviewer comment as a literal request and address exactly that.
Can my AI agents help with the Slack app?
Yes. Agents are particularly useful for: auditing the source to draft minimum-scope justifications, drafting the long description + onboarding video script, drafting the security questionnaire from a code audit, and triaging reviewer comments on each round. The playbook ships agent prompts inline.
What does shipping a Slack app cost?
$0 to develop and distribute. Slack does not charge listing fees, transaction fees, or annual fees. If you charge for your app, billing happens in your own backend (Stripe / etc.); Slack does not handle payments. Your costs are: hosting (small, $5-50/mo), database (small, $10-30/mo), and the time investment of 3-6 weeks of review iterations.
Open this template as a workspace.
We mint a fresh copy in your org with the steps as table rows, the pointers as a separate table, and the brief as a doc. Bring your agents, start checking off boxes.