Skip to main content
For Slack, Linear, GitHub, and Notion, the agent supports a one-click OAuth flow instead of copy-pasting API keys. OAuth is the recommended path because it:
  • Doesn’t require users to leave the dashboard to generate keys.
  • Records the workspace name / team / repo owner automatically (visible in GET /v1/cofounder/integrations).
  • Uses provider-issued tokens that can be revoked from the provider’s UI.
  • Lets you offer the same SaaS experience your users expect from any modern integrations page.
Webhook and ASC-write don’t need OAuth — they use a URL and the user’s existing ASC connection.

How the flow works

Two endpoints, both under the cofounder router: :providerslack | linear | github | notion.

Frontend usage

After the round-trip your page is reloaded with ?cofounder_oauth=success&provider=slack&account=Acme%20Workspace in the query string. Detect this in your page-load code, refresh the integrations list, and show a toast. Failure cases also redirect back, with ?cofounder_oauth=denied (user clicked Cancel) or ?cofounder_oauth=error&error=... (token exchange failed). Always inspect both shapes.

Server configuration

For each provider you want to support, create an OAuth client in the provider’s developer console. Set the Redirect URI to:
Then set the corresponding env vars: Cross-cutting: return_to MUST start with one of the allowlisted prefixes — otherwise it’s rejected (open-redirect guard).

What gets stored

After a successful OAuth round-trip, a row is upserted in cofounder_integrations:
encrypted_credentials is never returned by GET /v1/cofounder/integrations. The dashboard only sees the metadata above plus enabled and last_used_at.

Re-connect / Switch workspace

Re-running /oauth/:provider/start and completing the flow upserts the same (owner_email, provider) row — pointing the integration at the new workspace. The previous token is overwritten and effectively forgotten by the agent (it remains valid on the provider’s side until the user revokes it from there).

Disconnect

This removes the credentials from our database. It does not revoke the token on Slack — go to your Slack workspace’s Apps page if you want to revoke it there too.

State row lifecycle

Each /start creates a cofounder_oauth_states row that:
  • Holds the random state, the user’s email, the provider, and (if applicable) the PKCE code_verifier.
  • Expires after 10 minutes.
  • Is deleted as soon as the callback consumes it (single-use).
Expired rows are purged opportunistically on every /start call.

Manual API-key path (still supported)

If you’d rather skip OAuth — for example, scripting your own integration — you can PUT /v1/cofounder/integrations/:provider with the credential JSON directly. See each provider’s page for the schema. OAuth-managed and manually-managed rows coexist; the latest one wins.