### 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.
3. On the key you want to use, click on the action menu (`...`) at the end of that table row.
4. Select `Manage roles and permissions..`
5. You can connect a role to your key by using the `Assign role` input. Let's give this key the `dns.manager` and `read-only` roles.
As you can see, 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 sub menu, click on Keys.
3. Select one of your existing keys by clicking the action menu (`...`) to the right of the key.
4. Select the `Manage roles and Permissions...` option.
5. Select a `role` or `permission` from appropriate input.
6. Click `Update key`.
## 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.
# More Details
To see the details of an audit log, click on the row to display the details panel for that event. This will show you the full request and response payloads, as well as any errors that occurred.
# Feature requests
Need additional functionality from audit logs, beyond what is provided currently? [Get in touch](mailto:support@unkey.dev)!
# 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.
* `workspace.delete` - A workspace is deleted.
* `workspace.opt_in` - A workspace was opted into a feature.
## 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.
* `key.reroll` - A key is rerolled.
### Ratelimit Namespace
Ratelimit Namespace actions that will create a new audit log item.
* `ratelimitNamespace.create` - A ratelimit namespace is created.
* `ratelimitNamespace.update` - A ratelimit namespace is updated.
* `ratelimitNamespace.delete` - A ratelimit namespace is deleted.
### Ratelimit
Ratelimit actions that will create a new audit log item.
* `ratelimit.create` - A ratelimit is created.
* `ratelimit.update` - A ratelimit is updated.
* `ratelimit.delete` - A ratelimit is deleted.
* `ratelimit.set_override` - A ratelimit override is set.
* `ratelimit.read_override` - A ratelimit override is read.
* `ratelimit.delete_override` - A ratelimit override is deleted.
## 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.
## Webhook
Webhook actions that will create a new audit log item.
* `webhook.create` - A webhook is created.
* `webhook.update` - A webhook is updated.
* `webhook.delete` - A webhook is deleted.
## Identity
Identity actions that will create a new audit log item.
* `identity.create` - An identity is created.
* `identity.update` - An identity is updated.
* `identity.delete` - An identity is deleted.
# 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 }}
* The apiId can be found in the upper right corner after navigating to `APIs/
* Create a `Root Key` under the Settings menu. It will need the `api.*.create_key` permission or `api.
* Email us to get a `migrationId` at [support@unkey.dev](mailto:support@unkey.dev) with:
* Your workspace ID.
* What service the keys will be migrated from.
Extracting keys from your current system is likely the hardest part. It depends on how your keys are stored and how you can access them.
Some providers have APIs to list all keys, while others require you to manually export them.
You will need to provide the hash of your keys, as well as other settings to Unkey via the [keys.migrateKeys](/api-reference/v2/keys/migrate-api-keys) endpoint.
## Node.js Example
```js theme={"system"}
const { createHash } = require("node:crypto")
function hash(key) {
return {
value: createHash("sha256").update(key).digest("base64"),
variant: "sha256_base64",
}
}
const request = {
migrationId: "
## 2. 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.
Give it a name and add the features you need. You can always add and remove features from the dashboard later as needed.
## 3. API Key
Next there will be a dialog with an API key created for you. Copy the key and curl command to try out unkey.
## 4. Next Steps
You should get to know our [API reference](/api-reference/v2/auth), as you can add additional 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.
# 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 modal 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:
1. Optionally enter a name. This is internal only and not customer-facing.
2. Click the `Select Permissions...` button.
3. Add your workspace-wide permissions. These permissions affect and override the per-API permissions below.
4. For each API in your workspace, you can enable fine-grained permissions.
5. Click `Create New Key` at the bottom.