Skip to content
Open
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.67.0"
".": "0.68.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 119
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-51549f813f3002e18c6ca8d850cc0c7932828d511c151e0412c73b6798d19e30.yml
openapi_spec_hash: ee77b293c4bda91c1a32cfdd12b8739e
config_hash: 57567e00b41af47cef1b78e51b747aa0
configured_endpoints: 120
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e8afdbeac9332cf79200c2eb873e532104fd0a7472b08e63cde6c857a87cf0c3.yml
openapi_spec_hash: 2525caf30dffbdd83c83948201f11a52
config_hash: 03c7e57f268c750e2415831662e95969
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 0.68.0 (2026-06-14)

Full Changelog: [v0.67.0...v0.68.0](https://github.com/kernel/kernel-python-sdk/compare/v0.67.0...v0.68.0)

### Features

* Add API key rotate endpoint ([5ad5ee5](https://github.com/kernel/kernel-python-sdk/commit/5ad5ee511057a6bcaa69fee40087e3cf490a4494))
* **api:** surface deleted/expired API keys for audit trail (KERNEL-1350) ([6f16159](https://github.com/kernel/kernel-python-sdk/commit/6f16159d28de8129b12dfe2e144e9d1db39ad4ec))


### Refactors

* **api:** align API key audit surface with browser sibling (KERNEL-1350) ([bdf7a0d](https://github.com/kernel/kernel-python-sdk/commit/bdf7a0dec6ed448f4846186fba05e4cbb7eb0846))

## 0.67.0 (2026-06-11)

Full Changelog: [v0.66.0...v0.67.0](https://github.com/kernel/kernel-python-sdk/compare/v0.66.0...v0.67.0)
Expand Down
3 changes: 2 additions & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,11 @@ from kernel.types import APIKey, CreatedAPIKey
Methods:

- <code title="post /org/api_keys">client.api_keys.<a href="./src/kernel/resources/api_keys.py">create</a>(\*\*<a href="src/kernel/types/api_key_create_params.py">params</a>) -> <a href="./src/kernel/types/created_api_key.py">CreatedAPIKey</a></code>
- <code title="get /org/api_keys/{id}">client.api_keys.<a href="./src/kernel/resources/api_keys.py">retrieve</a>(id) -> <a href="./src/kernel/types/api_key.py">APIKey</a></code>
- <code title="get /org/api_keys/{id}">client.api_keys.<a href="./src/kernel/resources/api_keys.py">retrieve</a>(id, \*\*<a href="src/kernel/types/api_key_retrieve_params.py">params</a>) -> <a href="./src/kernel/types/api_key.py">APIKey</a></code>
- <code title="patch /org/api_keys/{id}">client.api_keys.<a href="./src/kernel/resources/api_keys.py">update</a>(id, \*\*<a href="src/kernel/types/api_key_update_params.py">params</a>) -> <a href="./src/kernel/types/api_key.py">APIKey</a></code>
- <code title="get /org/api_keys">client.api_keys.<a href="./src/kernel/resources/api_keys.py">list</a>(\*\*<a href="src/kernel/types/api_key_list_params.py">params</a>) -> <a href="./src/kernel/types/api_key.py">SyncOffsetPagination[APIKey]</a></code>
- <code title="delete /org/api_keys/{id}">client.api_keys.<a href="./src/kernel/resources/api_keys.py">delete</a>(id) -> None</code>
- <code title="post /org/api_keys/{id}/rotate">client.api_keys.<a href="./src/kernel/resources/api_keys.py">rotate</a>(id, \*\*<a href="src/kernel/types/api_key_rotate_params.py">params</a>) -> <a href="./src/kernel/types/created_api_key.py">CreatedAPIKey</a></code>

# CredentialProviders

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "kernel"
version = "0.67.0"
version = "0.68.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "kernel"
__version__ = "0.67.0" # x-release-please-version
__version__ = "0.68.0" # x-release-please-version
168 changes: 165 additions & 3 deletions src/kernel/resources/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@

import httpx

from ..types import api_key_list_params, api_key_create_params, api_key_update_params
from ..types import (
api_key_list_params,
api_key_create_params,
api_key_rotate_params,
api_key_update_params,
api_key_retrieve_params,
)
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
Expand Down Expand Up @@ -99,6 +105,7 @@ def retrieve(
self,
id: str,
*,
include_deleted: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
Expand All @@ -112,6 +119,9 @@ def retrieve(
masked.

Args:
include_deleted: When true, return the API key even if it has been deleted (soft-deleted), for
audit purposes. Defaults to false, which returns 404 for a deleted key.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -125,7 +135,13 @@ def retrieve(
return self._get(
path_template("/org/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
{"include_deleted": include_deleted}, api_key_retrieve_params.APIKeyRetrieveParams
),
),
cast_to=APIKey,
)
Expand Down Expand Up @@ -170,11 +186,13 @@ def update(
def list(
self,
*,
include_deleted: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
query: str | Omit = omit,
sort_by: Literal["created_at", "name", "expires_at"] | Omit = omit,
sort_direction: Literal["asc", "desc"] | Omit = omit,
status: Literal["active", "deleted", "all"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
Expand All @@ -187,6 +205,9 @@ def list(
API keys are masked.

Args:
include_deleted: Deprecated: use status=all instead. When true, include deleted (soft-deleted)
API keys in the results for audit purposes.

limit: Maximum number of results to return

offset: Number of results to skip
Expand All @@ -198,6 +219,10 @@ def list(

sort_direction: Sort direction for API keys.

status: Filter API keys by status. "active" returns keys that are not deleted (default;
expired-but-not-deleted keys are still included), "deleted" returns only
soft-deleted keys, "all" returns both.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -216,11 +241,13 @@ def list(
timeout=timeout,
query=maybe_transform(
{
"include_deleted": include_deleted,
"limit": limit,
"offset": offset,
"query": query,
"sort_by": sort_by,
"sort_direction": sort_direction,
"status": status,
},
api_key_list_params.APIKeyListParams,
),
Expand Down Expand Up @@ -262,6 +289,57 @@ def delete(
cast_to=NoneType,
)

def rotate(
self,
id: str,
*,
days_to_expire: Optional[int] | Omit = omit,
expire_in_days: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CreatedAPIKey:
"""Rotate an API key.

Issues a new key that copies the name and project of the
rotated key, and schedules the rotated key to expire after a grace period so
in-flight callers can swap over. The new plaintext key is returned once.

Args:
days_to_expire: Lifetime in days for the new key, up to 3650. Omit to reuse the rotated key's
original lifetime, or never-expires if it had none.

expire_in_days: Grace period in days before the rotated key expires. Use 0 to expire it
immediately. Omit for the default grace period of 7 days.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request

extra_body: Add additional JSON properties to the request

timeout: Override the client-level default timeout for this request, in seconds
"""
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._post(
path_template("/org/api_keys/{id}/rotate", id=id),
body=maybe_transform(
{
"days_to_expire": days_to_expire,
"expire_in_days": expire_in_days,
},
api_key_rotate_params.APIKeyRotateParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=CreatedAPIKey,
)


class AsyncAPIKeysResource(AsyncAPIResource):
"""Create and manage API keys for organization and project-scoped access."""
Expand Down Expand Up @@ -336,6 +414,7 @@ async def retrieve(
self,
id: str,
*,
include_deleted: bool | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
Expand All @@ -349,6 +428,9 @@ async def retrieve(
masked.

Args:
include_deleted: When true, return the API key even if it has been deleted (soft-deleted), for
audit purposes. Defaults to false, which returns 404 for a deleted key.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -362,7 +444,13 @@ async def retrieve(
return await self._get(
path_template("/org/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
{"include_deleted": include_deleted}, api_key_retrieve_params.APIKeyRetrieveParams
),
),
cast_to=APIKey,
)
Expand Down Expand Up @@ -407,11 +495,13 @@ async def update(
def list(
self,
*,
include_deleted: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
query: str | Omit = omit,
sort_by: Literal["created_at", "name", "expires_at"] | Omit = omit,
sort_direction: Literal["asc", "desc"] | Omit = omit,
status: Literal["active", "deleted", "all"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
Expand All @@ -424,6 +514,9 @@ def list(
API keys are masked.

Args:
include_deleted: Deprecated: use status=all instead. When true, include deleted (soft-deleted)
API keys in the results for audit purposes.

limit: Maximum number of results to return

offset: Number of results to skip
Expand All @@ -435,6 +528,10 @@ def list(

sort_direction: Sort direction for API keys.

status: Filter API keys by status. "active" returns keys that are not deleted (default;
expired-but-not-deleted keys are still included), "deleted" returns only
soft-deleted keys, "all" returns both.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -453,11 +550,13 @@ def list(
timeout=timeout,
query=maybe_transform(
{
"include_deleted": include_deleted,
"limit": limit,
"offset": offset,
"query": query,
"sort_by": sort_by,
"sort_direction": sort_direction,
"status": status,
},
api_key_list_params.APIKeyListParams,
),
Expand Down Expand Up @@ -499,6 +598,57 @@ async def delete(
cast_to=NoneType,
)

async def rotate(
self,
id: str,
*,
days_to_expire: Optional[int] | Omit = omit,
expire_in_days: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CreatedAPIKey:
"""Rotate an API key.

Issues a new key that copies the name and project of the
rotated key, and schedules the rotated key to expire after a grace period so
in-flight callers can swap over. The new plaintext key is returned once.

Args:
days_to_expire: Lifetime in days for the new key, up to 3650. Omit to reuse the rotated key's
original lifetime, or never-expires if it had none.

expire_in_days: Grace period in days before the rotated key expires. Use 0 to expire it
immediately. Omit for the default grace period of 7 days.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request

extra_body: Add additional JSON properties to the request

timeout: Override the client-level default timeout for this request, in seconds
"""
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._post(
path_template("/org/api_keys/{id}/rotate", id=id),
body=await async_maybe_transform(
{
"days_to_expire": days_to_expire,
"expire_in_days": expire_in_days,
},
api_key_rotate_params.APIKeyRotateParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=CreatedAPIKey,
)


class APIKeysResourceWithRawResponse:
def __init__(self, api_keys: APIKeysResource) -> None:
Expand All @@ -519,6 +669,9 @@ def __init__(self, api_keys: APIKeysResource) -> None:
self.delete = to_raw_response_wrapper(
api_keys.delete,
)
self.rotate = to_raw_response_wrapper(
api_keys.rotate,
)


class AsyncAPIKeysResourceWithRawResponse:
Expand All @@ -540,6 +693,9 @@ def __init__(self, api_keys: AsyncAPIKeysResource) -> None:
self.delete = async_to_raw_response_wrapper(
api_keys.delete,
)
self.rotate = async_to_raw_response_wrapper(
api_keys.rotate,
)


class APIKeysResourceWithStreamingResponse:
Expand All @@ -561,6 +717,9 @@ def __init__(self, api_keys: APIKeysResource) -> None:
self.delete = to_streamed_response_wrapper(
api_keys.delete,
)
self.rotate = to_streamed_response_wrapper(
api_keys.rotate,
)


class AsyncAPIKeysResourceWithStreamingResponse:
Expand All @@ -582,3 +741,6 @@ def __init__(self, api_keys: AsyncAPIKeysResource) -> None:
self.delete = async_to_streamed_response_wrapper(
api_keys.delete,
)
self.rotate = async_to_streamed_response_wrapper(
api_keys.rotate,
)
Loading
Loading