Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 109 additions & 5 deletions apps/docs/api-reference/v1/migration/keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,25 @@ curl -X POST https://api.unkey.com/v2/keys.createKey \
## POST /v1/keys.verifyKey → POST /v2/keys.verifyKey

**Key Changes:**
- **🚨 CRITICAL**: v2 requires root key authentication with `api.*.verify_key` permission
- **🚨 CRITICAL**: `apiId` parameter is no longer accepted in v2
- Remove `authorization` wrapper for permissions
- Use string-based permission queries instead of object syntax
- Change `remaining` → `credits` for cost parameters
- Add support for multiple named rate limits
- Response format: Direct response → `{meta, data}` envelope
- **Important**: v1 doesn't require root key authentication, v2 does

<Note>
**Major Authentication Change in v2**

The biggest change in v2 is that key verification now requires authentication with a root key that has the `api.*.verify_key` permission. This enables fine-grained access control:

- **Wildcard permission**: `api.*.verify_key` allows verifying keys from any API in your workspace
- **Specific API permission**: `api.api_123.verify_key` allows verifying only keys from API `api_123`
- **No apiId parameter**: Unlike v1, you cannot specify which API's keys to verify - this is controlled by the root key's permissions

This change improves security by ensuring only authorized services can verify keys, and provides workspace owners control over which services can verify keys from which APIs.
</Note>

**Simple Key Verification**

Expand All @@ -185,7 +198,7 @@ curl -X POST https://api.unkey.dev/v1/keys.verifyKey \

```bash title="v2 cURL" icon="terminal" highlight={2}
curl -X POST https://api.unkey.com/v2/keys.verifyKey \
-H "Authorization: Bearer <your-root-key>" \
-H "Authorization: Bearer <your-root-key-with-api.*.verify_key-permission>" \
-H "Content-Type: application/json" \
-d '{"key": "sk_1234abcdef"}'
```
Expand Down Expand Up @@ -291,7 +304,7 @@ curl -X POST https://api.unkey.dev/v1/keys.verifyKey \

```bash title="v2 cURL" icon="terminal" highlight={2,6}
curl -X POST https://api.unkey.com/v2/keys.verifyKey \
-H "Authorization: Bearer <your-root-key>" \
-H "Authorization: Bearer <your-root-key-with-api.*.verify_key-permission>" \
-H "Content-Type: application/json" \
-d '{
"key": "sk_1234abcdef",
Expand Down Expand Up @@ -341,7 +354,7 @@ curl -X POST https://api.unkey.dev/v1/keys.verifyKey \

```bash title="v2 cURL" icon="terminal" highlight={2,6-10}
curl -X POST https://api.unkey.com/v2/keys.verifyKey \
-H "Authorization: Bearer <your-root-key>" \
-H "Authorization: Bearer <your-root-key-with-api.*.verify_key-permission>" \
-H "Content-Type: application/json" \
-d '{
"key": "sk_1234abcdef",
Expand All @@ -357,6 +370,94 @@ curl -X POST https://api.unkey.com/v2/keys.verifyKey \

---

## Understanding v2 Root Key Permissions for Key Verification

The v2 `keys.verifyKey` endpoint introduces a powerful permission system that gives you granular control over which services can verify keys from which APIs.

### Setting Up Root Key Permissions

When creating a root key for key verification, you need to grant it the appropriate `api.*.verify_key` permission:

<Tabs>
<Tab title="Wildcard Permission (All APIs)">
```json title="Root Key with Permission to Verify Any API Key" icon="key"
{
"name": "Service Authentication Key",
"permissions": [
{
"name": "api.*.verify_key",
"description": "Allow verification of keys from any API in the workspace"
}
]
}
```

This root key can verify keys from any API in your workspace. Use this for services that need to authenticate users across multiple APIs.
</Tab>
<Tab title="Specific API Permission">
```json title="Root Key with Permission for Specific API" icon="shield"
{
"name": "Production API Verification Key",
"permissions": [
{
"name": "api.api_1234567890abcdef.verify_key",
"description": "Allow verification of keys only from the Production API"
}
]
}
```

This root key can only verify keys from the specific API `api_1234567890abcdef`. Use this for services that should only authenticate users from a particular API.
</Tab>
<Tab title="Multiple Specific APIs">
```json title="Root Key with Permission for Multiple APIs" icon="layers"
{
"name": "Multi-Service Verification Key",
"permissions": [
{
"name": "api.api_prod123.verify_key",
"description": "Verify keys from Production API"
},
{
"name": "api.api_staging456.verify_key",
"description": "Verify keys from Staging API"
}
]
}
```

This root key can verify keys from multiple specific APIs. Use this when you need to authenticate users from several APIs but not all APIs in the workspace.
</Tab>
</Tabs>

### Migration from v1 apiId Parameter

In v1, you could specify which API's keys to verify using the `apiId` parameter:

```json title="v1: Explicit API Selection"
{
"key": "sk_1234abcdef",
"apiId": "api_1234567890abcdef" // ❌ No longer supported in v2
}
```

In v2, this control is moved to the root key's permissions:

```json title="v2: Permission-Based API Selection"
{
"key": "sk_1234abcdef"
// API access controlled by root key's api.*.verify_key permissions
}
```

