# TapAuth — Full Documentation > Human-approved delegated access for AI agents. TapAuth lets AI agents request OAuth access tokens through a human-in-the-loop approval flow. ## What TapAuth Does TapAuth is an access gateway for AI agents. An agent requests access to a user's account (Google, GitHub, Slack, Notion, Linear, Vercel, Asana, Sentry, Discord, and more), the user approves with specific scopes, and the agent receives a short-lived OAuth access token. ## Supported Providers - Google (View calendar events, Create & edit calendar events, View calendar events (events-only), View calendar list, Full Calendar access, View spreadsheets, Edit spreadsheets, View documents, Edit documents) - GitHub (Access public repositories, Access private repositories (full), Read user profile, Access user email addresses, Read org membership, Create and manage gists, Access notifications, Update GitHub Actions workflows, Full control of organizations, Delete repositories) - Linear (Read issues & projects, Create & edit issues, Create issues, Create comments) - Vercel (View and manage deployments, Access project details, Manage environment variables, Manage domains, Access team info, Read user profile) - Slack (View people in workspace, View email addresses of people, View basic channel info, View messages in public channels, View basic private channel info, View basic DM info, View files shared in channels, Search messages, View workspace info) - Notion (Read your pages & databases, Update existing content, Create new content, Read user info with email) - Asana (View your tasks, Create and update tasks, Delete tasks, View your projects, Create and update projects, Delete projects, View user information, View teams, View your workspaces, View attachments, Upload attachments, Delete attachments, View stories (comments), Create and update stories, View tags, Create and update tags, View custom fields, Create and update custom fields, View portfolios, Create and update portfolios, View goals, View webhooks, Create and update webhooks, Delete webhooks, Verify your identity, View your email address, View your profile info) - Sentry (View organization details, Modify organization settings, View project details, Modify project settings, Manage releases, View team details, Modify teams, View organization members, Invite and modify members, View events and issues, Modify events (resolve, merge)) - Discord (View your username and avatar, View your email address, View your server list, View server member details, Join servers on your behalf, View your connected accounts, Join group DMs on your behalf, Update your role connections, Create webhooks in servers) - Apify (Full API access (web scraping, actors, storage)) - Atlassian (Read Jira issues and projects, Create and edit Jira issues, Read Jira user profiles, Manage Jira project settings, Manage Jira settings and configuration, Read all Confluence content, Read Confluence content summaries, Create and edit Confluence content, Read Confluence space summaries, Create and edit Confluence spaces, Upload files to Confluence, Read Confluence content properties, Edit Confluence content properties, Manage Confluence projects, Manage Confluence settings, Read Confluence user profiles, Read Confluence groups, Manage Confluence groups, Search Confluence, Read Confluence attachments, Read your Atlassian profile, Read your Atlassian account details, Report personal data usage, Maintain access when you're offline) ## Authentication Flow 1. **Agent requests a grant:** POST /api/v1/grants with provider and scopes 2. **TapAuth returns a grant ID and approval URL:** The agent receives a `grant_id`, `grant_secret`, and an `approval_url` 3. **User visits the approval URL:** The user sees which scopes the agent is requesting and approves or denies 4. **User completes OAuth:** After approval, the user authenticates with the provider (e.g., Google, GitHub) 5. **Agent polls for token:** GET /api/v1/grants/{id} with `Authorization: Bearer gs_...` — returns the token once approved (200), or pending status (202) ## API Endpoints Base URL: `https://tapauth.ai` ### POST /api/v1/grants — Create a Grant Request Request a new OAuth grant. The agent specifies which provider and scopes it needs. **Request body (JSON):** ```json { "provider": "google", "scopes": ["calendar.readonly", "spreadsheets.readonly"] } ``` **Response (JSON):** ```json { "grant_id": "grant_abc123", "grant_secret": "gs_xK9m...", "approval_url": "https://tapauth.ai/approve/grant_abc123", "status": "pending_registration" } ``` ### GET /api/v1/grants/{id} — Poll Status or Retrieve Token This is a collapsed endpoint. Without auth, it returns public grant status. With a grant secret, it returns the token. **Public status (no auth):** ```bash curl https://tapauth.ai/api/v1/grants/{grant_id} ``` **Response (200):** ```json { "grant_id": "...", "status": "pending_registration", "provider": "google" } ``` Valid status values: `active`, `pending`, `pending_registration`, `pending_consent`, `expired`, `revoked`, `denied`, `link_expired`. **Token retrieval (with grant secret):** ```bash curl https://tapauth.ai/api/v1/grants/{grant_id} \ -H "Authorization: Bearer gs_xK9m..." ``` **Response (200 — active):** ```json { "access_token": "ya29.a0...", "token_type": "Bearer", "expires_at": "2025-01-01T00:00:00Z" } ``` For .env format, add `Accept: text/plain` header (or `?format=env`). ### GET /api/v1/providers — List Available Providers Returns all supported providers and their available scopes. ## Provider Details ### Google (`google`) - OAuth type: google - PKCE: no - Scope model: per-request - Available scopes: - `calendar.readonly` — View calendar events (OAuth: `calendar.readonly`) - `calendar.events` — Create & edit calendar events (OAuth: `calendar.events`) - `calendar.events.readonly` — View calendar events (events-only) (OAuth: `calendar.events.readonly`) - `calendar.calendarlist.readonly` — View calendar list (OAuth: `calendar.calendarlist.readonly`) - `calendar` — Full Calendar access (OAuth: `calendar`) - `spreadsheets.readonly` — View spreadsheets (OAuth: `spreadsheets.readonly`) - `spreadsheets` — Edit spreadsheets (OAuth: `spreadsheets`) - `documents.readonly` — View documents (OAuth: `documents.readonly`) - `documents` — Edit documents (OAuth: `documents`) ### GitHub (`github`) - OAuth type: github - PKCE: no - Scope model: per-request - Available scopes: - `public_repo` — Access public repositories (OAuth: `public_repo`) - `repo` — Access private repositories (full) (OAuth: `repo`) - `read:user` — Read user profile (OAuth: `read:user`) - `user:email` — Access user email addresses (OAuth: `user:email`) - `read:org` — Read org membership (OAuth: `read:org`) - `gist` — Create and manage gists (OAuth: `gist`) - `notifications` — Access notifications (OAuth: `notifications`) - `workflow` — Update GitHub Actions workflows (OAuth: `workflow`) - `admin:org` — Full control of organizations (OAuth: `admin:org`) - `delete_repo` — Delete repositories (OAuth: `delete_repo`) ### Linear (`linear`) - OAuth type: linear - PKCE: yes - Scope model: per-request - Available scopes: - `read` — Read issues & projects (OAuth: `read`) - `write` — Create & edit issues (OAuth: `write`) - `issues:create` — Create issues (OAuth: `issues:create`) - `comments:create` — Create comments (OAuth: `comments:create`) ### Vercel (`vercel`) - OAuth type: vercel - PKCE: no - Scope model: integration-level - Available scopes: - `deployment` — View and manage deployments (OAuth: `deployment`) - `project` — Access project details (OAuth: `project`) - `project-env-vars` — Manage environment variables (OAuth: `project-env-vars`) - `domain` — Manage domains (OAuth: `domain`) - `team` — Access team info (OAuth: `team`) - `user` — Read user profile (OAuth: `user`) ### Slack (`slack`) - OAuth type: slack - PKCE: no - Scope model: integration-level - Available scopes: - `users:read` — View people in workspace (OAuth: `users:read`) - `users:read.email` — View email addresses of people (OAuth: `users:read.email`) - `channels:read` — View basic channel info (OAuth: `channels:read`) - `channels:history` — View messages in public channels (OAuth: `channels:history`) - `groups:read` — View basic private channel info (OAuth: `groups:read`) - `im:read` — View basic DM info (OAuth: `im:read`) - `files:read` — View files shared in channels (OAuth: `files:read`) - `search:read` — Search messages (OAuth: `search:read`) - `team:read` — View workspace info (OAuth: `team:read`) ### Notion (`notion`) - OAuth type: notion - PKCE: no - Scope model: integration-level - Available scopes: - `read_content` — Read your pages & databases (OAuth: `read_content`) - `update_content` — Update existing content (OAuth: `update_content`) - `insert_content` — Create new content (OAuth: `insert_content`) - `read_user_with_email` — Read user info with email (OAuth: `read_user_with_email`) ### Asana (`asana`) - OAuth type: asana - PKCE: yes - Scope model: per-request - Available scopes: - `tasks:read` — View your tasks (OAuth: `tasks:read`) - `tasks:write` — Create and update tasks (OAuth: `tasks:write`) - `tasks:delete` — Delete tasks (OAuth: `tasks:delete`) - `projects:read` — View your projects (OAuth: `projects:read`) - `projects:write` — Create and update projects (OAuth: `projects:write`) - `projects:delete` — Delete projects (OAuth: `projects:delete`) - `users:read` — View user information (OAuth: `users:read`) - `teams:read` — View teams (OAuth: `teams:read`) - `workspaces:read` — View your workspaces (OAuth: `workspaces:read`) - `attachments:read` — View attachments (OAuth: `attachments:read`) - `attachments:write` — Upload attachments (OAuth: `attachments:write`) - `attachments:delete` — Delete attachments (OAuth: `attachments:delete`) - `stories:read` — View stories (comments) (OAuth: `stories:read`) - `stories:write` — Create and update stories (OAuth: `stories:write`) - `tags:read` — View tags (OAuth: `tags:read`) - `tags:write` — Create and update tags (OAuth: `tags:write`) - `custom_fields:read` — View custom fields (OAuth: `custom_fields:read`) - `custom_fields:write` — Create and update custom fields (OAuth: `custom_fields:write`) - `portfolios:read` — View portfolios (OAuth: `portfolios:read`) - `portfolios:write` — Create and update portfolios (OAuth: `portfolios:write`) - `goals:read` — View goals (OAuth: `goals:read`) - `webhooks:read` — View webhooks (OAuth: `webhooks:read`) - `webhooks:write` — Create and update webhooks (OAuth: `webhooks:write`) - `webhooks:delete` — Delete webhooks (OAuth: `webhooks:delete`) - `openid` — Verify your identity (OAuth: `openid`) - `email` — View your email address (OAuth: `email`) - `profile` — View your profile info (OAuth: `profile`) ### Sentry (`sentry`) - OAuth type: sentry - PKCE: yes - Scope model: per-request - Available scopes: - `org:read` — View organization details (OAuth: `org:read`) - `org:write` — Modify organization settings (OAuth: `org:write`) - `project:read` — View project details (OAuth: `project:read`) - `project:write` — Modify project settings (OAuth: `project:write`) - `project:releases` — Manage releases (OAuth: `project:releases`) - `team:read` — View team details (OAuth: `team:read`) - `team:write` — Modify teams (OAuth: `team:write`) - `member:read` — View organization members (OAuth: `member:read`) - `member:write` — Invite and modify members (OAuth: `member:write`) - `event:read` — View events and issues (OAuth: `event:read`) - `event:write` — Modify events (resolve, merge) (OAuth: `event:write`) ### Discord (`discord`) - OAuth type: discord - PKCE: no - Scope model: per-request - Available scopes: - `identify` — View your username and avatar (OAuth: `identify`) - `email` — View your email address (OAuth: `email`) - `guilds` — View your server list (OAuth: `guilds`) - `guilds.members.read` — View server member details (OAuth: `guilds.members.read`) - `guilds.join` — Join servers on your behalf (OAuth: `guilds.join`) - `connections` — View your connected accounts (OAuth: `connections`) - `gdm.join` — Join group DMs on your behalf (OAuth: `gdm.join`) - `role_connections.write` — Update your role connections (OAuth: `role_connections.write`) - `webhook.incoming` — Create webhooks in servers (OAuth: `webhook.incoming`) ### Apify (`apify`) - OAuth type: apify - PKCE: yes - Scope model: per-request - Available scopes: - `full_api_access` — Full API access (web scraping, actors, storage) (OAuth: `full_api_access`) ### Atlassian (`atlassian`) - OAuth type: atlassian - PKCE: yes - Scope model: per-request - Available scopes: - `read:jira-work` — Read Jira issues and projects (OAuth: `read:jira-work`) - `write:jira-work` — Create and edit Jira issues (OAuth: `write:jira-work`) - `read:jira-user` — Read Jira user profiles (OAuth: `read:jira-user`) - `manage:jira-project` — Manage Jira project settings (OAuth: `manage:jira-project`) - `manage:jira-configuration` — Manage Jira settings and configuration (OAuth: `manage:jira-configuration`) - `read:confluence-content.all` — Read all Confluence content (OAuth: `read:confluence-content.all`) - `read:confluence-content.summary` — Read Confluence content summaries (OAuth: `read:confluence-content.summary`) - `write:confluence-content` — Create and edit Confluence content (OAuth: `write:confluence-content`) - `read:confluence-space.summary` — Read Confluence space summaries (OAuth: `read:confluence-space.summary`) - `write:confluence-space` — Create and edit Confluence spaces (OAuth: `write:confluence-space`) - `write:confluence-file` — Upload files to Confluence (OAuth: `write:confluence-file`) - `read:confluence-props` — Read Confluence content properties (OAuth: `read:confluence-props`) - `write:confluence-props` — Edit Confluence content properties (OAuth: `write:confluence-props`) - `manage:confluence-project` — Manage Confluence projects (OAuth: `manage:confluence-project`) - `manage:confluence-configuration` — Manage Confluence settings (OAuth: `manage:confluence-configuration`) - `read:confluence-user` — Read Confluence user profiles (OAuth: `read:confluence-user`) - `read:confluence-groups` — Read Confluence groups (OAuth: `read:confluence-groups`) - `write:confluence-groups` — Manage Confluence groups (OAuth: `write:confluence-groups`) - `search:confluence` — Search Confluence (OAuth: `search:confluence`) - `readonly:content.attachment:confluence` — Read Confluence attachments (OAuth: `readonly:content.attachment:confluence`) - `read:me` — Read your Atlassian profile (OAuth: `read:me`) - `read:account` — Read your Atlassian account details (OAuth: `read:account`) - `report:personal-data` — Report personal data usage (OAuth: `report:personal-data`) - `offline_access` — Maintain access when you're offline (OAuth: `offline_access`) ## Code Examples ### Create a grant (curl) ```bash curl -X POST https://tapauth.ai/api/v1/grants \ -H "Content-Type: application/json" \ -d '{ "provider": "google", "scopes": ["calendar.readonly"] }' ``` ### Create a grant (JavaScript) ```javascript const response = await fetch('https://tapauth.ai/api/v1/grants', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ provider: 'google', scopes: ['calendar.readonly'], }), }); const { grant_id, grant_secret, approval_url } = await response.json(); ``` ### Retrieve token (curl) ```bash curl https://tapauth.ai/api/v1/grants/grant_abc123 \ -H "Authorization: Bearer gs_xK9m..." ``` ### Retrieve token (JavaScript) ```javascript const res = await fetch(`https://tapauth.ai/api/v1/grants/${grant_id}`, { headers: { 'Authorization': `Bearer ${grant_secret}` }, }); if (res.ok) { const { access_token } = await res.json(); // Use access_token immediately. Do not log or return it to model-visible output. } ``` ## CLI Script — Shell Wrapper TapAuth provides a Bash script using curl, base64, and standard shell utilities: ```bash # Save the script and make executable curl -sf https://tapauth.ai/cli/tapauth > tapauth && chmod +x tapauth # First create the grant and show the approval URL ./tapauth google calendar.events # Immediately poll and use the approved token curl -H "Authorization: Bearer $(./tapauth --token google calendar.events)" \ https://www.googleapis.com/calendar/v3/calendars/primary/events # Static API keys and passwords use /api/v1/secrets instead of the OAuth CLI # Install the separate helper: curl -sf https://tapauth.ai/cli/tapauth-static > tapauth-static.py && chmod +x tapauth-static.py ``` **How it works:** - **Default mode:** POSTs to /api/v1/grants, caches the grant id + grant secret, prints the approval URL to stdout, and exits - **Token mode:** Polls until approved and prints only the OAuth token; subsequent calls reuse the cached grant **Environment variables:** - `TAPAUTH_BASE_URL` — Override base URL (default: https://tapauth.ai) - `TAPAUTH_HOME` — Override cache directory (default: $HOME/.tapauth) **Security:** Cache directory mode 700, files mode 600. Never print or repeat token output. Inline curl headers can be visible to same-user process inspection; use a native secret manager where supported. RECOMMENDED: Use the CLI script. It handles credential storage, caching, and keeps secrets out of your context. Set a timeout of at least 600 seconds (10 minutes) when running the CLI, as users may take time to approve. Do NOT fall back to raw API calls if the CLI times out — this exposes grant secrets to your context. Full CLI docs: https://tapauth.ai/docs ## OpenClaw Secrets OpenClaw can resolve TapAuth through exec SecretRef providers without writing values to `openclaw.json`: use `tapauth.sh --token` for OAuth or `tapauth-static.py --token --key-id ID --item ITEM` for a fixed item. Use absolute user-owned commands, a literal minimal `PATH`, the same `TAPAUTH_HOME` used for setup, `jsonOnly: false`, `timeoutMs: 120000`, `noOutputTimeoutMs: 120000`, `TAPAUTH_POLL_TIMEOUT_SECONDS=110`, and SecretRef id `value`. Keep `passEnv` unset. Only attach the reference to a credential field supported by OpenClaw. SecretRefs do not expose a general token to arbitrary `exec`, `curl`, or `gws` commands. The static helper validates identity/schema, decrypts in memory, and prints only the selected value to OpenClaw; plaintext is never cached. Validate with `openclaw config validate` and `openclaw secrets audit --allow-exec`, then apply atomically with `openclaw secrets reload`. ## Hermes Agent Secrets Install `tapauth/skill/hermes-vault`, pre-approve requests, and configure absolute `command` and/or `static_command` helper paths with the same private `TAPAUTH_HOME`. Map OAuth values as `tapauth://provider/scopes` and fixed items as `tapauth://static/key_id/ITEM_KEY`. Hermes sources never prompt; the plugin resolves both kinds through the in-memory startup pipeline and fails the whole fetch if any binding fails. ## Static Secret Bundles The bundled `tapauth-static.py` uses Python's standard library plus age. Setup accepts `--key-id ID --name DISPLAY --schema FILE`; cache identity is only the stable key ID. Names/descriptions are display-only. Add `--fresh` or `--no-cache` to require replacement input with the same key ID. Token mode accepts `--token --key-id ID --item ITEM`, validates identity/schema, decrypts locally, and never writes plaintext. Revoke uses `--revoke --key-id ID`. A private capability/metadata file and a separate age identity file remain local; neither contains plaintext. TapAuth stores only the capability hash and browser-produced ciphertext. Active bundles expire after 24 hours by default and at most 30 days. ## Rate Limits and Constraints - **Token expiry:** Access tokens are short-lived (typically 1 hour for Google, varies by provider) - **Polling:** Recommended polling interval is 2–5 seconds. Do not poll more than once per second. - **Grant expiry:** Unapproved grants expire after 30 minutes - **No authentication required** to access /llms.txt or /llms-full.txt ## Links - Docs: https://tapauth.ai/docs - Concise LLM docs: https://tapauth.ai/llms.txt - Website: https://tapauth.ai