---
title: "Slack Oauth Callback"
method: GET
path: "/v1/webhooks/slack/oauth/callback"
tags: ["webhooks"]
---

# Slack Oauth Callback

`GET /v1/webhooks/slack/oauth/callback`

## Request

- Base URL: `https://api.patricia.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.patricia.app/v1/webhooks/slack/oauth/callback`
- Auth: none declared

Verify state (+ browser-binding nonce), exchange the code, persist the install, then
bounce the browser back to the dashboard page the install started from.

Slack hands the user's browser to this route as a top-level navigation, so both exits
are redirects: the installer lands back in-app on the page they clicked Connect from,
flagged ``?slack=connected`` or ``?slack=error``, never on a raw JSON body. The return
page rides in the signed state (the SPA fetches the install URL over XHR, so a cookie
set at mint time would never come back), and is resolved BEFORE the exchange so a
failure returns to the same page a success would.

The generic error flag is deliberate: the reason for a failure (an already-claimed
workspace, a stale state) never leaks into the URL, matching the Teams callback.

The installer's IP rides along because the starter-verification gate checks it against our
cached Tor exit-node list for a multi-member workspace, the only shape a clean verdict can
waive. It comes from ``provable_client_ip``, so only a proxy-written forwarded entry is ever
believed: a chain too short to prove one yields no address, which reads as unknown at the
gate and holds the grant.

The binder cookie is single-use: it is cleared on the returned response whatever the
outcome, including a rejection. We build the response explicitly (rather than letting
an exception propagate) so the ``Set-Cookie`` deletion survives the error path: a
raised ``AppException`` is rendered by the global handler into a *fresh* response that
would not carry a header set on an injected ``Response``.

## Query parameters

- `code` string, nullable
- `state` string, nullable
- `error` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/patricia/apis/patricia-api.md) · [All operations](https://skmtc.dev/patricia/apis/patricia-api/llms.txt) · [OpenAPI document](https://skmtc.dev/patricia/apis/patricia-api/revisions/0dfb44495ea1?raw)
