Create API key
Create a new API key for user authentication and authorization.
Use this endpoint when users sign up, upgrade subscription tiers, or need additional keys. Keys are cryptographically secure and unique to the specified API namespace.
Important: The key is returned only once. Store it immediately and provide it to your user, as it cannot be retrieved later.
Common use cases:
- Generate keys for new user registrations
- Create additional keys for different applications
- Issue keys with specific permissions or limits
Required Permissions
Your credential needs one of:
api.*.create_key(create keys in any API)api.<api_id>.create_key(create keys in specific API)unkey:v1:<workspace_id>:keyspaces/*#create_key(create keys in any keyspace)unkey:v1:<workspace_id>:keyspaces/<keyspace_id>#create_key(create keys in a specific keyspace)
Authorization
Body
application/jsonThe API namespace this key belongs to.
Keys from different APIs cannot access each other.
Length: 3–255Pattern: ^[a-zA-Z0-9_]+$
Adds a visual identifier to the beginning of the generated key for easier recognition in logs and dashboards.
The prefix becomes part of the actual key string (e.g., prod_xxxxxxxxx).
Avoid using sensitive information in prefixes as they may appear in logs and error messages.
Length: 1–16Pattern: ^[a-zA-Z0-9_]+$
Sets a human-readable identifier for internal organization and dashboard display.
Never exposed to end users, only visible in management interfaces and API responses.
Avoid generic names like "API Key" when managing multiple keys for the same user or service.
Length: 1–255
Controls the cryptographic strength of the generated key in bytes.
Higher values increase security but result in longer keys that may be more annoying to handle.
The default 16 bytes provides 2^128 possible combinations, sufficient for most applications.
Consider 32 bytes for highly sensitive APIs, but avoid values above 64 bytes unless specifically required.
Default: 16
Range: 16–255
Links this key to a user or entity in your system using your own identifier.
Returned during verification to identify the key owner without additional database lookups.
Essential for user-specific analytics, billing, and multi-tenant key management.
Use your primary user ID, organization ID, or tenant ID for best results.
Accepts letters, numbers, underscores, dots, and hyphens for flexible identifier formats.
Length: 1–255Pattern: ^[a-zA-Z0-9_.-]+$
Stores arbitrary JSON metadata returned during key verification for contextual information.
Eliminates additional database lookups during verification, improving performance for stateless services.
Avoid storing sensitive data here as it's returned in verification responses.
Large metadata objects increase verification latency and should stay under 10KB total size.
Assigns existing roles to this key for permission management through role-based access control.
Roles must already exist in your workspace before assignment.
During verification, all permissions from assigned roles are checked against requested permissions.
Roles provide a convenient way to group permissions and apply consistent access patterns across multiple keys.
Items: max 100
Grants specific permissions directly to this key without requiring role membership.
Wildcard permissions like documents.* grant access to all sub-permissions including documents.read and documents.write.
Direct permissions supplement any permissions inherited from assigned roles.
Items: max 1000
Sets when this key automatically expires as a Unix timestamp in milliseconds.
Verification fails with code=EXPIRED immediately after this time passes.
Omitting this field creates a permanent key that never expires.
Avoid setting timestamps in the past as they immediately invalidate the key.
Keys expire based on server time, not client time, which prevents timezone-related issues.
Essential for trial periods, temporary access, and security compliance requiring key rotation.
Range: 0–4102444800000
Show child attributesHide child attributes
Range: 0–9223372036854776000
Show child attributesHide child attributes
Range: 1–9223372036854776000
Day of the month for monthly refills (1-31).
Only required when interval is 'monthly'.
For days beyond the month's length, refill occurs on the last day of the month.
Range: 1–31
Defines time-based rate limits that protect against abuse by controlling request frequency.
Unlike credits which track total usage, rate limits reset automatically after each window expires.
Multiple rate limits can control different operation types with separate thresholds and windows.
Essential for preventing API abuse while maintaining good performance for legitimate usage.
Items: max 50
Show child attributesHide child attributes
The name of this rate limit. This name is used to identify which limit to check during key verification.
Best practices for limit names:
- Use descriptive, semantic names like 'api_requests', 'heavy_operations', or 'downloads'
- Be consistent with naming conventions across your application
- Create separate limits for different resource types or operation costs
- Consider using namespaced names for better organization (e.g., 'files.downloads', 'compute.training')
You will reference this exact name when verifying keys to check against this specific limit.
Length: 3–128
The maximum number of operations allowed within the specified time window.
When this limit is reached, verification requests will fail with code=RATE_LIMITED until the window resets. The limit should reflect:
- Your infrastructure capacity and scaling limitations
- Fair usage expectations for your service
- Different tier levels for various user types
- The relative cost of the operations being limited
Higher values allow more frequent access but may impact service performance.
Range: >= 1
The duration for each ratelimit window in milliseconds.
This controls how long the rate limit counter accumulates before resetting. Common values include:
- 1000 (1 second): For strict per-second limits on high-frequency operations
- 60000 (1 minute): For moderate API usage control
- 3600000 (1 hour): For less frequent but costly operations
- 86400000 (24 hours): For daily quotas
Shorter windows provide more frequent resets but may allow large burst usage. Longer windows provide more consistent usage patterns but take longer to reset after limit exhaustion.
Range: >= 1000
Default: false
Controls whether the key is active immediately upon creation.
When set to false, the key exists but all verification attempts fail with code=DISABLED.
Useful for pre-creating keys that will be activated later or for keys requiring manual approval.
Most keys should be created with enabled=true for immediate use.
Default: true
Controls whether the plaintext key is stored in an encrypted vault for later retrieval.
When true, allows recovering the actual key value using keys.getKey with decrypt=true.
When false, the key value cannot be retrieved after creation for maximum security.
Only enable for development keys or when key recovery is absolutely necessary.
Default: false
Responses
requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
The full generated API key that should be securely provided to your user.
SECURITY WARNING: This is the only time you'll receive the complete key - Unkey only stores a securely hashed version. Never log or store this value in your own systems; provide it directly to your end user via secure channels. After this API call completes, this value cannot be retrieved again (unless created with recoverable=true).
requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).Show child attributesHide child attributes
JSON path indicating exactly where in the request the error occurred. This helps pinpoint the problematic field or parameter. Examples include:
- 'body.name' (field in request body)
- 'body.items[3].tags' (nested array element)
- 'path.apiId' (path parameter)
- 'query.limit' (query parameter)
Use this location to identify exactly which part of your request needs correction.
requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).requestId is particularly important when troubleshooting issues with the Unkey support team.Show child attributesHide child attributes
Show child attributesHide child attributes
400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).