> ## Documentation Index
> Fetch the complete documentation index at: https://cofounder.appeeky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrations

> Manage Slack, Linear, GitHub, Webhook, Notion, and ASC write credentials.

```
GET    /v1/cofounder/integrations
PUT    /v1/cofounder/integrations/:provider
DELETE /v1/cofounder/integrations/:provider
GET    /v1/cofounder/oauth/:provider/start
GET    /v1/cofounder/oauth/:provider/callback     ← public (state-authenticated)
```

Each integration row holds credentials + config for one delivery channel. Two ways to populate it:

* **OAuth** (Slack, Linear, GitHub, Notion) — one click, captures workspace info automatically. See [OAuth flow](../integrations/oauth).
* **PUT** (all providers) — supply credentials directly. Used by the manual key paths and by Webhook/ASC-write which don't have an OAuth flow.

## Providers

| Provider    | Required credentials                   | Config                |
| ----------- | -------------------------------------- | --------------------- |
| `slack`     | `webhookUrl` OR `botToken`+`channelId` | `defaultChannel`      |
| `linear`    | `apiKey`                               | `teamId`, `projectId` |
| `github`    | `token`                                | `owner`, `repo`       |
| `webhook`   | `url`                                  | `secret`              |
| `notion`    | `token`                                | `databaseId`          |
| `asc_write` | (none — uses existing ASC connection)  | (none)                |

## GET — list

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl https://api.appeeky.com/v1/cofounder/integrations -H "X-API-Key: $KEY"
```

Returns metadata only — **credentials are never exposed**:

```jsonc theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": {
    "integrations": [
      {
        "id": "uuid",
        "provider": "slack",
        "enabled": true,
        "config": { "defaultChannel": "#app-cofounder" },
        "last_used_at": "2026-05-02T08:00:13Z",
        "last_error": null,
        "created_at": "...",
        "updated_at": "...",
        // OAuth-managed integrations include extra metadata:
        "auth_method": "oauth",                    // "oauth" | "manual"
        "oauth_account_label": "Acme Workspace",   // shown in dashboards
        "oauth_external_id": "T012ABC",            // workspace/team/repo id
        "oauth_scope": "chat:write,channels:read,...",
        "oauth_expires_at": null                   // null = long-lived
      }
    ]
  }
}
```

## PUT — upsert

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X PUT https://api.appeeky.com/v1/cofounder/integrations/slack \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{
    "credentials": { "webhookUrl": "https://hooks.slack.com/services/..." },
    "integrationConfig": { "defaultChannel": "#app-cofounder" },
    "enabled": true
  }'
```

Body:

| Field               | Required                  | Description              |
| ------------------- | ------------------------- | ------------------------ |
| `credentials`       | Yes (per provider schema) | Object with credentials  |
| `integrationConfig` | No                        | Provider-specific config |
| `enabled`           | No, default `true`        | Disable without deleting |

Every PUT triggers a **connectivity test** against the provider before saving. If the test fails, the request returns `422 INTEGRATION_TEST_FAILED` and nothing is persisted.

## DELETE

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X DELETE https://api.appeeky.com/v1/cofounder/integrations/slack \
  -H "X-API-Key: $KEY"
```

Removes the row entirely. To temporarily disable, use PUT with `enabled: false` instead.

## Enabling integrations on the agent

Setting credentials is necessary but not sufficient. The integration is only used by the agent if it's listed in `preferences.enabledIntegrations`:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
PUT /v1/cofounder/preferences
{ "enabledIntegrations": ["slack", "linear", "notion"] }
```

This two-step (credentials + enable) lets you pre-provision integrations without immediately turning them on.

## Errors

* `400 INVALID_PROVIDER` — unknown provider
* `400 MISSING_CREDENTIAL` — required credential field absent
* `422 INTEGRATION_TEST_FAILED` — credentials are wrong or endpoint is unreachable

## OAuth flow (Slack, Linear, GitHub, Notion)

```
GET /v1/cofounder/oauth/:provider/start?return_to=<url>
   → 200 { authorizeUrl, state, expiresAt }   ← user opens authorizeUrl

GET /v1/cofounder/oauth/:provider/callback?code=...&state=...
   → 302 redirect to return_to with one of:
        ?cofounder_oauth=success&provider=…&account=…
        ?cofounder_oauth=denied&provider=…&error=…
        ?cofounder_oauth=error&provider=…&error=…
```

The `return_to` URL is validated against an allowlist of host prefixes (open-redirect guard). Defaults: `https://app.appeeky.com`, `https://api.appeeky.com`, `http://localhost`. Configure via `COFOUNDER_OAUTH_RETURN_TO_ALLOWLIST`.

After a successful callback the row in `cofounder_integrations` is upserted with:

* `auth_method = 'oauth'`
* `oauth_account_label`, `oauth_external_id`, `oauth_scope` populated from the provider
* `encrypted_credentials.accessToken` (and provider-specific aliases like `botToken` for Slack)

Re-running the OAuth flow for the same provider overwrites the row — useful when switching workspaces.

See [OAuth (recommended)](../integrations/oauth) for the full flow + frontend code example.

## Per-provider details

See the integration-specific docs:

* [OAuth (cross-provider)](../integrations/oauth)
* [Slack](../integrations/slack)
* [Linear](../integrations/linear)
* [GitHub](../integrations/github)
* [Webhook](../integrations/webhook)
* [Notion](../integrations/notion)
* [ASC write](../integrations/asc-write)
