Skip to content
Merged
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
83 changes: 75 additions & 8 deletions info/api-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -212,18 +212,85 @@ func main() {

## Rotate a key

Rotate by creating the replacement first, then deleting the old key after your workload has switched over.
`rotate` issues a replacement key in a single call and keeps the old key working for a short grace period, so your workload can switch over without downtime. The new key copies the rotated key's name and project scope, and—like create—Kernel returns the plaintext `key` only once.

1. Create a new API key with the same scope.
2. Store the new plaintext key in your secret manager.
3. Deploy or restart the workload that uses `KERNEL_API_KEY`.
4. Verify the workload can call Kernel.
5. Delete the old API key.
Two optional parameters control the timing:

- `days_to_expire` sets the new key's lifetime in days (`1`-`3650`). Omit it to give the new key the same lifetime the rotated key originally had, or to never expire if the old key never did.
- `expire_in_days` sets how long the old key keeps working before it expires. Use `0` to revoke it immediately, or omit it for the default 7-day grace window. The old key stops authenticating automatically once the window passes—you don't need to delete it.

<CodeGroup>
```typescript TypeScript
const rotated = await kernel.apiKeys.rotate('key_01jwv4tn5m8k3q2v7x9p0a1bc2', {
days_to_expire: 30,
expire_in_days: 7,
});

console.log(rotated.key); // Save this value now. Kernel won't show it again.
console.log(rotated.id, rotated.masked_key);
```

```python Python
import os
from kernel import Kernel

client = Kernel(api_key=os.environ["KERNEL_API_KEY"])

rotated = client.api_keys.rotate(
"key_01jwv4tn5m8k3q2v7x9p0a1bc2",
days_to_expire=30,
expire_in_days=7,
)

print(rotated.key) # Save this value now. Kernel won't show it again.
print(rotated.id, rotated.masked_key)
```

```go Go
package main

import (
"context"
"fmt"

"github.com/kernel/kernel-go-sdk"
)

func main() {
ctx := context.Background()
client := kernel.NewClient()

rotated, err := client.APIKeys.Rotate(
ctx,
"key_01jwv4tn5m8k3q2v7x9p0a1bc2",
kernel.APIKeyRotateParams{
DaysToExpire: kernel.Int(30),
ExpireInDays: kernel.Int(7),
},
)
if err != nil {
panic(err)
}

fmt.Println(rotated.Key) // Save this value now. Kernel won't show it again.
fmt.Println(rotated.ID, rotated.MaskedKey)
}
```
</CodeGroup>

After you rotate a key:

1. Store the new plaintext key in your secret manager.
2. Deploy or restart the workload that uses `KERNEL_API_KEY`.
3. Verify the workload can call Kernel before the grace window ends.

To cut over immediately instead of using a grace window, pass `expire_in_days: 0` so the old key stops working as soon as the new one is issued.

## Troubleshooting

| Error | What it means | What to do |
| --- | --- | --- |
| `400 Bad Request` | The name is missing, `days_to_expire` is outside `1`-`3650`, or `project_id` is empty. | Send a name, choose a valid expiry, or omit `project_id` for an org-scoped key. |
| `400 Bad Request` | The name is missing, `days_to_expire` is outside `1`-`3650`, `expire_in_days` is outside `0`-`3650`, or `project_id` is empty. | Send a name, choose a valid expiry, or omit `project_id` for an org-scoped key. |
| `400 Bad Request` (rotate) | `days_to_expire` is shorter than `expire_in_days`, so the new key would expire before the old key's grace window ends. | Raise `days_to_expire` or lower `expire_in_days`. |
| `401 Unauthorized` | Kernel couldn't authenticate the request. | Set a valid `KERNEL_API_KEY`. |
| `404 Not Found` | The project doesn't exist or the caller can't access it. | Check the project ID. If you're using a project-scoped key, create keys only for that same project. |
| `404 Not Found` | The project or API key doesn't exist, or the caller can't access it. | Check the ID. If you're using a project-scoped key, you can only rotate keys in that same project. |
Loading