diff --git a/langfuse/api/__init__.py b/langfuse/api/__init__.py index ce613a95d..451ad991e 100644 --- a/langfuse/api/__init__.py +++ b/langfuse/api/__init__.py @@ -134,6 +134,8 @@ OpenAiResponseUsageSchema, OpenAiUsage, OptionalObservationBody, + OrganizationApiKey, + OrganizationApiKeysResponse, OrganizationProject, OrganizationProjectsResponse, OtelAttribute, @@ -378,6 +380,8 @@ "OpenAiResponseUsageSchema", "OpenAiUsage", "OptionalObservationBody", + "OrganizationApiKey", + "OrganizationApiKeysResponse", "OrganizationProject", "OrganizationProjectsResponse", "OtelAttribute", diff --git a/langfuse/api/reference.md b/langfuse/api/reference.md index 8291edf16..86a3c640e 100644 --- a/langfuse/api/reference.md +++ b/langfuse/api/reference.md @@ -4330,6 +4330,71 @@ client.organizations.get_organization_projects() + + + + +
client.organizations.get_organization_api_keys() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all API keys for the organization associated with the API key (requires organization-scoped API key) +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from langfuse.client import FernLangfuse + +client = FernLangfuse( + x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME", + x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION", + x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY", + username="YOUR_USERNAME", + password="YOUR_PASSWORD", + base_url="https://yourhost.com/path/to/api", +) +client.organizations.get_organization_api_keys() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
diff --git a/langfuse/api/resources/__init__.py b/langfuse/api/resources/__init__.py index 49e7a40ee..b3a6cc31a 100644 --- a/langfuse/api/resources/__init__.py +++ b/langfuse/api/resources/__init__.py @@ -193,6 +193,8 @@ MembershipResponse, MembershipRole, MembershipsResponse, + OrganizationApiKey, + OrganizationApiKeysResponse, OrganizationProject, OrganizationProjectsResponse, ) @@ -399,6 +401,8 @@ "OpenAiResponseUsageSchema", "OpenAiUsage", "OptionalObservationBody", + "OrganizationApiKey", + "OrganizationApiKeysResponse", "OrganizationProject", "OrganizationProjectsResponse", "OtelAttribute", diff --git a/langfuse/api/resources/organizations/__init__.py b/langfuse/api/resources/organizations/__init__.py index 5c5bfced3..36249ae36 100644 --- a/langfuse/api/resources/organizations/__init__.py +++ b/langfuse/api/resources/organizations/__init__.py @@ -7,6 +7,8 @@ MembershipResponse, MembershipRole, MembershipsResponse, + OrganizationApiKey, + OrganizationApiKeysResponse, OrganizationProject, OrganizationProjectsResponse, ) @@ -18,6 +20,8 @@ "MembershipResponse", "MembershipRole", "MembershipsResponse", + "OrganizationApiKey", + "OrganizationApiKeysResponse", "OrganizationProject", "OrganizationProjectsResponse", ] diff --git a/langfuse/api/resources/organizations/client.py b/langfuse/api/resources/organizations/client.py index b60f2d2bd..1e7bcd117 100644 --- a/langfuse/api/resources/organizations/client.py +++ b/langfuse/api/resources/organizations/client.py @@ -18,6 +18,7 @@ from .types.membership_request import MembershipRequest from .types.membership_response import MembershipResponse from .types.memberships_response import MembershipsResponse +from .types.organization_api_keys_response import OrganizationApiKeysResponse from .types.organization_projects_response import OrganizationProjectsResponse # this is used as the default value for optional parameters @@ -519,6 +520,68 @@ def get_organization_projects( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def get_organization_api_keys( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> OrganizationApiKeysResponse: + """ + Get all API keys for the organization associated with the API key (requires organization-scoped API key) + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationApiKeysResponse + + Examples + -------- + from langfuse.client import FernLangfuse + + client = FernLangfuse( + x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME", + x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION", + x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY", + username="YOUR_USERNAME", + password="YOUR_PASSWORD", + base_url="https://yourhost.com/path/to/api", + ) + client.organizations.get_organization_api_keys() + """ + _response = self._client_wrapper.httpx_client.request( + "api/public/organizations/apiKeys", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as( + OrganizationApiKeysResponse, _response.json() + ) # type: ignore + if _response.status_code == 400: + raise Error(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 403: + raise AccessDeniedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 405: + raise MethodNotAllowedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 404: + raise NotFoundError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncOrganizationsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -1070,3 +1133,73 @@ async def main() -> None: except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_organization_api_keys( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> OrganizationApiKeysResponse: + """ + Get all API keys for the organization associated with the API key (requires organization-scoped API key) + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationApiKeysResponse + + Examples + -------- + import asyncio + + from langfuse.client import AsyncFernLangfuse + + client = AsyncFernLangfuse( + x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME", + x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION", + x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY", + username="YOUR_USERNAME", + password="YOUR_PASSWORD", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.organizations.get_organization_api_keys() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "api/public/organizations/apiKeys", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as( + OrganizationApiKeysResponse, _response.json() + ) # type: ignore + if _response.status_code == 400: + raise Error(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 403: + raise AccessDeniedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 405: + raise MethodNotAllowedError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + if _response.status_code == 404: + raise NotFoundError( + pydantic_v1.parse_obj_as(typing.Any, _response.json()) + ) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/langfuse/api/resources/organizations/types/__init__.py b/langfuse/api/resources/organizations/types/__init__.py index d154f63d8..b3ea09797 100644 --- a/langfuse/api/resources/organizations/types/__init__.py +++ b/langfuse/api/resources/organizations/types/__init__.py @@ -6,6 +6,8 @@ from .membership_response import MembershipResponse from .membership_role import MembershipRole from .memberships_response import MembershipsResponse +from .organization_api_key import OrganizationApiKey +from .organization_api_keys_response import OrganizationApiKeysResponse from .organization_project import OrganizationProject from .organization_projects_response import OrganizationProjectsResponse @@ -16,6 +18,8 @@ "MembershipResponse", "MembershipRole", "MembershipsResponse", + "OrganizationApiKey", + "OrganizationApiKeysResponse", "OrganizationProject", "OrganizationProjectsResponse", ] diff --git a/langfuse/api/resources/organizations/types/organization_api_key.py b/langfuse/api/resources/organizations/types/organization_api_key.py new file mode 100644 index 000000000..ad54bb182 --- /dev/null +++ b/langfuse/api/resources/organizations/types/organization_api_key.py @@ -0,0 +1,54 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class OrganizationApiKey(pydantic_v1.BaseModel): + id: str + created_at: dt.datetime = pydantic_v1.Field(alias="createdAt") + expires_at: typing.Optional[dt.datetime] = pydantic_v1.Field( + alias="expiresAt", default=None + ) + last_used_at: typing.Optional[dt.datetime] = pydantic_v1.Field( + alias="lastUsedAt", default=None + ) + note: typing.Optional[str] = None + public_key: str = pydantic_v1.Field(alias="publicKey") + display_secret_key: str = pydantic_v1.Field(alias="displaySecretKey") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + kwargs_with_defaults_exclude_none: typing.Any = { + "by_alias": True, + "exclude_none": True, + **kwargs, + } + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), + super().dict(**kwargs_with_defaults_exclude_none), + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/langfuse/api/resources/organizations/types/organization_api_keys_response.py b/langfuse/api/resources/organizations/types/organization_api_keys_response.py new file mode 100644 index 000000000..e19ce6373 --- /dev/null +++ b/langfuse/api/resources/organizations/types/organization_api_keys_response.py @@ -0,0 +1,45 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .organization_api_key import OrganizationApiKey + + +class OrganizationApiKeysResponse(pydantic_v1.BaseModel): + api_keys: typing.List[OrganizationApiKey] = pydantic_v1.Field(alias="apiKeys") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + kwargs_with_defaults_exclude_none: typing.Any = { + "by_alias": True, + "exclude_none": True, + **kwargs, + } + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), + super().dict(**kwargs_with_defaults_exclude_none), + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime}