diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index db00cae..0b8a7c6 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.67.0"
+ ".": "0.68.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index a164009..4127b5f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 342bd47..746ed91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
diff --git a/api.md b/api.md
index 4b24f10..8ba0dd4 100644
--- a/api.md
+++ b/api.md
@@ -449,10 +449,11 @@ from kernel.types import APIKey, CreatedAPIKey
Methods:
- client.api_keys.create(\*\*params) -> CreatedAPIKey
-- client.api_keys.retrieve(id) -> APIKey
+- client.api_keys.retrieve(id, \*\*params) -> APIKey
- client.api_keys.update(id, \*\*params) -> APIKey
- client.api_keys.list(\*\*params) -> SyncOffsetPagination[APIKey]
- client.api_keys.delete(id) -> None
+- client.api_keys.rotate(id, \*\*params) -> CreatedAPIKey
# CredentialProviders
diff --git a/pyproject.toml b/pyproject.toml
index 035e174..4020062 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -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"
diff --git a/src/kernel/_version.py b/src/kernel/_version.py
index 7c28de4..b0e3713 100644
--- a/src/kernel/_version.py
+++ b/src/kernel/_version.py
@@ -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
diff --git a/src/kernel/resources/api_keys.py b/src/kernel/resources/api_keys.py
index 93e8015..da28774 100644
--- a/src/kernel/resources/api_keys.py
+++ b/src/kernel/resources/api_keys.py
@@ -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
@@ -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,
@@ -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
@@ -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,
)
@@ -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,
@@ -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
@@ -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
@@ -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,
),
@@ -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."""
@@ -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,
@@ -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
@@ -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,
)
@@ -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,
@@ -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
@@ -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
@@ -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,
),
@@ -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:
@@ -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:
@@ -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:
@@ -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:
@@ -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,
+ )
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index 1e9b39a..e38ba40 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -39,6 +39,7 @@
from .proxy_list_response import ProxyListResponse as ProxyListResponse
from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse
from .api_key_create_params import APIKeyCreateParams as APIKeyCreateParams
+from .api_key_rotate_params import APIKeyRotateParams as APIKeyRotateParams
from .api_key_update_params import APIKeyUpdateParams as APIKeyUpdateParams
from .browser_create_params import BrowserCreateParams as BrowserCreateParams
from .browser_curl_response import BrowserCurlResponse as BrowserCurlResponse
@@ -54,6 +55,7 @@
from .deployment_state_event import DeploymentStateEvent as DeploymentStateEvent
from .invocation_list_params import InvocationListParams as InvocationListParams
from .invocation_state_event import InvocationStateEvent as InvocationStateEvent
+from .api_key_retrieve_params import APIKeyRetrieveParams as APIKeyRetrieveParams
from .browser_create_response import BrowserCreateResponse as BrowserCreateResponse
from .browser_retrieve_params import BrowserRetrieveParams as BrowserRetrieveParams
from .browser_update_response import BrowserUpdateResponse as BrowserUpdateResponse
diff --git a/src/kernel/types/api_key.py b/src/kernel/types/api_key.py
index 6df577f..4451952 100644
--- a/src/kernel/types/api_key.py
+++ b/src/kernel/types/api_key.py
@@ -28,6 +28,12 @@ class APIKey(BaseModel):
created_by: CreatedBy
+ deleted_at: Optional[datetime] = None
+ """When the API key was deleted (soft-deleted).
+
+ Null for keys that have not been deleted.
+ """
+
expires_at: Optional[datetime] = None
"""When the API key expires"""
diff --git a/src/kernel/types/api_key_list_params.py b/src/kernel/types/api_key_list_params.py
index 79a9c41..3ddc2a3 100644
--- a/src/kernel/types/api_key_list_params.py
+++ b/src/kernel/types/api_key_list_params.py
@@ -8,6 +8,13 @@
class APIKeyListParams(TypedDict, total=False):
+ include_deleted: bool
+ """Deprecated: use status=all instead.
+
+ When true, include deleted (soft-deleted) API keys in the results for audit
+ purposes.
+ """
+
limit: int
"""Maximum number of results to return"""
@@ -25,3 +32,11 @@ class APIKeyListParams(TypedDict, total=False):
sort_direction: Literal["asc", "desc"]
"""Sort direction for API keys."""
+
+ status: Literal["active", "deleted", "all"]
+ """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.
+ """
diff --git a/src/kernel/types/api_key_retrieve_params.py b/src/kernel/types/api_key_retrieve_params.py
new file mode 100644
index 0000000..e2b9ea3
--- /dev/null
+++ b/src/kernel/types/api_key_retrieve_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["APIKeyRetrieveParams"]
+
+
+class APIKeyRetrieveParams(TypedDict, total=False):
+ include_deleted: bool
+ """
+ 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.
+ """
diff --git a/src/kernel/types/api_key_rotate_params.py b/src/kernel/types/api_key_rotate_params.py
new file mode 100644
index 0000000..3810e58
--- /dev/null
+++ b/src/kernel/types/api_key_rotate_params.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+__all__ = ["APIKeyRotateParams"]
+
+
+class APIKeyRotateParams(TypedDict, total=False):
+ days_to_expire: Optional[int]
+ """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: Optional[int]
+ """Grace period in days before the rotated key expires.
+
+ Use 0 to expire it immediately. Omit for the default grace period of 7 days.
+ """
diff --git a/tests/api_resources/test_api_keys.py b/tests/api_resources/test_api_keys.py
index 9c3abca..5fdb5dc 100644
--- a/tests/api_resources/test_api_keys.py
+++ b/tests/api_resources/test_api_keys.py
@@ -9,7 +9,10 @@
from kernel import Kernel, AsyncKernel
from tests.utils import assert_matches_type
-from kernel.types import APIKey, CreatedAPIKey
+from kernel.types import (
+ APIKey,
+ CreatedAPIKey,
+)
from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -66,7 +69,16 @@ def test_streaming_response_create(self, client: Kernel) -> None:
@parametrize
def test_method_retrieve(self, client: Kernel) -> None:
api_key = client.api_keys.retrieve(
- "id",
+ id="id",
+ )
+ assert_matches_type(APIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Kernel) -> None:
+ api_key = client.api_keys.retrieve(
+ id="id",
+ include_deleted=True,
)
assert_matches_type(APIKey, api_key, path=["response"])
@@ -74,7 +86,7 @@ def test_method_retrieve(self, client: Kernel) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Kernel) -> None:
response = client.api_keys.with_raw_response.retrieve(
- "id",
+ id="id",
)
assert response.is_closed is True
@@ -86,7 +98,7 @@ def test_raw_response_retrieve(self, client: Kernel) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Kernel) -> None:
with client.api_keys.with_streaming_response.retrieve(
- "id",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -101,7 +113,7 @@ def test_streaming_response_retrieve(self, client: Kernel) -> None:
def test_path_params_retrieve(self, client: Kernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
client.api_keys.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -160,11 +172,13 @@ def test_method_list(self, client: Kernel) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Kernel) -> None:
api_key = client.api_keys.list(
+ include_deleted=True,
limit=100,
offset=0,
query="query",
sort_by="created_at",
sort_direction="asc",
+ status="active",
)
assert_matches_type(SyncOffsetPagination[APIKey], api_key, path=["response"])
@@ -232,6 +246,58 @@ def test_path_params_delete(self, client: Kernel) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_rotate(self, client: Kernel) -> None:
+ api_key = client.api_keys.rotate(
+ id="id",
+ )
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_rotate_with_all_params(self, client: Kernel) -> None:
+ api_key = client.api_keys.rotate(
+ id="id",
+ days_to_expire=30,
+ expire_in_days=7,
+ )
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_rotate(self, client: Kernel) -> None:
+ response = client.api_keys.with_raw_response.rotate(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ api_key = response.parse()
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_rotate(self, client: Kernel) -> None:
+ with client.api_keys.with_streaming_response.rotate(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ api_key = response.parse()
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_rotate(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.api_keys.with_raw_response.rotate(
+ id="",
+ )
+
class TestAsyncAPIKeys:
parametrize = pytest.mark.parametrize(
@@ -286,7 +352,16 @@ async def test_streaming_response_create(self, async_client: AsyncKernel) -> Non
@parametrize
async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
api_key = await async_client.api_keys.retrieve(
- "id",
+ id="id",
+ )
+ assert_matches_type(APIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncKernel) -> None:
+ api_key = await async_client.api_keys.retrieve(
+ id="id",
+ include_deleted=True,
)
assert_matches_type(APIKey, api_key, path=["response"])
@@ -294,7 +369,7 @@ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
response = await async_client.api_keys.with_raw_response.retrieve(
- "id",
+ id="id",
)
assert response.is_closed is True
@@ -306,7 +381,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
async with async_client.api_keys.with_streaming_response.retrieve(
- "id",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -321,7 +396,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> N
async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
await async_client.api_keys.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -380,11 +455,13 @@ async def test_method_list(self, async_client: AsyncKernel) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None:
api_key = await async_client.api_keys.list(
+ include_deleted=True,
limit=100,
offset=0,
query="query",
sort_by="created_at",
sort_direction="asc",
+ status="active",
)
assert_matches_type(AsyncOffsetPagination[APIKey], api_key, path=["response"])
@@ -451,3 +528,55 @@ async def test_path_params_delete(self, async_client: AsyncKernel) -> None:
await async_client.api_keys.with_raw_response.delete(
"",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_rotate(self, async_client: AsyncKernel) -> None:
+ api_key = await async_client.api_keys.rotate(
+ id="id",
+ )
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_rotate_with_all_params(self, async_client: AsyncKernel) -> None:
+ api_key = await async_client.api_keys.rotate(
+ id="id",
+ days_to_expire=30,
+ expire_in_days=7,
+ )
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_rotate(self, async_client: AsyncKernel) -> None:
+ response = await async_client.api_keys.with_raw_response.rotate(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ api_key = await response.parse()
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_rotate(self, async_client: AsyncKernel) -> None:
+ async with async_client.api_keys.with_streaming_response.rotate(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ api_key = await response.parse()
+ assert_matches_type(CreatedAPIKey, api_key, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_rotate(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.api_keys.with_raw_response.rotate(
+ id="",
+ )