Source: https://crabglamp.com/docs/app-integrations/reference
Last updated: 2026-06-09
Type: reference

This is the catalog for the App integrations surface. For an end-to-end walkthrough, see the Tutorial.

## Supported providers and scopes

<table>
  <thead>
    <tr><th>Provider</th><th>Scopes</th><th>Picker</th><th>Access token TTL</th></tr>
  </thead>
  <tbody>
    <tr>
      <td>Google</td>
      <td>Always <code>openid email profile</code>; optional per connection: Gmail (send), Calendar, Sheets, Docs, Contacts, Drive (per-file <code>drive.file</code>)</td>
      <td>Yes</td>
      <td>~1 hour</td>
    </tr>
    <tr>
      <td>GitHub</td>
      <td>Fixed: <code>repo</code>, <code>user</code>, <code>read:org</code></td>
      <td>No</td>
      <td>Long-lived (auto-revoked after ~1 year idle)</td>
    </tr>
    <tr>
      <td>Spotify</td>
      <td>Fixed: profile + email, playlist read/modify (public &amp; private), playback read/control, recently-played, top tracks</td>
      <td>No</td>
      <td>~1 hour</td>
    </tr>
  </tbody>
</table>

Google omits broad Drive scopes (`drive`, `drive.readonly`) on purpose — only the per-file `drive.file` scope is offered, so requesting a broad Drive scope is rejected.

Refresh tokens are stored encrypted at rest (AES-256-GCM). The plaintext is never logged, never returned via the API, and never seen by Agents.

## API endpoints

### GET /api/apps/providers

Returns the provider registry (env vars, tool/skill install commands, example commands). Used by the on-VM CLI to discover available providers and their scope catalogs. Dual auth (Clerk or HMAC). Strips OAuth URLs, secrets, and dashboard-only fields. `Cache-Control: private, max-age=300`.

Response 200 (one entry per provider):

```json
[
  {
    "provider": "google",
    "displayName": "Google Workspace",
    "description": "Gmail, Calendar, Sheets, Docs, Contacts",
    "envVar": "GOG_ACCESS_TOKEN",
    "accountEnvVar": "GOG_ACCOUNT",
    "tool": { "name": "gog", "installCmd": "…", "checkCmd": "command -v gog" },
    "exampleCommand": "gog gmail search 'newer_than:7d' --max 10",
    "tokenLifetime": "~1 hour",
    "scopeLabels": {
      "https://www.googleapis.com/auth/gmail.send": "Gmail (send only)",
      "https://www.googleapis.com/auth/calendar": "Google Calendar"
    }
  }
]
```

### GET /api/apps/authorize

Start the OAuth flow. Clerk-only (all flows originate from the dashboard popup). Query params: `provider=google|github|spotify`, `scopes` (comma-separated), `accountId` (optional, for org context). Generates a one-time state nonce + PKCE challenge and **302-redirects** to the provider's consent screen — there is no JSON response body.

### GET /api/apps/callback

OAuth callback. No Clerk auth — the one-time state nonce in the query string is the auth (single-use). CrabGlamp exchanges the code using the stored PKCE verifier, reads your email and scopes, saves the connection, and returns a popup-closing page that signals the dashboard to refresh.

### GET /api/apps/[id]/token

Fetch a fresh access token for the connection. CrabGlamp returns the cached token if it is still valid, or refreshes it against the provider first (10-second timeout). Concurrent calls for the same connection are serialized so they can't race. Returns:

```json
{
  "accessToken": "ya29.…",
  "expiresAt": "2026-05-15T13:00:00Z",
  "provider": "google",
  "providerSubject": "…",
  "providerAccountId": "…",
  "providerAccountName": "you@example.com",
  "scopes": ["openid", "email", "profile"]
}
```

Status codes:
- `200` — fresh token returned.
- `410 Gone` — body `{ "error": "connection_error" }`. The refresh token is dead; the connection is marked `error`. Re-authorize from the dashboard.
- `503` — body `{ "error": "refresh_unavailable" }`. A transient provider error or a platform-side OAuth misconfiguration; the connection stays `active` so the next request can retry.

### DELETE /api/apps/[id]

Revoke the connection. CrabGlamp best-effort revokes the refresh token at the provider, then removes the connection.

## CLI

On-VM CLI for App integrations:

<table>
  <thead>
    <tr><th>Command</th><th>Purpose</th></tr>
  </thead>
  <tbody>
    <tr><td><code>crabglamp apps providers</code></td><td>List available providers and their scope catalogs</td></tr>
    <tr><td><code>crabglamp apps &lt;provider&gt;</code></td><td>Configure a connected provider on this Agent — writes the access token to its env var (e.g. <code>$GOG_ACCESS_TOKEN</code>)</td></tr>
    <tr><td><code>crabglamp apps refresh &lt;provider&gt;</code></td><td>Refresh the access token for a provider and update its env var</td></tr>
    <tr><td><code>crabglamp apps list</code></td><td>List configured connections on this Agent</td></tr>
  </tbody>
</table>

## Limits

<table>
  <thead>
    <tr><th>Limit</th><th>Value</th></tr>
  </thead>
  <tbody>
    <tr><td>Refresh fetch timeout</td><td>10 seconds</td></tr>
    <tr><td>Authorization window</td><td>10 minutes</td></tr>
    <tr><td>Encryption</td><td>AES-256-GCM at rest</td></tr>
  </tbody>
</table>
