### Key Changes of v2
* **New Domain:** API available at `api.unkey.com` instead of `api.unkey.dev`
* **Enhanced Caching:** Server-based infrastructure with improved caching mechanisms
* **Improved Invalidations:** Enhanced cache invalidation system across regions
* **Improved Developer Experience:** More consistent error handling and response formats
## What You Need to Change
The main changes you'll need to make when migrating:
* **Update your base URL** from `api.unkey.dev` to `api.unkey.com` (The SDKs do this automatically starting at v2.0.0)
* **Change response parsing** from direct responses to `response.data`
* **Handle new error format** with hierarchical error codes and request IDs
## Response Format Changes
All v2 responses now use a standardized envelope format with `meta` and `data` fields:
#### v1 Response Format
```json theme={"system"}
{
"valid": true,
"keyId": "key_123",
"name": "Production API Key"
}
```
#### v2 Response Format
```json theme={"system"}
{
"meta": {
"requestId": "req_abc123"
},
"data": {
"valid": true,
"keyId": "key_123",
"name": "Production API Key"
}
}
```
***
## Detailed Migration by Category
Choose the endpoint category you need to migrate:
## Per Key Analytics
Our per key analytics give you a deep dive into each individual key, giving usage data, key data and where the requests originated from. This data can be useful for finding your top users, and where verifications are coming from.
## Tags
You can add tags to verification requests to aggregate or filter data when querying.
For example you might want to add the path of your API as a tag: `path=/v1/my-path` and then later retrieve a breakdown of api key usage per unique path.
Unkey does not parse tags in any special way.
The only limitations are:
* Tags are strings.
* You can specify up to 10 tags per request.
* Each tag must be between (including) 1 and 128 characters.
That being said, having some structure for your tags could be benefitial for you.
A common theme is treating them as key-value pairs and specifying them with either a colon or equal-sign as delimiter.
```
key:value
key=value
```
Since Unkey does not know what API routes your user has called or which resources they interact with, we encourage you to record these in the tags.
Here's an example tags for a fictional blog API:
```json theme={"system"}
[
"path=/v1/posts.createPost",
"postId=post_1asofijqknslkfqWF",
"region=us-east-1",
"apiVersion=f8ad21bd", // a git sha of your deployment or semver
]
```
### Using tags
Tags can be added in the request body.
```bash Providing Tags {6-9} theme={"system"}
curl --request POST \
--url https://api.unkey.com/v2/keys.verifyKey \
--header 'Content-Type: application/json' \
--data '{
"key": "sk_1234",
"tags": [
"tag1",
"path=/v1/my-resource/123"
]
}'
```
### Querying tags
Tags can be used to filter and aggregate data in your analytics.
# Example
Source: https://unkey.com/docs/apis/features/authorization/example
RBAC in the almost-real world
Let's look at an example app for allowing your users to manage domains.
As part of the API, your users will be able to perform CRUD operations against domains or individual dns records.
Create them in your [dashboard](https://app.unkey.com/authorization/roles) too.
3. Select one of your existing keys by clicking on it
4. Scroll down to the `Roles` section if not visible.
You should now be on `/app/keys/key_auth_???/key_???`
You can connect a role to your key by clicking on the checkbox.
Let's give this key the `dns.manager` and `read-only` roles.
A toast message should come up in the lower corner when the action has been completed.
As you can see, now the key now contains 2 `roles` and 5 `permissions` shown just above the Roles section:
## Connecting roles to keys
1. In the sidebar, click on one of your APIs
2. In the breakcrumb navigation on the top click Reqests and then keys
3. Select one of your existing keys by clicking on it
4. Scroll down to the `Roles` section if not visible
You should now be on `/app/keys/key_auth_???/key_???`
You can connect a role to your key by clicking on the checkbox.
Let's give this key the `dns.manager` and `read-only` roles.
A toast message should come up in the lower corner when the action has been completed.
As you can see, now the key now contains 2 `roles` and 5 `permissions` shown just above the Roles section:
## Creating keys
When a user of your app creates a new key, you can attach zero, one or multiple previously created roles to the key.
```bash theme={"system"}
curl -XPOST \
--url https://api.unkey.com/v2/keys.createKey \
-H "Authorization: Bearer ${ROOT_KEY}" \
-H "Content-Type: application/json" \
-d '{
"apiId": "${API_ID}",
"roles": [
"role1", "role2", "role3"
]
}'
```
See [here](api-reference/v2/keys/create-api-key) for details.
# Verifying
Source: https://unkey.com/docs/apis/features/authorization/verifying
Verifying permissions through the API
Once a key is generated, you can verify it using the [verify](https://www.unkey.com/docs/api-reference/v2/keys/verify-api-key) endpoint. Our system verifies whether the key has the necessary permissions to perform the requested action(s). If the user's role grants the required permissions, the request is allowed to proceed; otherwise, access is denied.
# Overview
Source: https://unkey.com/docs/apis/introduction
Protect your public APIs
Unkey provides a simple feature rich API key management system. You can use Unkey to protect your public APIs with ease. Below is an example of implementing Unkey in your API.
# Event Types
Source: https://unkey.com/docs/audit-log/types
Available audit log event types
## Workspaces
Workspace actions that will create a new audit log item.
* `workspace.create` - A workspace is created.
* `workspace.update` - A workspace is updated.
## API
API actions that will create a new audit log item.
* `api.create` - An API is created.
* `api.update` - An API is updated.
* `api.delete` - An API is deleted.
## Keys
Key actions that will create a new audit log item.
* `key.create` - A key is created.
* `key.update` - A key is updated.
* `key.delete` - A key is deleted.
## Ratelimit
Ratelimit actions that will create a new audit log item.
### Ratelimit Namespace
* `ratelimitNamespace.update` - A ratelimit namespace is updated.
* `ratelimitNamespace.update` - A ratelimit namespace is updated.
* `ratelimitNamespace.delete` - A ratelimit namespace is deleted.
### Ratelimit Override
* `ratelimitOverride.create` - A ratelimit override is created.
* `ratelimitOverride.update` - A ratelimit override is updated.
## Role
Role actions that will create a new audit log item.
* `role.create` - A role is created.
* `role.update` - A role is updated.
* `role.delete` - A role is deleted.
## Permission
Permission actions that will create a new audit log item.
* `permission.create` - A permission is created.
* `permission.update` - A permission is updated.
* `permission.delete` - A permission is deleted.
## Authorization
Authorization actions that will create a new audit log item.
* `authorization.connect_role_and_permission` - A role and permission are connected
* `authorization.disconnect_role_and_permissions` - A role and permission are disconnected.
* `authorization.connect_role_and_key` - A role and key are connected.
* `authorization.disconnect_role_and_key` - A role and key are disconnected.
* `authorization.connect_permission_and_key` - A permission and key are connected.
* `authorization.disconnect_permission_and_key` - A permission and key are disconnected.
# Overview
Source: https://unkey.com/docs/concepts/identities/overview
Identities are a representations of a user, an org or a machine in your application.
Was verified: {{ wasVerified }}
## 2. Choose how you want to use Unkey
As soon as you create your account you will be asked to choose how you want to use Unkey. Your options are:
* **API Keys**: This is used for protecting your public API.
* **Ratelimiting**: This is global low latency ratelimiting for your application.
> You can of course use both, but for now we'll just choose API Keys.
## 3. Create your first API
Next we will get you to create your first API. This is the API that you will be protecting with Unkey. You can create as many APIs as you like, but for now we'll just create one.
## 4. Follow the Unkey tutorial
Next we will show you the basics of how to use Unkey. You can skip this step if you like, but we recommend you follow along.
## 5. Next Steps
You should get to know our [API reference](/api-reference/v2/auth), as you can add additonal fields to your request when issuing a key.
You can also check out the [Features](/apis/features/ratelimiting) section for more information on how to use Unkey.
# Ratelimiting
Source: https://unkey.com/docs/quickstart/onboarding/onboarding-ratelimiting
Get started with standalone ratelimiting
## 1. Create your Unkey account
The first step to using Unkey is to create an account. You can do this by visiting [app.unkey.com](https://app.unkey.com) or by clicking the Dashboard button in the top right of your screen.
## 2. Choose how you want to use Unkey
As soon as you create your account you will be asked to choose how you want to use Unkey. Your options are:
* **API Keys**: This is used for protecting your public API.
* **Ratelimiting**: This is global low latency ratelimiting for your application.
> You can of course use both, but for this choose Ratelimiting.
## 3. Follow the Unkey tutorial
Next we will show you the basics of how to use Unkey Ratelimiting. You can skip this step if you like, but we recommend you follow along.
## 4. Next Steps
You should get to know our [API reference](/api-reference/v2/overview), as you can add additonal fields to your request when ratelimiting endpoints.
# Bun
Source: https://unkey.com/docs/quickstart/ratelimiting/bun
Ratelimiting endpoints with Bun's http server
## Prerequisites
* Created your [Unkey account](https://app.unkey.com/auth/sign-up)
* Created an [Unkey root key](https://app.unkey.com/settings/root-keys) with `ratelimit.*.create_namespace` and `ratelimit.*.limit` permissions.
## Creating a bun server protected by Unkey
After selecting both permissions, click `Create New Key` at the bottom of the page and copy the generated key to your `.env` file.
For security reasons, this key can not be shown again. In case you lose it, you need to create a new one.
Enter the identifier to override, a custom limit and custom duration.
### Examples
| override | matches |
| --------------- | ---------------------------------- |
| `*@domain.com` | `1@domain.com`, `hello@domain.com` |
| `invite:*` | `invite:abc`, `invite:hello world` |
| `prefix*suffix` | `prefixhelloworldsuffix` |
# Delete Protection
Source: https://unkey.com/docs/security/delete-protection
Prevents an resource from being deleted when enabled.
# Delete Protection
Delete Protection is a safety feature that prevents accidental deletion of a resource. When enabled, it blocks all deletion attempts through both the dashboard and API.
## Overview
**Delete Protection** adds an extra layer of security by:
* Preventing accidental deletion of critical resources
* Requiring explicit confirmation to disable protection
* Blocking deletion attempts through both UI and API
## Supported Resources
Currently, Delete Protection is available for:
* APIs: Protect your API configurations and settings from accidental deletion
More resources will be added in future updates.
## Enabling API Delete Protection
1. Navigate to your API settings in the dashboard
2. Click "Enable Delete Protection"
3. Type the API name to confirm
4. Click "Enable API Delete Protection" to add protection
Once enabled, the API cannot be deleted until protection is explicitly disabled.
## Disabling API Delete Protection
1. Navigate to your API settings in the dashboard
2. Click "Disable Delete Protection"
3. Type the API name to confirm
4. Click "Disable API Delete Protection" to remove protection
## Resource Behavior
When Delete Protection is enabled:
* All deletion attempts are blocked
* The resource returns a `DELETE_PROTECTED` error
* The error includes a link to this documentation
### Example API Error Response
```json theme={"system"}
{
"error": {
"code": "DELETE_PROTECTED",
"docs": "https://unkey.com/docs/api-reference/errors/code/DELETE_PROTECTED",
"message": "api [apiId] is protected from deletions",
"requestId": "req_1234"
}
}
```
## Best Practices
1. **Enable for Production resources**: Always enable Delete Protection for resources in production
2. **Use for Critical resources**: Protect resources that contain important data or configurations
3. **Regular Review**: Periodically review protection status of your resources
4. **Team Communication**: Inform team members about protected resources
5. **Documentation**: Document which resources are protected and why
## Limitations
* Delete Protection only prevents deletion of the resource
* It does not prevent modifications to the resource
* It does not prevent deletion of children of a resource, like keys or ratelimits that belong to a protected resource
* Protection can be disabled by any user with appropriate permissions
## Related Errors
* [DELETE\_PROTECTED](https://www.unkey.com/docs/api-reference/errors/code/DELETE_PROTECTED) - Returned when attempting to delete a protected API
# GitHub Secret Scanning
Source: https://unkey.com/docs/security/github-scanning
How Unkey protects you from leaked root keys
Unkey has partnered with GitHub to scan repositories for leaked keys.
GitHub Secret Scanning uses regular expressions to scan repositories for keys matching Unkey root keys. If a key is found, GitHub will notify Unkey, and we will validate the key and notify users via email. To ensure the production environment remains up and running, we do not disable the key.
This is a service that is automatic and requires nothing from you to function. However, outside of GitHub, we will not be able to inform you if a key has leaked.
Learn more: [GitHub Secret Scanning](https://docs.github.com/en/code-security/secret-scanning)
## Sources Scanned
* content
* commit
* pull\_request\_title
* pull\_request\_description
* pull\_request\_comment
* issue\_title
* issue\_description
* issue\_comment
* discussion\_title
* discussion\_body
* discussion\_comment
* commit\_comment
* gist\_content
* gist\_comment
* npm
* unknown
# Overview
Source: https://unkey.com/docs/security/overview
How does Unkey work? What security measures are in place?
## Why is Unkey secure? What makes it secure?
Unkey is secure because we never store the API Key in our database. Instead we store a hash of the API Key. This means that even if our database is compromised, your API Keys are safe. You should follow a similar pattern in your own applications by providing the API key to your user and not storing it in your database either.
We manage the keys by using the unique id that each key is given when it is created. This id allows you as developer to update or delete the key, but this id cannot be used to verify the key.
## Where are API keys stored?
We don't store API Keys, we store a hash of the API Key (sha256). This is then stored in our database. When you attempt to verify the API Key, we hash the API Key you provide and compare it to the hash we have stored. If they match, then the API Key is valid.
# Recovering Keys
Source: https://unkey.com/docs/security/recovering-keys
Show keys again after they are created
Best practice is to create a key, show it to your users and never store it yourself. If the user loses the key, they can create a new one. This way you don't have to worry about storing the key securely.
Without recovery, we would generate a new key and only store a hash of it. This way we can check if the key is correct but nobody, not even someone with access to the database, can recover the key.
However there are some reasons why you might want to recover keys and show them again.
* API playgrounds that need the key to call an API
* Better DX for your users, it's annoying to create a new key and update it everywhere
## Vault
Vault is our secure storage for secrets, such as keys. It follows a few principles:
* Secrets are encrypted at rest
* A leak of vaults data does not expose secrets
* A leak of the main database does not expose secrets
* A leak of the main encryption keys does not expose secrets
An attacker would need access to the vault, the main database and the main encryption keys to decrypt the secrets.
In order to make this even harder, we rotate the encryption keys regularly and do not run vault on the same servers as the main database to prevent an attacker from getting access to all the required information at once.
To learn more about how it works under the hood, you can head over to our [engineering docs](https://engineering.unkey.dev/services/vault).
## Opting in
By default we only store key hashes, not encrypted keys.
If you want us to store keys in a way that we can recover them, you need to opt in: