Skip to main content
Verify an API key’s validity and permissions for request authentication. Use this command on every incoming request to your protected resources. It checks key validity, permissions, rate limits, and usage quotas in a single call. Important: Returns HTTP 200 for all verification outcomes — check the valid field in response data to determine if the key is authorized. A 429 may be returned if the workspace exceeds its API rate limit. Required permissions: Your root key needs one of:
  • api.*.verify_key (verify keys in any API)
  • api.<api_id>.verify_key (verify keys in specific API)
Note: If your root key has no verify permissions at all, you will receive a 403 Forbidden error. If your root key has verify permissions for a different API than the key you’re verifying, you will receive a 200 response with code: NOT_FOUND to avoid leaking key existence.
See the API reference for the full HTTP endpoint documentation.

Usage

unkey api keys verify-key [flags]

Flags

--key
string
required
The API key to verify, exactly as provided by your user. Include any prefix — even small changes will cause verification to fail.
--tags
string[]
Metadata tags for analytics in key=value format. Attaches metadata for analytics and monitoring without affecting verification outcomes. Enables segmentation of API usage in dashboards by endpoint, client version, region, or custom dimensions. Avoid including sensitive data in tags as they may appear in logs and analytics reports.
--permissions
string
Permission query to check, supports AND/OR operators and parentheses for grouping. Examples: "documents.read", "documents.read AND documents.write", "(documents.read OR documents.write) AND users.view". Verification fails if the key lacks the required permissions through direct assignment or role inheritance.
--credits-json
string
JSON object for credit consumption configuration. Controls credit deduction for usage-based billing and quota enforcement. Omitting this field uses the default cost of 1 credit per verification.
--ratelimits-json
string
JSON array of rate limit checks to enforce during verification. Omitting this field skips rate limit checks entirely, relying only on configured key rate limits. Multiple rate limits can be checked simultaneously, each with different costs and temporary overrides.
--migration-id
string
Migration provider ID for on-demand key migration from your previous system. Reach out for migration support at support@unkey.dev.

Global Flags

FlagTypeDescription
--root-keystringOverride root key ($UNKEY_ROOT_KEY)
--api-urlstringOverride API base URL (default: https://api.unkey.com)
--configstringPath to config file (default: ~/.unkey/config.toml)
--outputstringOutput format — use json for raw JSON

Examples

unkey api keys verify-key --key=sk_1234abcdef

Output

Default output shows the request ID with latency, followed by the verification result:
req_2c9a0jf23l4k567 (took 32ms)

{
  "valid": true,
  "code": "VALID",
  "keyId": "key_1234abcd",
  "name": "user-dashboard-key",
  "enabled": true,
  "permissions": ["documents.read", "documents.write", "users.view"],
  "roles": ["editor"],
  "credits": 950,
  "expires": 1735689600000
}
With --output=json, the full response envelope is returned:
{
  "meta": {
    "requestId": "req_2c9a0jf23l4k567"
  },
  "data": {
    "valid": true,
    "code": "VALID",
    "keyId": "key_1234abcd",
    "name": "user-dashboard-key",
    "enabled": true,
    "permissions": ["documents.read", "documents.write", "users.view"],
    "roles": ["editor"],
    "credits": 950,
    "expires": 1735689600000,
    "meta": {
      "userId": "user_12345",
      "plan": "premium"
    }
  }
}
When verification fails, the valid field is false and code indicates the reason:
{
  "meta": {
    "requestId": "req_def456ghi789"
  },
  "data": {
    "valid": false,
    "code": "EXPIRED",
    "keyId": "key_5678efgh",
    "name": "temporary-access-key",
    "enabled": true,
    "expires": 1704067200000
  }
}
Possible code values: VALID, NOT_FOUND, FORBIDDEN, INSUFFICIENT_PERMISSIONS, USAGE_EXCEEDED, RATE_LIMITED, DISABLED, EXPIRED.
Last modified on March 26, 2026