**Benefits of the New System:**
- **Better Security**: Only authorized services can verify keys
- **Granular Control**: Workspace owners control which services can verify keys from which APIs
- **Simpler Integration**: No need to manage `apiId` parameters in your application code
- **Audit Trail**: All key verifications are tied to specific root keys with known permissions

---

## GET /v1/keys.getKey → POST /v2/keys.getKey

**Key Changes:**
Expand Down Expand Up @@ -1294,10 +1395,13 @@ console.log(keyData.keyId);
- [ ] Add `refillDay` for monthly intervals

### Key Verification
- [ ] Add root key authentication header to key verification calls
- [ ] **CRITICAL**: Create root key with `api.*.verify_key` permission for your verification service
- [ ] Add root key authentication header to all key verification calls
- [ ] Remove `apiId` parameter from verification requests (controlled by root key permissions now)
- [ ] Convert permission query objects to strings: `"perm1 AND perm2"`
- [ ] Update `remaining` → `credits` for cost parameters
- [ ] Handle new rate limits array structure in responses
- [ ] Test verification with both wildcard (`api.*.verify_key`) and specific API permissions

### Response Handling
- [ ] Change `response` (direct) to `response.data` in all key operations
Expand Down
6 changes: 4 additions & 2 deletions apps/docs/errors/unkey/application/assertion_failed.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:application:assertion_failed"
title: "assertion_failed"
description: "A runtime assertion or invariant check failed"
---

<Danger>`err:unkey:application:invalid_input`</Danger>


```json Example
{
Expand Down Expand Up @@ -54,4 +56,4 @@ When contacting support, be sure to include:

## Related Errors
- [err:unkey:application:unexpected_error](./unexpected_error) - A more general internal error
- [err:unkey:application:service_unavailable](./service_unavailable) - When a service is temporarily unavailable
- [err:unkey:application:service_unavailable](./service_unavailable) - When a service is temporarily unavailable
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/application/invalid_input.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:application:invalid_input"
title: "invalid_input"
description: "Client provided input that failed validation"
---

<Danger>`err:unkey:application:invalid_input`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/application/protected_resource.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:application:protected_resource"
title: "protected_resource"
description: "Attempt to modify a protected resource"
---

<Danger>`err:unkey:application:protected_resource`</Danger>


```json Example
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:application:service_unavailable"
title: "service_unavailable"
description: "A service is temporarily unavailable"
---

<Danger>`err:unkey:application:service_unavailable`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/application/unexpected_error.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:application:unexpected_error"
title: "unexpected_error"
description: "An unhandled or unexpected error occurred"
---

<Danger>`err:unkey:application:unexpected_error`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/authentication/key_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authentication:key_not_found"
title: "key_not_found"
description: "The authentication key was not found"
---

<Danger>`err:unkey:authentication:key_not_found`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/authentication/malformed.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authentication:malformed"
title: "malformed"
description: "Authentication credentials were incorrectly formatted"
---

<Danger>`err:unkey:authentication:malformed`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/authentication/missing.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authentication:missing"
title: "missing"
description: "Authentication credentials were not provided in the request"
---

<Danger>`err:unkey:authentication:missing`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/authorization/forbidden.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authorization:forbidden"
title: "forbidden"
description: "The operation is not allowed"
---

<Danger>`err:unkey:authorization:forbidden`</Danger>


```json Example
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authorization:insufficient_permissions"
title: "insufficient_permissions"
description: "The authenticated entity lacks sufficient permissions for the requested operation"
---

<Danger>`err:unkey:authorization:insufficient_permissions`</Danger>


```json Example
{
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/errors/unkey/authorization/key_disabled.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authorization:key_disabled"
title: "key_disabled"
description: "The authentication key is disabled"
---

<Danger>`err:unkey:authorization:key_disabled`</Danger>


```json Example
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
title: "err:unkey:authorization:workspace_disabled"
title: "workspace_disabled"
description: "The associated workspace is disabled"
---

<Danger>`err:unkey:authorization:workspace_disabled`</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/api_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:api_not_found"
title: "api_not_found"
description: "The requested API was not found"
---

<Danger>
err:unkey:data:api_not_found
</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/audit_log_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:audit_log_not_found"
title: "audit_log_not_found"
description: "The requested audit log was not found"
---

<Danger>
err:unkey:data:audit_log_not_found
</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/identity_already_exists.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:identity_already_exists"
title: "identity_already_exists"
description: "The requested identity already exists"
---

<Danger>
err:unkey:data:identity_already_exists
</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/identity_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:identity_not_found"
title: "identity_not_found"
description: "The requested identity was not found"
---

<Danger>
err:unkey:data:identity_not_found
</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/key_auth_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:key_auth_not_found"
title: "key_auth_not_found"
description: "The requested key authentication was not found"
---

<Danger>
err:unkey:data:key_auth_not_found
</Danger>


```json Example
{
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/errors/unkey/data/key_not_found.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: "err:unkey:data:key_not_found"
title: "key_not_found"
description: "The requested key was not found"
---

<Danger>
err:unkey:data:key_not_found
</Danger>


```json Example
{
Expand Down
Loading