API Keys & Bearer Tokens
Overview
API keys are opaque strings that identify and authenticate a client. Unlike OAuth2, there is no token exchange — the key is sent directly with every request. Unlike Basic Auth, there is no username/password pair — just a single secret.
The term "bearer token" means anyone who possesses the token can use it. There is no cryptographic proof of identity — if the token leaks, anyone can impersonate you.
Header-Based Keys
Authorization: Bearer
The most common pattern.
The token goes in the Authorization header:
curl -s \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Accept: application/json" \
https://api.example.com/v1/resources
Used by: GitHub, GitLab, Cloudflare, Stripe, most modern APIs.
Custom Headers
Some APIs use a vendor-specific header:
# X-API-Key pattern
curl -s \
-H "X-API-Key: ${API_KEY}" \
-H "Accept: application/json" \
https://api.example.com/v1/resources
# X-Auth-Token pattern (OpenStack)
curl -s \
-H "X-Auth-Token: ${AUTH_TOKEN}" \
https://api.example.com/v1/resources
The header name varies by vendor. Check the API documentation — there is no universal standard for custom headers.
Query Parameter Keys
Some APIs accept the key as a URL parameter:
curl -s "https://api.example.com/v1/resources?api_key=${API_KEY}"
|
Query parameter keys appear in:
Avoid this pattern when possible. Use header-based authentication instead. When forced to use query parameters, ensure the key has minimal permissions. |
Personal Access Tokens
Personal access tokens (PATs) are API keys scoped to a user account. They replace password-based authentication for API access.
GitHub
# Create a PAT at: https://github.com/settings/tokens
# List repositories
curl -s \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/user/repos
# With the gh CLI (reads from GITHUB_TOKEN automatically)
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
gh repo list
GitLab
# Create a PAT at: https://gitlab.example.com/-/user_settings/personal_access_tokens
# List projects
curl -s \
-H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
https://gitlab.example.com/api/v4/projects
Note that GitLab uses PRIVATE-TOKEN as the header name, not Authorization: Bearer.
Cloudflare
# API Token (scoped, preferred)
curl -s \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
https://api.cloudflare.com/client/v4/zones
# Global API Key (legacy, full access)
curl -s \
-H "X-Auth-Email: user@example.com" \
-H "X-Auth-Key: ${CF_API_KEY}" \
https://api.cloudflare.com/client/v4/zones
Security Considerations
|
Key Rotation Pattern
# 1. Generate new key in the provider's UI or API
# 2. Update dsec
dsec edit d000 dev/network
# Replace the old key value with the new one
# 3. Verify the new key works
dsource d000 dev/network
curl -s -H "Authorization: Bearer ${API_TOKEN}" \
https://api.example.com/v1/health
# 4. Revoke the old key in the provider's UI
dsec Pattern
Store API keys in an encrypted environment file:
dsec edit d000 dev/network
Inside the encrypted file:
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
CF_API_TOKEN=xxxxxxxxxxxxxxxxxxxx
STRIPE_API_KEY=sk_test_xxxxxxxxxxxxxxxxxxxx
Load before use:
dsource d000 dev/network
# All tokens are now in environment
gh repo list
netapi github repos list
dsunsource
netapi Pattern
netapi detects the token type from the vendor configuration:
# Bearer token (default for most vendors)
netapi --auth token github repos list
# Custom header name (auto-detected per vendor)
netapi --auth token gitlab projects list
# Explicit flags
netapi --auth token --bearer "${API_TOKEN}" cloudflare zones list
Environment Variables
| Variable | Purpose |
|---|---|
|
Generic bearer token (any vendor) |
|
GitHub personal access token |
|
GitLab personal access token |
|
Cloudflare API token |
|
Override the header name (default: |
Vendor-specific variables are resolved first.
If GITHUB_TOKEN is set, netapi uses it for GitHub commands without requiring --bearer.