This page documents OAuth endpoints used by Tools web integrations.
oauth.slack.start/oauth/slack/startGET or POSTauth:webStarts the Slack OAuth flow and redirects to Slack oauth/v2/authorize.
slack-bot.marketplace.install/slack-bot/install/marketplaceGETUse this URL as Slack's Direct Install URL for Marketplace/App Directory installation and scope re-authorization. The endpoint seeds the Slack Bot OAuth state and return context, then immediately responds with HTTP 302 to Slack oauth/v2/authorize using the current required bot scopes.
Do not configure /oauth/slack/callback as the Direct Install URL. The callback belongs under Slack OAuth & Permissions - Redirect URLs and is only the destination Slack returns to after authorization.
oauth.slack.callback/oauth/slack/callbackGETauth:webSlack redirects back here with code and state.
For Slack AI Bot installations, OAuth errors return to /slack-bot when the flow can still be identified even if the temporary browser return target is unavailable. The OAuth state is still validated normally; this only keeps a failed bot installation in the correct setup context instead of sending it to My API Keys.
oauth.slack.callback-url/oauth/slack/callback-urlGETauth:webReturns the currently computed callback URL in JSON:
{
"callback_url": "https://tools.example.test/oauth/slack/callback"
}
Tools can install the same Slack app as an OpenAI-backed conversational bot for one or more Slack workspaces.
To install the same Slack app in additional workspaces, enable Slack App Distribution for the app. An unlisted distributed app can be used for private or pilot installations without publishing it in the Slack Marketplace. The same OAuth callback and Events Request URL are used for every installation. A target workspace may require an administrator to approve the app before installation can finish.
/slack-botFrom this page you can install the bot through Slack OAuth and configure each connected workspace independently. After the first installation, Install another Slack workspace starts the same OAuth flow for another workspace. Available settings include:
@mentionsWorkspace settings are saved asynchronously from /slack-bot, so changing the bot configuration does not reload the full page. Validation errors and save results are shown next to the save action. A successful settings change also sends a metadata-only notification to the configured Slack diagnostics channel when that channel is available. Custom instructions, preferred source URLs, tokens and secrets are not copied into that notification. Settings changes are also recorded in the dedicated Slack bot audit log with the workspace, actor, action, result and correlation id.
Preferred source URLs are priorities, not an exclusive source allowlist. When a relevant question can be answered from a preferred source and web search is enabled, the bot is instructed to check those sources first. It may use other reliable sources when the preferred sources are irrelevant, unavailable, or insufficient. The bot must not claim that it fetched or verified a configured URL unless the available search/context evidence shows that it did.
Spontaneous replies are disabled by default. Enabling the toggle alone does not activate them globally: each eligible public or private channel must also be listed by Slack channel ID. Ordinary channel messages are then evaluated conservatively. The bot should join only when a short reply adds useful information, answers an implied need, or naturally continues an active discussion. A configurable cooldown limits how frequently actual spontaneous replies can be posted in the same channel.
The bot can also understand supported image attachments in direct messages, direct mentions, and their bounded conversation context. JPEG, PNG, WebP, and GIF images are read from Slack only while the message is being processed, with a maximum of four images and 8 MB per image. Image bytes are not kept as a Slack-message archive or copied into OpenAI request logs. Existing Slack installations must be reinstalled after the current app manifest is saved so Slack can grant the files:read scope required for private file access.
Explicit image-creation requests in direct messages and addressed channel mentions are routed through ToolsAPI's existing image-generation service. Requests such as "Generate an image of a lighthouse at night" create the image under the Tools user who owns the Slack workspace installation, subject to the normal image-generation access rules. Generated images are uploaded as real Slack files and preserve the current DM, Assistant, or mention thread. Spontaneous channel initiative messages do not trigger image generation. Capability-only questions such as "Can you create images?" receive an affirmative reply without starting a generation job.
Slack image delivery uses Slack's current external file-upload flow and requires the files:write bot scope in addition to files:read for image input. Workspaces installed before either scope was granted must save the current app manifest and reinstall the bot so Slack can grant the missing permission.
Workspace bot access tokens returned by Slack OAuth are stored encrypted and are never shown back in the browser.
After a workspace installation has been persisted, Tools also attempts to announce the completed installation in the configured Slack diagnostics channel using that exact workspace's bot installation. If the workspace is saved but this diagnostic message cannot be delivered, the installation remains saved and /slack-bot shows an explicit error instead of silently presenting the notification step as successful.
Slack OAuth permissions and Slack Event Subscriptions are two separate app settings. Installing or reinstalling a workspace grants the scopes requested by Tools, but it does not create, repair, or verify the Slack-side Events Request URL or subscribed bot events.
/slack-bot therefore shows all three parts of the inbound contract together:
The page also generates a Slack App Manifest using the current callback and Events Request URLs. The manifest contains no OAuth token or signing secret. Review or paste it in Slack App Settings - App Manifest and save the Slack-side configuration. If the manifest introduces a scope that the installed workspace does not already have, reinstall the bot after saving the app configuration so Slack can grant that scope.
The current Tools integration preserves Slack's existing Assistant thread experience for apps that already use it. Slack now recommends the newer Agent messaging experience for new apps, but Tools does not silently migrate an existing Slack app between those experiences.
Signed Slack Event Subscriptions remain the primary inbound path and provide the fastest response. Tools also has a bounded Web API polling fallback so a missing or broken Events callback does not have to make the bot completely silent.
For distributed/unlisted Slack installations, the fallback is intentionally limited to one conversations.history request per workspace per minute and at most 15 messages per request. This matches Slack's current limit for new non-Marketplace distributed installations. Native Event Subscriptions remain the immediate path for normal mentions and DMs; the polling path is resilience rather than a low-latency replacement for Events API delivery.
Full conversation discovery is intentionally refreshed separately and stays bounded so the fallback does not repeat workspace-wide discovery unnecessarily.
The fallback checks a limited recent history window for conversations available to the installed bot. Direct channel mentions are normalized to the same app_mention processing path, while direct messages are normalized to message.im. The normal bot/self-message filters, workspace settings, transient message retention and OpenAI reply pipeline are reused. Because image loading happens in that shared processing path, supported image attachments work the same way when a message is recovered through polling.
Native Events API delivery and polling can remain enabled at the same time. Tools deduplicates the underlying Slack message by workspace, conversation, Slack message timestamp and normalized event type, so restoring Event Subscriptions does not cause a second reply to a message already picked up by polling.
Older installations can still poll already known conversations when the corresponding history scope is available. Full discovery of joined public channels, private channels and direct-message conversations requires the current channels:read, groups:read and im:read scopes. Image access additionally requires files:read, while generated image delivery requires files:write. Reinstall the workspace after saving the current app manifest when any required scope is missing.
For every connected workspace, /slack-bot shows whether the stored Slack installation contains all currently required bot scopes and displays the most recent supported Slack bot event that reached Tools, including its type, processing status, receive time and whether it arrived through the native Slack Events API or the polling fallback.
The same diagnostics section shows bounded polling status, including whether conversation discovery is limited by missing read scopes. These diagnostics do not expose Slack message bodies, bot access tokens or signing secrets.
The diagnostics page also provides an outgoing delivery test. Enter a Slack channel ID and choose Send test as bot. Tools then uses the selected workspace's stored bot installation to send a short message through Slack. A successful test confirms that Slack accepted an outgoing message from that bot installation to that channel. It does not prove that Slack Event Subscriptions are delivering incoming events to Tools.
When Tools accepts a direct mention or DM callback, it can also send a post-response ingress diagnostic before the OpenAI job is processed. That diagnostic contains only operational metadata such as workspace, channel, event type, and event id. It does not copy the Slack message body, OAuth token, request signature, signing secret, or AI response.
If no native supported event has reached Tools, check both the native Events API status and the polling fallback status shown on /slack-bot. A bot being present in a Slack channel does not by itself prove that Slack is delivering callbacks. Slack Event Subscriptions should still use the Events Request URL shown on /slack-bot and subscribe to the supported bot events listed below.
An outgoing Send test as bot success proves only outgoing chat.postMessage delivery. It does not prove native callback delivery. If native callbacks remain absent but the polling fallback is healthy, mentions and DMs can still be processed through the fallback within its bounded polling window.
/api/slack-bot/eventsPOSTUse the URL shown on /slack-bot as the Slack Events Request URL. The endpoint supports Slack URL verification and event callbacks.
Subscribe the Slack app to these required bot events:
app_mention - direct mentions in channelsmessage.im - direct messages, including user messages inside Slack Assistant threadsassistant_thread_started - lifecycle event for the existing Assistant messaging experienceassistant_thread_context_changed - lifecycle event for the existing Assistant messaging experienceThese additional bot events are required only when spontaneous channel replies are enabled:
message.channels - spontaneous replies in public channelsmessage.groups - spontaneous replies in private channelsThe bot requests these bot scopes:
app_mentions:readassistant:writechat:writereactions:writechannels:historychannels:readgroups:historygroups:readim:historyim:readmpim:historyfiles:readfiles:writeChannel mentions are answered in a Slack thread. Direct messages are answered directly unless the incoming DM already belongs to a thread. User messages inside the existing Slack Assistant experience arrive through message.im and can contain a thread_ts; Tools preserves that thread_ts when posting the reply. Spontaneous replies stay in the current thread when the triggering message belongs to one; otherwise they are posted directly in the configured channel. When context is enabled, the assistant can include a bounded amount of prior thread, DM, or eligible channel history, including supported images attached to those recent user messages. Explicit image-generation requests follow the same thread-preservation rules when the generated file is uploaded.
Incoming Slack requests are signature-verified before processing. Duplicate event ids are ignored, bot/self messages are ignored, and temporary message text is cleared after processing instead of being kept as a permanent Slack-message archive. Native Events API and polling observations of the same Slack message are also deduplicated before AI processing. Private image bytes are fetched only while the queued message is processed and are not persisted in Slack bot event state or OpenAI request logs. Generated-image audit records contain safe operational metadata only and do not copy Slack message bodies, prompts, image bytes, tokens, or credentials.
The Slack AI Bot is separate from Slack Log Routing. Existing incoming webhooks used for audit/log forwarding are not used for conversational replies.
oauth.soundcloud.start/oauth/soundcloud/startPOSTauth:webExpected payload:
{
"provider_app_id": 1,
"target_owner_type": "system",
"target_owner_id": null
}
oauth.soundcloud.callback/oauth/soundcloud/callbackGETauth:webReceives provider callback values (state, code, error, error_description).
oauth.microsoft.start/oauth/microsoft/startPOSTauth:webStarts the shared Microsoft OAuth flow for the currently logged-in user.
oauth.microsoft.start_link/oauth/microsoft/start-linkGETauth:webCreates a fresh signed Microsoft OAuth state and redirects directly to Microsoft from one normal clickable browser URL.
oauth.microsoft.callback/oauth/microsoft/callbackGETReceives provider callback values (state, code, error, error_description) and stores the current per-user Microsoft connection used by Microsoft To Do today. When the original browser session is gone, Tools now recreates the matching web session from the signed OAuth state before redirecting the user back into the Microsoft To Do integration page.
/api/microsoft/oauth/start/api/microsoft-todo/oauth/startGETPOST /api/account/loginReturns one Microsoft authorization URL for the authenticated user together with the callback URL currently expected by this host.
/api/microsoft/auth/statusGETPOST /api/account/loginReturns the shared Microsoft auth/platform-app readiness for the authenticated user, including callback/start URLs and tenant/account-type diagnostics that are not tied only to Microsoft To Do list/task counts.
The current X mention-bot does not complete a browser-based OAuth exchange. It still uses static server-side X_BOT_* credentials from .env.
If you receive X OAuth 2.0 client credentials during app setup, store them in:
X_OAUTH2_CLIENT_IDX_OAUTH2_CLIENT_SECRETX_OAUTH2_REDIRECT_URIIf the X dashboard also shows generated OAuth 2.0 user tokens, store them in:
X_OAUTH2_ACCESS_TOKENX_OAUTH2_REFRESH_TOKENThose are reserved for a future callback-driven OAuth2 flow and are separate from the current OAuth1-style posting credentials X_BOT_ACCESS_TOKEN and X_BOT_ACCESS_TOKEN_SECRET.
However, Tools now exposes a public callback placeholder so there is a real URL available for X app registration when a callback field is required:
oauth.x.callback/oauth/x/callbackGETThis route currently acts as an informational landing page and placeholder only. It does not yet exchange or store X OAuth tokens.
oauth.x.callback-url/oauth/x/callback-urlGETReturns JSON containing the currently computed X callback URL.
For Slack app configuration, register the OAuth callback URL shown by Tools under Slack OAuth & Permissions - Redirect URLs. For Slack Marketplace/App Directory, configure /slack-bot/install/marketplace as the Direct Install URL so Tools can create OAuth state before redirecting to Slack. If a callback override is configured, that value is used as the effective redirect URI and should be registered in Slack App settings.
For the shared Microsoft / Microsoft Graph app configuration, register the callback matching the current environment and use the generic /oauth/microsoft/callback route as the registration target for a shared Microsoft / Graph app.
If a Microsoft redirect override is configured, it becomes the effective redirect URI and should also be registered in the Microsoft Entra app. The legacy Microsoft To Do redirect override remains accepted as a compatibility alias.
If you expect personal Microsoft accounts (@outlook.com, @hotmail.com, @live.com), use tenant common or consumers and make sure the Azure app registration itself is enabled for personal accounts (MSA). If not, Microsoft commonly responds with unauthorized_client.
For X app registration, use the X callback URL shown by the current Tools environment when a callback field is required.
When the Microsoft To Do platform app is not environment-managed, the shared app settings can also be saved from /settings/integrations/microsoft-todo by an acknowledged admin. The page shows the same recommended callback URL together with additive diagnostics about missing platform-app fields.