Credential Setup Guides
For agents: enroll or link?
Most of this page is written for the human doing dashboard setup. If you’re an agent deciding how to get a credential into TAP, the choice isn’t preference — it’s determined by where the secret lives:
| Situation | Path |
|---|---|
The secret already exists on this machine (.env, ~/.aws, an env var) | Enroll — pipe it directly |
| A human still has to generate or fetch it (vendor dashboard, 1Password, a teammate) | Link — send them a setup link |
| Google / Microsoft — no pasteable secret exists, only a consent flow | Link (always) |
| Signing keys | Generate in-proxy (dashboard Signing Key template, or POST /app/users/{ext_id}/keys) — never enroll |
| The human isn’t at a terminal with the agent (web, phone) | Link |
Both doors are the same endpoint, POST /agent/credentials — sending a value enrolls; omitting it returns a prefilled link. Full request/response shapes, required fields, and every error code: API Reference → POST /agent/credentials.
Enrolling is not “the agent creates credentials.” It’s the agent enrolling a credential it already has access to — if an agent can cat .env, it already holds that key; enrolling moves it under TAP’s enforcement (host binding, per-request approval, audit) rather than handing the agent anything new. Piping the value from its source (an env var, a file) so it never enters the agent’s own context is the whole point — read it into a variable or print it first and that property is gone. TAP cannot verify this; only the agent knows whether it happened.
Enrollment does not weaken approval: an agent-enrolled credential requires human approval on every request by default, including reads. The human’s review moment is the credential’s first real use, not its creation.
Import from .env
If your keys already live in a .env file, skip the per-service setup: Credentials → Import from .env (also offered as the first step of onboarding).
- Paste the file (or pick it — it’s read locally in your browser, never uploaded as a file).
- TAP recognizes the secrets. ~25 well-known services are matched by env-var name and by the secret’s shape (
sk-ant-…→ Anthropic,ghp_…→ GitHub,xoxb-…→ Slack, …), so oddly-named vars still match.AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYand Twilio SID/token pairs collapse into single credentials. Config vars (DATABASE_URL,PORT, …) are skipped, and listed so you can see nothing was silently dropped. - Review. Each row shows an editable credential name and an allowed-hosts binding — the API host(s) the secret may be sent to, pre-filled for recognized services. This binding is enforced by the proxy: the secret can never be forwarded anywhere else.
- Unrecognized keys appear unchecked. On managed hosting, TAP asks an LLM to identify the service from the variable name alone (values are never sent) and pre-fills a host marked AI-suggested — verify. A wrong suggestion fails closed — the host binding means the worst case is a 403 until you correct it, never a leak. If no suggestion appears, type the host yourself: it’s the domain your code sends that key to.
- Import. Selected rows are created through the same API as the manual form; values are stored encrypted (in a hardware enclave on managed hosting). The description records provenance, e.g.
Imported from .env (OPENAI_API_KEY).
Once your agent uses TAP for these services, delete the raw keys from your .env — that’s the point.
The guides below are for services that need more than a pasted secret — OAuth flows, bundles, connectors.
Standard API Key
Select Standard API Key in the dashboard, give it a name, and paste the secret. TAP injects it into Authorization: Bearer by default.
Mercury
app.mercury.com/settings/tokens → Create API Token → Copy
Wise
wise.com/settings/api-tokens → Add new token → Full access → Copy
GitHub
github.com/settings/tokens → Generate new token (fine-grained) → Select repos and permissions → Copy
Slack
api.slack.com/apps → Create New App → OAuth & Permissions → Add scopes → Install to Workspace → Copy Bot User OAuth Token (xoxb-...)
Stripe
dashboard.stripe.com/apikeys → Reveal test/live secret key → Copy
OpenAI
platform.openai.com/api-keys → Create new secret key → Copy
Anthropic
console.anthropic.com/settings/keys → Create Key → Copy
Vercel
vercel.com/account/tokens → Create → Copy
Notion
notion.so/my-integrations → New integration → Copy Internal Integration Secret. Then share the relevant pages/databases with the integration.
SendGrid
app.sendgrid.com/settings/api_keys → Create API Key → Full Access or Restricted → Copy
Twilio
console.twilio.com → Account Info → Copy Auth Token. Use AccountSID:AuthToken as the secret value.
Cloudflare
dash.cloudflare.com/profile/api-tokens → Create Token → Copy
Custom
For APIs that authenticate with a non-standard header, or that require more than one secret, select Custom in the dashboard.
Non-standard auth headers
If the API uses a header other than Authorization: Bearer (e.g. X-Linear-Token), select Custom, enter the secret value, and add it under Custom Auth Headers in the advanced section:
X-Linear-Token: {value}TAP treats that header as a valid auth position and injects the secret automatically.
Multi-secret APIs (Datadog, and others)
Some APIs require two or more independent secrets in different headers. Enable the Multi-secret option and add one row per secret: the field name, the secret value, and the target header the API expects it in (from the API’s docs). That’s it — agents then use the credential exactly like a single-secret one (X-TAP-Credential: <name>), and TAP injects every field into its header automatically. No placeholder syntax needed.
Datadog
Datadog needs an API key (DD-API-KEY) and an Application key (DD-APPLICATION-KEY).
-
Get your keys at app.datadoghq.com/organization-settings/api-keys and app.datadoghq.com/personal-settings/application-keys
-
In the TAP dashboard → Credentials → + Add Credential
-
Enable the Multi-secret option and add two rows:
Field name Secret value Target header api_keyyour Datadog API key DD-API-KEYapp_keyyour Datadog Application key DD-APPLICATION-KEY -
Save — TAP injects both headers automatically on every request
Datadog’s console shows a Key ID next to each key. TAP does not use it — paste only the key values.
Pick your Datadog region. A Datadog key is valid on exactly one site, and each site has its own API host. The credential form shows a region dropdown for any vendor that operates several — choose the host matching the URL you see in the Datadog console, and TAP binds the credential to just that one. Getting it wrong returns 403 with a perfectly valid key, which reads like a bad credential and is not. The same picker appears for Plaid (production / sandbox / development) and PostHog (US / EU), which have the same one-key-one-region rule.
Site API host US1 — app.datadoghq.comapi.datadoghq.comUS3 api.us3.datadoghq.comUS5 api.us5.datadoghq.comAP1 api.ap1.datadoghq.comEU1 — app.datadoghq.euapi.datadoghq.euUS1-FED api.ddog-gov.comThe Holonym Foundation org is on US5. Separate Datadog accounts (Passport has its own) may be on a different site, so check per account rather than assuming.
Power users can still wire headers per-request with <CREDENTIAL:name.field> placeholders (see Proxy API), but it’s no longer required — the field→header mapping lives in the credential config.
AWS (SigV4)
AWS APIs use SigV4 signing. TAP signs every request automatically — no pre-signing needed.
- console.aws.amazon.com/iam → Users → Select user → Security credentials → Create access key → Copy Access Key ID and Secret Access Key
- In the TAP dashboard → + Add Credential → select AWS
- Enter your Access Key ID and Secret Access Key
- Region and Service are auto-detected from the target URL. You can override them if needed.
- Save — TAP signs requests with SigV4 automatically
OAuth 2.0 Client Credentials
For machine-to-machine APIs that use the OAuth 2.0 client credentials grant (Azure Resource Manager, Salesforce, Box, Okta, and others). TAP exchanges the credentials for a Bearer token on every request — the agent never sees the secret or the token.
Credential JSON
In the TAP dashboard → + Add Credential → OAuth 2.0 Client Credentials, enter:
| Field | Required | Description |
|---|---|---|
client_id | Yes | The application/client ID |
client_secret | Yes | The client secret |
token_url | Yes | The token endpoint URL |
scope | No | Space-separated scopes (some providers require this) |
Azure Resource Manager
- portal.azure.com → Azure Active Directory → App registrations → New registration → name it → Register
- Copy the Application (client) ID and Directory (tenant) ID
- Certificates & secrets → New client secret → copy the value immediately
- Subscriptions → your subscription → Access control (IAM) → Add role assignment → assign Reader (or higher) to the app
- In TAP, enter:
token_url:https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/tokenscope:https://management.azure.com/.default
Salesforce
- Setup → App Manager → New Connected App → enable OAuth → add scopes → Save
- Copy Consumer Key (
client_id) and Consumer Secret (client_secret) token_url:https://login.salesforce.com/services/oauth2/token
Google (OAuth 2.0)
For Gmail, Calendar, Drive, Sheets, and any Google API — including the Admin SDK (Directory, Reports) for Workspace administration and the full Google Cloud Platform surface (Service Usage, IAM, Compute, …).
TAP handles the OAuth 2.0 flow for you.
- In the TAP dashboard, click + Add Credential and select Google
- Check the permissions this credential should have. Gmail, Calendar, Drive, and Sheets are pre-selected; Contacts, Tasks, Workspace Admin (manage users, groups, and org units), Admin Reports (read-only audit/usage logs), and Google Cloud (full GCP API access) are opt-in
- Click Connect Google Account
- Sign in with the Google account you want the agent to access and grant permission
TAP stores the refresh token and handles token refresh automatically. Only the permissions you checked appear on Google’s consent screen — and the credential is permanently limited to them, so create separate credentials for separate jobs.
Keep all permissions checked on Google’s consent screen. Google lets you uncheck individual permissions during consent, but a credential missing some of its requested permissions would fail in confusing ways later — so TAP rejects partial grants and asks you to retry. If you don’t want a permission, deselect it in the TAP dashboard instead, before connecting.
Workspace Admin scopes only work if the connecting Google account holds an admin role, and they can manage your entire Workspace. Put them in a dedicated credential (separate from day-to-day Gmail/Drive) and consider requiring passkey approval in its policy. The same goes for Google Cloud — it grants whatever GCP IAM lets the connecting account do, project-wide.
Advanced: You can also paste a refresh token manually using the collapsible option in the credential form.
Google Cloud (Service Account)
For automation against Google Cloud: CI jobs, scheduled agents, infrastructure queries — anything that has to run without a human present.
Use this rather than the Google OAuth credential above whenever a human is not in the loop. A Google OAuth credential is tied to a person, and Google gates sensitive operations (enabling an API, changing IAM) behind reauthorization that expires within minutes. An agent will hit that wall and stop. A service account has no such flow: it authenticates with a signed assertion and keeps working.
Credential JSON
In the TAP dashboard → + Add Credential, set the connector to sidecar and paste the service account key JSON exactly as Google issues it:
{
"type": "service_account",
"project_id": "your-project",
"private_key_id": "…",
"private_key": "-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----\n",
"client_email": "your-sa@your-project.iam.gserviceaccount.com",
"token_uri": "https://oauth2.googleapis.com/token"
}TAP signs a short-lived JWT assertion with the key and exchanges it for an access token on each request. The key never leaves TAP and the agent never sees a token.
type must be exactly service_account — that field is how TAP tells this apart from a Google OAuth bundle.
Narrowing scope
By default the credential requests https://www.googleapis.com/auth/cloud-platform, which is everything the service account’s IAM roles allow. To narrow it, add a non-standard scopes field (space-delimited) to the JSON before pasting:
"scopes": "https://www.googleapis.com/auth/bigquery.readonly"Grant the service account the narrowest IAM roles that do the job, and bind the credential’s allowed_hosts to *.googleapis.com so it cannot be pointed elsewhere. Note that billing roles are granted on the billing account, which is a separate resource from the project.
Creating the key may be blocked. Many organizations set the org policy
constraints/iam.disableServiceAccountKeyCreation, which prevents downloading a key at all. If so, Workload Identity Federation is the alternative — it has no long-lived key to leak, and is tracked separately.
Failures here are configuration errors, not reauthorization ones. If a request fails with
gcp_service_account_mint_failed, check that the key is still active, that the service account holds the required IAM role, and that the target API is enabled on the project. There is no “reconnect” step for a service account.
X / Twitter
Use one TAP credential for X. It can hold:
- an X app Bearer Token for app-auth reads such as recent search and recent counts
- optional OAuth 1.0a account fields for user-context actions such as posting as an account
TAP chooses the auth mode per request. By default, read-like requests use the Bearer Token when present, while writes use OAuth 1.0a when present. If a read-like request gets a 401/403 from X and the same credential has OAuth 1.0a fields, TAP retries once with OAuth 1.0a. Agents should only use X-TAP-Auth-Mode: bearer or X-TAP-Auth-Mode: oauth1 as an escape hatch for a specific route.
The dashboard preset binds the credential to api.x.com so an agent cannot send it to an arbitrary host.
Step 1: Create a Twitter Developer App
- Go to the Twitter Developer Portal
- Create a new Project and App (or use an existing one)
- Add X API credits if the endpoint requires pay-per-usage access
- Copy the app Bearer Token from the app’s Keys and Tokens tab
- Optional: under User authentication settings, enable OAuth 1.0a with the access level your agent needs (Read, Read+Write, or Read+Write+DM)
Step 2: Get your credentials
For search/counts, collect:
- Bearer Token
For posting/user-context actions, also collect:
- Consumer Key (API Key)
- Consumer Secret (API Key Secret)
- Access Token
- Access Token Secret
If you change your app’s permissions, regenerate the access token.
Step 3: Add to TAP
- In the TAP dashboard, click + Add Credential and select X / Twitter
- Paste the Bearer Token and/or all four OAuth 1.0a values
- Click Create
Example recent search through TAP:
curl -X POST "$TAP_PROXY_URL/forward" \
-H "X-TAP-Key: $TAP_API_KEY" \
-H "X-TAP-Credential: x" \
-H "X-TAP-Target: https://api.x.com/2/tweets/search/recent?query=python%20lang%3Aen%20-is%3Aretweet&tweet.fields=created_at,public_metrics,author_id" \
-H "X-TAP-Method: GET"Recent counts also uses the same credential:
curl -X POST "$TAP_PROXY_URL/forward" \
-H "X-TAP-Key: $TAP_API_KEY" \
-H "X-TAP-Credential: x" \
-H "X-TAP-Target: https://api.x.com/2/tweets/counts/recent?query=python%20lang%3Aen%20-is%3Aretweet" \
-H "X-TAP-Method: GET"Telegram (Personal Account)
Lets agents read and send messages as a real Telegram user. The dashboard walks you through the setup — no scripts needed.
Step 1: Get API credentials
- Go to my.telegram.org/apps and log in with your phone number
- Create a new application (or use an existing one)
- Note the API ID (a number) and API Hash (a hex string)
Step 2: Open the Telegram wizard in TAP
In the TAP dashboard, click + Add Credential and select Telegram. A dedicated 3-step modal opens:
- Credentials — enter a credential name, optional description, your API ID and API Hash, then click Next
- Phone — enter the phone number registered to your Telegram account and click Send code; Telegram will send a code to your Telegram app
- Verify — enter the verification code. If your account has Two-Factor Authentication enabled, a password field appears — enter your 2FA password and click Connect
TAP generates and stores the session automatically.