Issue and verify API keys
This guide walks through the full lifecycle of issuing an API key and verifying it. All examples are executable and tested in CI.
Prerequisites
A running Talos server and the talos CLI. See the quickstart to start one locally.
Issue an API key
Send a request to the admin plane to create a new key:
- CLI
- curl
RESPONSE=$(talos keys issue "backend-service" \
--actor user_42 \
--scopes "read:orders,write:orders" \
--ttl 720h \
--metadata '{"team": "payments", "environment": "staging"}' \
--format json \
-e "$TALOS_URL" 2>/dev/null)
echo "$RESPONSE" | jq .
export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
-H "Content-Type: application/json" \
-d '{
"name": "backend-service",
"actor_id": "user_42",
"scopes": ["read:orders", "write:orders"],
"ttl": "720h",
"metadata": {"team": "payments", "environment": "staging"}
}')
echo "$RESPONSE" | jq .
export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
export KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
Request fields
The key fields are name (human-readable label), actor_id (key actor), and optional scopes, ttl, metadata, and
rate_limit_policy. For the complete field reference, see the
IssueAPIKey API reference.
For HTTP API requests, ttl also accepts extended formats such as 1y, 1mo, 1w, 1d, and compounds like 1y6mo. The
current CLI --ttl flag examples still use standard Go durations such as 720h and 1h30m.
Response fields
The response contains two top-level fields:
issued_api_key— The key metadata (ID, name, actor, scopes, status, timestamps).secret— The full API key credential. This value is returned only once and cannot be retrieved later. Store it securely.
For the complete metadata field reference, see the IssueAPIKey API reference.
Verify a key
Send the secret to the data plane to check whether a credential is valid:
- CLI
- curl
talos keys verify "$API_SECRET" -e "$TALOS_URL"
curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
-H "Content-Type: application/json" \
-d "{\"credential\":\"$API_SECRET\"}" | jq .
Verification response
The response includes is_active (boolean), key_id, actor_id, issuer, scopes, metadata, and expire_time when valid.
When is_active is false, error_code and error_message indicate the reason. When rate limit enforcement is enabled
(Commercial), the response also includes rate_limit_remaining and rate_limit_reset_time for keys with a rate limit policy. For
the complete field reference, see the VerifyAPIKey API reference.
Verification error codes
When is_active is false, the error_code field indicates why. Common codes include VERIFICATION_ERROR_EXPIRED,
VERIFICATION_ERROR_REVOKED, VERIFICATION_ERROR_NOT_FOUND, and VERIFICATION_ERROR_RATE_LIMITED (Commercial, when the key's
rate limit quota is exhausted). For the complete list, see the
verification error codes reference.
Cache bypass
Verification results are cached for performance. After revoking a key, you can bypass the cache for immediate consistency:
curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
-H "Content-Type: application/json" \
-H "Cache-Control: no-cache" \
-d '{"credential":"sk_..."}'
Cache control headers:
| Header | Effect |
|---|---|
Cache-Control: no-cache | Bypass cache read, force fresh DB lookup |
Cache-Control: no-store | Bypass both cache read and write |
Pragma: no-cache | Same as no-cache (HTTP/1.0 compatibility) |
Retrieve a key by ID
Look up key metadata without the secret:
- CLI
- curl
talos keys issued get "$KEY_ID" -e "$TALOS_URL"
curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" | jq .
The secret is never returned from GET requests.
List keys
List all issued keys with optional filtering and pagination:
- CLI
- curl
talos keys issued list --actor user_42 --page-size 10 -e "$TALOS_URL"
curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys?page_size=10&actor_id=user_42" | jq .
Query parameters
Key parameters are page_size, page_token (cursor-based pagination), actor_id, and status (filtering). For the complete
parameter reference, see the ListIssuedAPIKeys API reference.
The response includes a next_page_token field. When empty, you have reached the last page.
Next steps
- Key lifecycle — update, rotate, and revoke keys
- Import keys — bring existing keys into Talos
- Derive tokens — mint short-lived JWTs or macaroons
- Error handling — error response format and retry logic
