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
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.11.0"
".": "0.12.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 106
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/keycard/keycard-api-98bb06a2aca1b7ea066960a14eb4879aa4967bc4ed9686b66e60438824ce8415.yml
openapi_spec_hash: b7bdac3288a2e626465c0baf6df49c17
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/keycard/keycard-api-52cd0ce5e22a084f1d1b6479ea85a80066c68c88d70ec7b23daeceba6264797b.yml
openapi_spec_hash: 438cb543611b1ecd037414d52791a4a0
config_hash: b0ee2dc67cc490e45f8fe0acabd76206
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.12.0 (2026-05-21)

Full Changelog: [v0.11.0...v0.12.0](https://github.com/keycardai/keycard-python/compare/v0.11.0...v0.12.0)

### Features

* add scopes to provider openid protocol schemas (ACC-354) ([350683d](https://github.com/keycardai/keycard-python/commit/350683d62f6d36e181f69effb96cd4a6354853db))

## 0.11.0 (2026-05-15)

Full Changelog: [v0.10.0...v0.11.0](https://github.com/keycardai/keycard-python/compare/v0.10.0...v0.11.0)
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 = "keycardai_api"
version = "0.11.0"
version = "0.12.0"
description = "The official Python library for the keycard-api API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/keycardai_api/_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__ = "keycardai_api"
__version__ = "0.11.0" # x-release-please-version
__version__ = "0.12.0" # x-release-please-version
16 changes: 14 additions & 2 deletions src/keycardai_api/resources/zones/delegated_grants.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def list(
expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit,
limit: int | Omit = omit,
resource_id: str | Omit = omit,
sort: str | Omit = omit,
status: Literal["active", "expired", "revoked"] | Omit = omit,
user_id: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
Expand All @@ -141,7 +142,9 @@ def list(
"""Returns a list of delegated grants in the specified zone.

Can be filtered by
user, resource, or status.
user, resource, or status. Use cursor pagination via `after`/`before`. Sort:
comma-separated field list; prefix with `-` for descending. Use
`expand[]=total_count` to include the matching row count.

Args:
after: Cursor for forward pagination
Expand All @@ -152,6 +155,8 @@ def list(

resource_id: Filter by resource ID

sort: Comma-separated sort fields. Prefix with - for descending. Allowed: created_at

user_id: Filter by user ID

extra_headers: Send extra headers
Expand Down Expand Up @@ -179,6 +184,7 @@ def list(
"expand": expand,
"limit": limit,
"resource_id": resource_id,
"sort": sort,
"status": status,
"user_id": user_id,
},
Expand Down Expand Up @@ -333,6 +339,7 @@ async def list(
expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit,
limit: int | Omit = omit,
resource_id: str | Omit = omit,
sort: str | Omit = omit,
status: Literal["active", "expired", "revoked"] | Omit = omit,
user_id: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
Expand All @@ -345,7 +352,9 @@ async def list(
"""Returns a list of delegated grants in the specified zone.

Can be filtered by
user, resource, or status.
user, resource, or status. Use cursor pagination via `after`/`before`. Sort:
comma-separated field list; prefix with `-` for descending. Use
`expand[]=total_count` to include the matching row count.

Args:
after: Cursor for forward pagination
Expand All @@ -356,6 +365,8 @@ async def list(

resource_id: Filter by resource ID

sort: Comma-separated sort fields. Prefix with - for descending. Allowed: created_at

user_id: Filter by user ID

extra_headers: Send extra headers
Expand Down Expand Up @@ -383,6 +394,7 @@ async def list(
"expand": expand,
"limit": limit,
"resource_id": resource_id,
"sort": sort,
"status": status,
"user_id": user_id,
},
Expand Down
46 changes: 28 additions & 18 deletions src/keycardai_api/resources/zones/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ def list(
*,
after: str | Omit = omit,
before: str | Omit = omit,
expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit,
expand: Union[
Literal["total_count", "session_count", "grant_count"],
List[Literal["total_count", "session_count", "grant_count"]],
]
| Omit = omit,
filter_email: Union[str, SequenceNotStr[str]] | Omit = omit,
filter_id: Union[str, SequenceNotStr[str]] | Omit = omit,
limit: int | Omit = omit,
Expand Down Expand Up @@ -115,14 +119,15 @@ def list(

Use cursor pagination via `after`/`before`. Sort: comma-separated field list;
prefix with `-` for descending. Use `expand[]=total_count` to include the
matching row count. Filter by exact email via `filter[email]`; search via
`query[email]` / `query[subject]` / `query[]` (substring match, OR'd across
repeated values). `query[]` matches against email and federation credential
subject. Pass `filter[id]` (repeatable, max 100) to restrict results to a known
set of users — mutually exclusive with `after`/`before` (returns 400 if
combined). When `filter[id]` is set, `limit` is ignored and the response
contains every requested user that exists in the zone, in a single page. IDs not
in the zone are silently omitted.
matching row count, `expand[]=session_count` to include per-user session counts,
and `expand[]=grant_count` to include per-user delegated-grant counts. Filter by
exact email via `filter[email]`; search via `query[email]` / `query[subject]` /
`query[]` (substring match, OR'd across repeated values). `query[]` matches
against email and federation credential subject. Pass `filter[id]` (repeatable,
max 100) to restrict results to a known set of users — mutually exclusive with
`after`/`before` (returns 400 if combined). When `filter[id]` is set, `limit` is
ignored and the response contains every requested user that exists in the zone,
in a single page. IDs not in the zone are silently omitted.

Args:
after: Cursor for forward pagination
Expand Down Expand Up @@ -244,7 +249,11 @@ async def list(
*,
after: str | Omit = omit,
before: str | Omit = omit,
expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit,
expand: Union[
Literal["total_count", "session_count", "grant_count"],
List[Literal["total_count", "session_count", "grant_count"]],
]
| Omit = omit,
filter_email: Union[str, SequenceNotStr[str]] | Omit = omit,
filter_id: Union[str, SequenceNotStr[str]] | Omit = omit,
limit: int | Omit = omit,
Expand Down Expand Up @@ -272,14 +281,15 @@ async def list(

Use cursor pagination via `after`/`before`. Sort: comma-separated field list;
prefix with `-` for descending. Use `expand[]=total_count` to include the
matching row count. Filter by exact email via `filter[email]`; search via
`query[email]` / `query[subject]` / `query[]` (substring match, OR'd across
repeated values). `query[]` matches against email and federation credential
subject. Pass `filter[id]` (repeatable, max 100) to restrict results to a known
set of users — mutually exclusive with `after`/`before` (returns 400 if
combined). When `filter[id]` is set, `limit` is ignored and the response
contains every requested user that exists in the zone, in a single page. IDs not
in the zone are silently omitted.
matching row count, `expand[]=session_count` to include per-user session counts,
and `expand[]=grant_count` to include per-user delegated-grant counts. Filter by
exact email via `filter[email]`; search via `query[email]` / `query[subject]` /
`query[]` (substring match, OR'd across repeated values). `query[]` matches
against email and federation credential subject. Pass `filter[id]` (repeatable,
max 100) to restrict results to a known set of users — mutually exclusive with
`after`/`before` (returns 400 if combined). When `filter[id]` is set, `limit` is
ignored and the response contains every requested user that exists in the zone,
in a single page. IDs not in the zone are silently omitted.

Args:
after: Cursor for forward pagination
Expand Down
3 changes: 3 additions & 0 deletions src/keycardai_api/types/zones/delegated_grant_list_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class DelegatedGrantListParams(TypedDict, total=False):
resource_id: str
"""Filter by resource ID"""

sort: str
"""Comma-separated sort fields. Prefix with - for descending. Allowed: created_at"""

status: Literal["active", "expired", "revoked"]

user_id: str
Expand Down
6 changes: 6 additions & 0 deletions src/keycardai_api/types/zones/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class ProtocolsOauth2(BaseModel):
class ProtocolsOpenid(BaseModel):
"""OpenID Connect protocol configuration"""

scopes: Optional[List[str]] = None
"""Additional OIDC scopes to request from this provider during authentication (e.g.

"groups"). Merged with the default scopes (openid, profile, email).
"""

user_identifier_claim: Optional[str] = None
"""
Name of a top-level string claim in this provider's ID Token to use as the user
Expand Down
6 changes: 6 additions & 0 deletions src/keycardai_api/types/zones/provider_create_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ class ProtocolsOauth2(TypedDict, total=False):
class ProtocolsOpenid(TypedDict, total=False):
"""OpenID Connect protocol configuration for provider creation"""

scopes: SequenceNotStr[str]
"""Additional OIDC scopes to request from this provider during authentication (e.g.

"groups"). Merged with the default scopes (openid, profile, email).
"""

user_identifier_claim: str
"""
Name of a top-level string claim in this provider's ID Token to use as the user
Expand Down
7 changes: 7 additions & 0 deletions src/keycardai_api/types/zones/provider_update_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ class ProtocolsOauth2(TypedDict, total=False):
class ProtocolsOpenid(TypedDict, total=False):
"""OpenID Connect protocol configuration. Set to null to remove all OpenID config."""

scopes: Optional[SequenceNotStr[str]]
"""Additional OIDC scopes to request from this provider during authentication (e.g.

"groups"). Merged with the default scopes (openid, profile, email). Set to null
to clear.
"""

user_identifier_claim: Optional[str]
"""
Name of a top-level string claim in this provider's ID Token to use as the user
Expand Down
12 changes: 12 additions & 0 deletions src/keycardai_api/types/zones/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class User(BaseModel):
authenticated_at: Optional[str] = None
"""Date when the user was last authenticated"""

grant_count: Optional[int] = None
"""Delegated-grant count for this user.

Populated only when `expand[]=grant_count` is set on the listing endpoint.
"""

issuer: Optional[str] = None
"""Issuer identifier of the identity provider"""

Expand All @@ -52,5 +58,11 @@ class User(BaseModel):
user is not deleted.
"""

session_count: Optional[int] = None
"""Session count for this user.

Populated only when `expand[]=session_count` is set on the listing endpoint.
"""

subject: Optional[str] = None
"""Subject identifier from the identity provider"""
8 changes: 7 additions & 1 deletion src/keycardai_api/types/zones/user_list_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ class UserListParams(TypedDict, total=False):
before: str
"""Cursor for backward pagination"""

expand: Annotated[Union[Literal["total_count"], List[Literal["total_count"]]], PropertyInfo(alias="expand[]")]
expand: Annotated[
Union[
Literal["total_count", "session_count", "grant_count"],
List[Literal["total_count", "session_count", "grant_count"]],
],
PropertyInfo(alias="expand[]"),
]

filter_email: Annotated[Union[str, SequenceNotStr[str]], PropertyInfo(alias="filter[email]")]
"""Filter by exact email address"""
Expand Down
2 changes: 2 additions & 0 deletions tests/api_resources/zones/test_delegated_grants.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def test_method_list_with_all_params(self, client: KeycardAPI) -> None:
expand="total_count",
limit=1,
resource_id="resource_id",
sort="-created_at, -created_at,\r\r \t \n\r-created_at,\n\n \t-created_at,\n \r \r created_at,\n\t\t\n\t \ncreated_at,\n \n\r\r -created_at, \t\n\n -created_at",
status="active",
user_id="user_id",
)
Expand Down Expand Up @@ -373,6 +374,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncKeycardAPI)
expand="total_count",
limit=1,
resource_id="resource_id",
sort="-created_at, -created_at,\r\r \t \n\r-created_at,\n\n \t-created_at,\n \r \r created_at,\n\t\t\n\t \ncreated_at,\n \n\r\r -created_at, \t\n\n -created_at",
status="active",
user_id="user_id",
)
Expand Down
4 changes: 4 additions & 0 deletions tests/api_resources/zones/test_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def test_method_create_with_all_params(self, client: KeycardAPI) -> None:
"token_response_access_token_pointer": "token_response_access_token_pointer",
},
"openid": {
"scopes": ["string"],
"user_identifier_claim": "user_identifier_claim",
"userinfo_endpoint": "https://example.com",
},
Expand Down Expand Up @@ -195,6 +196,7 @@ def test_method_update_with_all_params(self, client: KeycardAPI) -> None:
"token_response_access_token_pointer": "token_response_access_token_pointer",
},
"openid": {
"scopes": ["string"],
"user_identifier_claim": "user_identifier_claim",
"userinfo_endpoint": "https://example.com",
},
Expand Down Expand Up @@ -399,6 +401,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKeycardAPI
"token_response_access_token_pointer": "token_response_access_token_pointer",
},
"openid": {
"scopes": ["string"],
"user_identifier_claim": "user_identifier_claim",
"userinfo_endpoint": "https://example.com",
},
Expand Down Expand Up @@ -536,6 +539,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKeycardAPI
"token_response_access_token_pointer": "token_response_access_token_pointer",
},
"openid": {
"scopes": ["string"],
"user_identifier_claim": "user_identifier_claim",
"userinfo_endpoint": "https://example.com",
},
Expand Down
Loading