Skip to main content

Issue and verify API keys

An issued API key is a credential that Ory Talos generates. The admin surface creates the key, returns the full secret once at creation, and stores only a hash afterward. Use issued keys when you want Ory Talos to own the full lifecycle — generation, lookup, rotation, and revocation — for the credentials your customers or services use to call your API. For how issued keys compare to imported keys and derived tokens, see credential types.

This guide walks through the issue-and-verify flow end to end. CI runs every example.

Prerequisites

You need a running Ory Talos server and the talos CLI. See the quickstart to start one locally.

Issue an API key

Send a request to the admin endpoint to create a key:

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')

Request fields

The required fields are name (human-readable label) and actor_id (the key's actor). scopes, ttl, metadata, and rate_limit_policy are optional. For the complete field reference, see the IssueAPIKey API reference.

Over the HTTP API, ttl accepts protobuf seconds (86400s), Go durations (720h, 1h30m), and extended units (1d, 1w, 1mo, 1y) including compounds such as 1y6mo. The CLI --ttl flag accepts Go durations only, 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, and timestamps).
  • secret — The full API key credential. Talos returns this value only once and never exposes it again. Store it securely.

For the complete issued_api_key field reference, see the IssueAPIKey API reference.

Verify a key

Send the secret to the admin verify endpoint to check whether the credential is valid:

talos keys verify "$API_SECRET" -e "$TALOS_URL"

Verification response

The response includes is_valid (true when verification succeeds), status (key lifecycle state), key_id, actor_id, scopes, metadata, and expire_time. When is_valid is false, error_code and error_message give the reason. With rate limit enforcement (Commercial), keys that have a rate limit policy also return rate_limit_remaining and rate_limit_reset_time. For the complete field reference, see the VerifyAPIKey API reference.

Verification error codes

When is_valid 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 exhausts its rate limit quota). For the complete list, see the verification error codes reference.

Cache bypass

Talos caches verification results. After revoking a key, bypass the cache to read its current state immediately:

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:

HeaderEffect
Cache-Control: no-cacheBypass cache read, force fresh DB lookup
Cache-Control: no-storeBypass both cache read and write
Pragma: no-cacheSame as no-cache (HTTP/1.0 compatibility)

Retrieve a key by ID

Look up key metadata without the secret:

talos keys issued get "$KEY_ID" -e "$TALOS_URL"

Talos never returns the secret from GET requests.

List keys

List all issued keys with optional filtering and pagination:

talos keys issued list --actor user_42 --page-size 10 -e "$TALOS_URL"

Query parameters

Pagination is cursor-based with page_size (default 50, max 1000) and page_token. Filtering uses an AIP-160 filter expression on the indexed fields actor_id and status, for example filter=actor_id="user_42" or filter=status=KEY_STATUS_ACTIVE. The CLI --actor and --status flags translate into the equivalent filter value. For the complete parameter reference, see the ListIssuedAPIKeys API reference.

The response includes next_page_token. When empty, you've reached the last page.

Next steps