v4
latestOpenAPI 3.1.02026-08-03427198448.4 KBslack
Slack Events
Slack Events API request URL.
Ordering is deliberate and must not be reordered:
- Verify X-Slack-Signature (and reject a stale timestamp) against the RAW body, before any JSON parsing.
- Handle url_verification (Slack's one-time endpoint handshake).
- For a DM, app_mention, or assistant_thread_started event, resolve team_id -> the org that installed this workspace (a READ -- required because agent_background_jobs.org_id is a NOT NULL FK, so there is no way to enqueue anything without it; a read has no "succeeded but orphaned" failure mode, unlike a write, so it is safe to keep ahead of the ACK). Everything else that is a genuine judgement call -- the slack_agent_app gate, Slack identity-link resolution -- stays in the worker (services/job_processor.py:_process_slack_agent_turn_job / _process_slack_assistant_thread_started_job), never here.
- Acknowledge with 200 after exactly ONE pre-ACK WRITE: an idempotent job insert (AgentBackgroundJobService.create_background_job_idempotent, dedupe_key=event_id) that carries the event-dedup uniqueness itself. A duplicate Slack delivery's insert simply conflicts and returns the existing job row -- no separate dedup write exists that a later failure could orphan (see the migration's design-note comment for the prior two-write design this replaced and why it lost events). If the insert raises, we do NOT ACK (500) -- nothing was durably written, so Slack's retry is the correct, safe recovery path.
post/api/slack/events
Response
Successful Response
{"stackTrail":"paths:/api/slack/events:post:responses:200:content:application/json:schema","oasType":"schema","type":"unknown"}