# This file is auto-generated by oagen. Do not edit.

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union

if TYPE_CHECKING:
    from .._client import AsyncWorkOSClient, WorkOSClient

from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven
from .models import (
    AuthorizationCheck,
    AuthorizationResource,
    GroupRoleAssignment,
    GroupRoleAssignmentList,
    Permission,
    ReplaceGroupRoleAssignmentEntry,
    Role,
    RoleList,
    UserRoleAssignment,
)
from workos.common.models.authorization_permission import AuthorizationPermission
from workos.common.models.user_organization_membership_base_list_data import (
    UserOrganizationMembershipBaseListData,
)
from .models import AuthorizationAssignment
from workos.common.models.pagination_order import PaginationOrder
from .._pagination import AsyncPage, SyncPage
from dataclasses import dataclass


@dataclass
class ResourceTargetById:
    """Identify resource target by id."""

    resource_id: str


@dataclass
class ResourceTargetByExternalId:
    """Identify resource target by external id."""

    resource_external_id: str
    resource_type_slug: str


@dataclass
class ParentResourceById:
    """Identify parent resource by id."""

    parent_resource_id: str


@dataclass
class ParentResourceByExternalId:
    """Identify parent resource by external id."""

    parent_resource_type_slug: str
    parent_resource_external_id: str


@dataclass
class ParentById:
    """Identify parent by id."""

    parent_resource_id: str


@dataclass
class ParentByExternalId:
    """Identify parent by external id."""

    parent_resource_type_slug: str
    parent_external_id: str


class Authorization:
    """Authorization API resources."""

    def __init__(self, client: "WorkOSClient") -> None:
        self._client = client

    def list_group_role_assignments(
        self,
        group_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[GroupRoleAssignment]:
        """List role assignments for a group

        List all role assignments granted to a group. Each assignment represents a role granted to the group on a resource.

        Args:
            group_id: The ID of the group.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[GroupRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            model=GroupRoleAssignment,
            params=params,
            request_options=request_options,
        )

    def create_group_role_assignment(
        self,
        group_id: str,
        *,
        role_slug: str,
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignment:
        """Assign a role to a group

        Assign a role to a group on a specific resource.

        Args:
            group_id: The ID of the group.
            role_slug: The slug of the role to assign to the group.
            resource_id: The ID of the resource. Omit along with the external-id fields to target the organization itself.
            resource_external_id: The external ID of the resource.
            resource_type_slug: The resource type slug.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "role_slug": role_slug,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            model=GroupRoleAssignment,
            request_options=request_options,
        )

    def update_group_role_assignments(
        self,
        group_id: str,
        *,
        role_assignments: List[ReplaceGroupRoleAssignmentEntry],
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignmentList:
        """Replace all role assignments for a group

        Replace all role assignments for a group with the provided list. Existing assignments not in the list will be removed.

        Args:
            group_id: The ID of the group.
            role_assignments: The list of role assignments that should exist for the group. All existing assignments will be replaced.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignmentList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_assignments": [item.to_dict() for item in role_assignments],
        }
        return self._client.request(
            method="put",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            model=GroupRoleAssignmentList,
            request_options=request_options,
        )

    def delete_group_role_assignments(
        self,
        group_id: str,
        *,
        role_slug: str,
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove group role assignments by criteria

        Remove role assignments from a group that match the provided criteria. Returns 404 when no matching active assignment is found.

        Args:
            group_id: The ID of the group.
            role_slug: The slug of the role to remove assignments for.
            resource_id: The ID of the resource. Mutually exclusive with `resource_external_id` and `resource_type_slug`.
            resource_external_id: The external ID of the resource.
            resource_type_slug: The resource type slug.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "role_slug": role_slug,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        self._client.request(
            method="delete",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            request_options=request_options,
        )

    def get_group_role_assignment(
        self,
        group_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignment:
        """Get a group role assignment

        Get a specific role assignment for a group by its ID.

        Args:
            group_id: The ID of the group.
            role_assignment_id: The ID of the group role assignment.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=(
                "authorization",
                "groups",
                str(group_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            model=GroupRoleAssignment,
            request_options=request_options,
        )

    def delete_group_role_assignment(
        self,
        group_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a group role assignment

        Remove a specific role assignment from a group by its ID.

        Args:
            group_id: The ID of the group.
            role_assignment_id: The ID of the group role assignment to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "groups",
                str(group_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            request_options=request_options,
        )

    def check(
        self,
        organization_membership_id: str,
        *,
        permission_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationCheck:
        """Check authorization

        Check if an organization membership has a specific permission on a resource. Supports identification by resource_id OR by resource_external_id + resource_type_slug.

        Args:
            organization_membership_id: The ID of the organization membership to check.
            permission_slug: The slug of the permission to check.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationCheck

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permission_slug": permission_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        return self._client.request(
            method="post",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "check",
            ),
            body=body,
            model=AuthorizationCheck,
            request_options=request_options,
        )

    def list_resources_for_membership(
        self,
        organization_membership_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        parent_resource: Union[ParentResourceById, ParentResourceByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[AuthorizationResource]:
        """List resources for organization membership

        Returns all child resources of a parent resource where the organization membership has a specific permission. This is useful for resource discovery—answering "What projects can this user access in this workspace?"

        You must provide either `parent_resource_id` or both `parent_resource_external_id` and `parent_resource_type_slug` to identify the parent resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only child resources where the organization membership has this permission are returned.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizationResource]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
            }.items()
            if v is not None
        }
        if isinstance(parent_resource, ParentResourceById):
            params["parent_resource_id"] = parent_resource.parent_resource_id
        elif isinstance(parent_resource, ParentResourceByExternalId):
            params["parent_resource_type_slug"] = (
                parent_resource.parent_resource_type_slug
            )
            params["parent_resource_external_id"] = (
                parent_resource.parent_resource_external_id
            )
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
            ),
            model=AuthorizationResource,
            params=params,
            request_options=request_options,
        )

    def list_effective_permissions(
        self,
        organization_membership_id: str,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[AuthorizationPermission]:
        """List effective permissions for an organization membership on a resource

        Returns all permissions the organization membership effectively has on a resource, including permissions inherited through roles assigned to ancestor resources.

        Args:
            organization_membership_id: The ID of the organization membership.
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizationPermission]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
                str(resource_id),
                "permissions",
            ),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    def list_effective_permissions_by_external_id(
        self,
        organization_membership_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[AuthorizationPermission]:
        """List effective permissions for an organization membership on a resource by external ID

        Returns all permissions the organization membership effectively has on a resource identified by its external ID, including permissions inherited through roles assigned to ancestor resources.

        Args:
            organization_membership_id: The ID of the organization membership.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizationPermission]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "permissions",
            ),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    def list_role_assignments(
        self,
        organization_membership_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[UserRoleAssignment]:
        """List role assignments

        List all role assignments for an organization membership. This returns all roles that have been assigned to the user on resources, including organization-level and sub-resource roles.

        Args:
            organization_membership_id: The ID of the organization membership.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            resource_id: Filter assignments by the ID of the resource.
            resource_external_id: Filter assignments by the external ID of the resource.
            resource_type_slug: Filter assignments by the slug of the resource type.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    def assign_role(
        self,
        organization_membership_id: str,
        *,
        role_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> UserRoleAssignment:
        """Assign a role

        Assign a role to an organization membership on a specific resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_slug: The slug of the role to assign.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_slug": role_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        return self._client.request(
            method="post",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            body=body,
            model=UserRoleAssignment,
            request_options=request_options,
        )

    def remove_role(
        self,
        organization_membership_id: str,
        *,
        role_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a role assignment

        Remove a role assignment by role slug and resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_slug: The slug of the role to remove.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_slug": role_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            body=body,
            request_options=request_options,
        )

    def remove_role_assignment(
        self,
        organization_membership_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a role assignment by ID

        Remove a role assignment using its ID.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_assignment_id: The ID of the role assignment to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            request_options=request_options,
        )

    def list_organization_roles(
        self,
        organization_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> RoleList:
        """List custom roles

        Get a list of all roles that apply to an organization. This includes both environment roles and custom roles, returned in priority order.

        Args:
            organization_id: The ID of the organization.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            RoleList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=("authorization", "organizations", str(organization_id), "roles"),
            model=RoleList,
            request_options=request_options,
        )

    def create_organization_role(
        self,
        organization_id: str,
        *,
        name: str,
        slug: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Create a custom role

        Create a new custom role for this organization.

        Args:
            organization_id: The ID of the organization.
            slug: A unique identifier for the role within the organization. When provided, must begin with 'org-' and contain only lowercase letters, numbers, hyphens, and underscores. When omitted, a slug is auto-generated from the role name and a random suffix.
            name: A descriptive name for the role.
            description: An optional description of the role's purpose.
            resource_type_slug: The slug of the resource type the role is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="post",
            path=("authorization", "organizations", str(organization_id), "roles"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def get_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Get a custom role

        Retrieve a role that applies to an organization by its slug. This can return either an environment role or a custom role.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            model=Role,
            request_options=request_options,
        )

    def update_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Update a custom role

        Update an existing custom role. Only the fields provided in the request body will be updated.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            name: A descriptive name for the role.
            description: An optional description of the role's purpose.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="patch",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def delete_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a custom role

        Delete an existing custom role.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            request_options=request_options,
        )

    def add_organization_role_permission(
        self,
        organization_id: str,
        slug: str,
        *,
        body_slug: str,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Add a permission to a custom role

        Add a single permission to a custom role. If the permission is already assigned to the role, this operation has no effect.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            body_slug: The slug of the permission to add to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "slug": body_slug,
        }
        return self._client.request(
            method="post",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def set_organization_role_permissions(
        self,
        organization_id: str,
        slug: str,
        *,
        permissions: List[str],
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Set permissions for a custom role

        Replace all permissions on a custom role with the provided list.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            permissions: The permission slugs to assign to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permissions": permissions,
        }
        return self._client.request(
            method="put",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def remove_organization_role_permission(
        self,
        organization_id: str,
        slug: str,
        permission_slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a permission from a custom role

        Remove a single permission from a custom role by its slug.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            permission_slug: The slug of the permission to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
                str(permission_slug),
            ),
            request_options=request_options,
        )

    def get_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Get a resource by external ID

        Retrieve the details of an authorization resource by its external ID, organization, and resource type. This is useful when you only have the external ID from your system and need to fetch the full resource details.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            model=AuthorizationResource,
            request_options=request_options,
        )

    def update_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Update a resource by external ID

        Update an existing authorization resource using its external ID.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            name: A display name for the resource.
            description: An optional description of the resource.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return self._client.request(
            method="patch",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    def delete_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        cascade_delete: Optional[bool] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete an authorization resource by external ID

        Delete an authorization resource by organization, resource type, and external ID. This also deletes all descendant resources.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            cascade_delete: If true, deletes all descendant resources and role assignments. If not set and the resource has children or assignments, the request will fail. Defaults to `false`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params: Dict[str, Any] = {
            k: v
            for k, v in {
                "cascade_delete": cascade_delete,
            }.items()
            if v is not None
        }
        self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            params=params,
            request_options=request_options,
        )

    def list_memberships_for_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        assignment: Optional[Union[AuthorizationAssignment, str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[UserOrganizationMembershipBaseListData]:
        """List memberships for a resource by external ID

        Returns all organization memberships that have a specific permission on a resource, using the resource's external ID. This is useful for answering "Who can access this resource?" when you only have the external ID.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type this resource belongs to.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only users with this permission on the resource are returned.
            assignment: Filter by assignment type. Use "direct" for direct assignments only, or "indirect" to include inherited assignments.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserOrganizationMembershipBaseListData]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
                "assignment": enum_value(assignment)
                if assignment is not None
                else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "organization_memberships",
            ),
            model=UserOrganizationMembershipBaseListData,
            params=params,
            request_options=request_options,
        )

    def list_role_assignments_for_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        role_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[UserRoleAssignment]:
        """List role assignments for a resource by external ID

        List all role assignments granted on a resource, identified by its external ID. Each assignment includes the organization membership it was granted to.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            role_slug: Filter assignments by the slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "role_slug": role_slug,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "role_assignments",
            ),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    def list_resources(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        organization_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        parent: Optional[Union[ParentById, ParentByExternalId]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[AuthorizationResource]:
        """List resources

        Get a paginated list of authorization resources.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            organization_id: Filter resources by organization ID.
            resource_type_slug: Filter resources by resource type slug.
            resource_external_id: Filter resources by external ID.
            parent: Identifies the parent. One of: ParentById, ParentByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizationResource]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "organization_id": organization_id,
                "resource_type_slug": resource_type_slug,
                "resource_external_id": resource_external_id,
            }.items()
            if v is not None
        }
        if parent is not None:
            if isinstance(parent, ParentById):
                params["parent_resource_id"] = parent.parent_resource_id
            elif isinstance(parent, ParentByExternalId):
                params["parent_resource_type_slug"] = parent.parent_resource_type_slug
                params["parent_external_id"] = parent.parent_external_id
        return self._client.request_page(
            method="get",
            path=("authorization", "resources"),
            model=AuthorizationResource,
            params=params,
            request_options=request_options,
        )

    def create_resource(
        self,
        *,
        external_id: str,
        name: str,
        resource_type_slug: str,
        organization_id: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Create an authorization resource

        Create a new authorization resource.

        Args:
            external_id: An external identifier for the resource.
            name: A display name for the resource.
            description: An optional description of the resource.
            resource_type_slug: The slug of the resource type.
            organization_id: The ID of the organization this resource belongs to.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "external_id": external_id,
            "name": name,
            "resource_type_slug": resource_type_slug,
            "organization_id": organization_id,
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return self._client.request(
            method="post",
            path=("authorization", "resources"),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    def get_resource(
        self,
        resource_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Get a resource

        Retrieve the details of an authorization resource by its ID.

        Args:
            resource_id: The ID of the authorization resource.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=("authorization", "resources", str(resource_id)),
            model=AuthorizationResource,
            request_options=request_options,
        )

    def update_resource(
        self,
        resource_id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Update a resource

        Update an existing authorization resource.

        Args:
            resource_id: The ID of the authorization resource.
            name: A display name for the resource.
            description: An optional description of the resource.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return self._client.request(
            method="patch",
            path=("authorization", "resources", str(resource_id)),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    def delete_resource(
        self,
        resource_id: str,
        *,
        cascade_delete: Optional[bool] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete an authorization resource

        Delete an authorization resource and all its descendants.

        Args:
            resource_id: The ID of the authorization resource.
            cascade_delete: If true, deletes all descendant resources and role assignments. If not set and the resource has children or assignments, the request will fail. Defaults to `false`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params: Dict[str, Any] = {
            k: v
            for k, v in {
                "cascade_delete": cascade_delete,
            }.items()
            if v is not None
        }
        self._client.request(
            method="delete",
            path=("authorization", "resources", str(resource_id)),
            params=params,
            request_options=request_options,
        )

    def list_memberships_for_resource(
        self,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        assignment: Optional[Union[AuthorizationAssignment, str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[UserOrganizationMembershipBaseListData]:
        """List organization memberships for resource

        Returns all organization memberships that have a specific permission on a resource instance. This is useful for answering "Who can access this resource?".

        Args:
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only users with this permission on the resource are returned.
            assignment: Filter by assignment type. Use `direct` for direct assignments only, or `indirect` to include inherited assignments.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserOrganizationMembershipBaseListData]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
                "assignment": enum_value(assignment)
                if assignment is not None
                else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=(
                "authorization",
                "resources",
                str(resource_id),
                "organization_memberships",
            ),
            model=UserOrganizationMembershipBaseListData,
            params=params,
            request_options=request_options,
        )

    def list_role_assignments_for_resource(
        self,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        role_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[UserRoleAssignment]:
        """List role assignments for a resource

        List all role assignments granted on a specific resource instance. Each assignment includes the organization membership it was granted to.

        Args:
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            role_slug: Filter assignments by the slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "role_slug": role_slug,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("authorization", "resources", str(resource_id), "role_assignments"),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    def list_environment_roles(
        self,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> RoleList:
        """List environment roles

        List all environment roles in priority order.

        Returns:
            RoleList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=("authorization", "roles"),
            model=RoleList,
            request_options=request_options,
        )

    def create_environment_role(
        self,
        *,
        slug: str,
        name: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Create an environment role

        Create a new environment role.

        Args:
            slug: A unique slug for the role.
            name: A descriptive name for the role.
            description: An optional description of the role.
            resource_type_slug: The slug of the resource type the role is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="post",
            path=("authorization", "roles"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def get_environment_role(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Get an environment role

        Get an environment role by its slug.

        Args:
            slug: The slug of the environment role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=("authorization", "roles", str(slug)),
            model=Role,
            request_options=request_options,
        )

    def update_environment_role(
        self,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Update an environment role

        Update an existing environment role.

        Args:
            slug: The slug of the environment role.
            name: A descriptive name for the role.
            description: An optional description of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="patch",
            path=("authorization", "roles", str(slug)),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def add_environment_role_permission(
        self,
        slug: str,
        *,
        body_slug: str,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Add a permission to an environment role

        Add a single permission to an environment role. If the permission is already assigned to the role, this operation has no effect.

        Args:
            slug: The slug of the environment role.
            body_slug: The slug of the permission to add to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "slug": body_slug,
        }
        return self._client.request(
            method="post",
            path=("authorization", "roles", str(slug), "permissions"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def set_environment_role_permissions(
        self,
        slug: str,
        *,
        permissions: List[str],
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Set permissions for an environment role

        Replace all permissions on an environment role with the provided list.

        Args:
            slug: The slug of the environment role.
            permissions: The permission slugs to assign to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permissions": permissions,
        }
        return self._client.request(
            method="put",
            path=("authorization", "roles", str(slug), "permissions"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    def list_permissions(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[AuthorizationPermission]:
        """List permissions

        Get a list of all permissions in your WorkOS environment.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizationPermission]

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("authorization", "permissions"),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    def create_permission(
        self,
        *,
        slug: str,
        name: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Permission:
        """Create a permission

        Create a new permission in your WorkOS environment. The permission can then be assigned to environment roles and custom roles.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            name: A descriptive name for the Permission.
            description: An optional description of the Permission.
            resource_type_slug: The slug of the resource type this permission is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Permission

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="post",
            path=("authorization", "permissions"),
            body=body,
            model=Permission,
            request_options=request_options,
        )

    def get_permission(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationPermission:
        """Get a permission

        Retrieve a permission by its unique slug.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationPermission

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="get",
            path=("authorization", "permissions", str(slug)),
            model=AuthorizationPermission,
            request_options=request_options,
        )

    def update_permission(
        self,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationPermission:
        """Update a permission

        Update an existing permission. Only the fields provided in the request body will be updated.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            name: A descriptive name for the Permission.
            description: An optional description of the Permission.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationPermission

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return self._client.request(
            method="patch",
            path=("authorization", "permissions", str(slug)),
            body=body,
            model=AuthorizationPermission,
            request_options=request_options,
        )

    def delete_permission(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a permission

        Delete an existing permission. System permissions cannot be deleted.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=("authorization", "permissions", str(slug)),
            request_options=request_options,
        )


class AsyncAuthorization:
    """Authorization API resources (async)."""

    def __init__(self, client: "AsyncWorkOSClient") -> None:
        self._client = client

    async def list_group_role_assignments(
        self,
        group_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[GroupRoleAssignment]:
        """List role assignments for a group

        List all role assignments granted to a group. Each assignment represents a role granted to the group on a resource.

        Args:
            group_id: The ID of the group.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[GroupRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            model=GroupRoleAssignment,
            params=params,
            request_options=request_options,
        )

    async def create_group_role_assignment(
        self,
        group_id: str,
        *,
        role_slug: str,
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignment:
        """Assign a role to a group

        Assign a role to a group on a specific resource.

        Args:
            group_id: The ID of the group.
            role_slug: The slug of the role to assign to the group.
            resource_id: The ID of the resource. Omit along with the external-id fields to target the organization itself.
            resource_external_id: The external ID of the resource.
            resource_type_slug: The resource type slug.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "role_slug": role_slug,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            model=GroupRoleAssignment,
            request_options=request_options,
        )

    async def update_group_role_assignments(
        self,
        group_id: str,
        *,
        role_assignments: List[ReplaceGroupRoleAssignmentEntry],
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignmentList:
        """Replace all role assignments for a group

        Replace all role assignments for a group with the provided list. Existing assignments not in the list will be removed.

        Args:
            group_id: The ID of the group.
            role_assignments: The list of role assignments that should exist for the group. All existing assignments will be replaced.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignmentList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_assignments": [item.to_dict() for item in role_assignments],
        }
        return await self._client.request(
            method="put",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            model=GroupRoleAssignmentList,
            request_options=request_options,
        )

    async def delete_group_role_assignments(
        self,
        group_id: str,
        *,
        role_slug: str,
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove group role assignments by criteria

        Remove role assignments from a group that match the provided criteria. Returns 404 when no matching active assignment is found.

        Args:
            group_id: The ID of the group.
            role_slug: The slug of the role to remove assignments for.
            resource_id: The ID of the resource. Mutually exclusive with `resource_external_id` and `resource_type_slug`.
            resource_external_id: The external ID of the resource.
            resource_type_slug: The resource type slug.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "role_slug": role_slug,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        await self._client.request(
            method="delete",
            path=("authorization", "groups", str(group_id), "role_assignments"),
            body=body,
            request_options=request_options,
        )

    async def get_group_role_assignment(
        self,
        group_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> GroupRoleAssignment:
        """Get a group role assignment

        Get a specific role assignment for a group by its ID.

        Args:
            group_id: The ID of the group.
            role_assignment_id: The ID of the group role assignment.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            GroupRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=(
                "authorization",
                "groups",
                str(group_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            model=GroupRoleAssignment,
            request_options=request_options,
        )

    async def delete_group_role_assignment(
        self,
        group_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a group role assignment

        Remove a specific role assignment from a group by its ID.

        Args:
            group_id: The ID of the group.
            role_assignment_id: The ID of the group role assignment to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "groups",
                str(group_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            request_options=request_options,
        )

    async def check(
        self,
        organization_membership_id: str,
        *,
        permission_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationCheck:
        """Check authorization

        Check if an organization membership has a specific permission on a resource. Supports identification by resource_id OR by resource_external_id + resource_type_slug.

        Args:
            organization_membership_id: The ID of the organization membership to check.
            permission_slug: The slug of the permission to check.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationCheck

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permission_slug": permission_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        return await self._client.request(
            method="post",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "check",
            ),
            body=body,
            model=AuthorizationCheck,
            request_options=request_options,
        )

    async def list_resources_for_membership(
        self,
        organization_membership_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        parent_resource: Union[ParentResourceById, ParentResourceByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[AuthorizationResource]:
        """List resources for organization membership

        Returns all child resources of a parent resource where the organization membership has a specific permission. This is useful for resource discovery—answering "What projects can this user access in this workspace?"

        You must provide either `parent_resource_id` or both `parent_resource_external_id` and `parent_resource_type_slug` to identify the parent resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only child resources where the organization membership has this permission are returned.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizationResource]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
            }.items()
            if v is not None
        }
        if isinstance(parent_resource, ParentResourceById):
            params["parent_resource_id"] = parent_resource.parent_resource_id
        elif isinstance(parent_resource, ParentResourceByExternalId):
            params["parent_resource_type_slug"] = (
                parent_resource.parent_resource_type_slug
            )
            params["parent_resource_external_id"] = (
                parent_resource.parent_resource_external_id
            )
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
            ),
            model=AuthorizationResource,
            params=params,
            request_options=request_options,
        )

    async def list_effective_permissions(
        self,
        organization_membership_id: str,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[AuthorizationPermission]:
        """List effective permissions for an organization membership on a resource

        Returns all permissions the organization membership effectively has on a resource, including permissions inherited through roles assigned to ancestor resources.

        Args:
            organization_membership_id: The ID of the organization membership.
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizationPermission]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
                str(resource_id),
                "permissions",
            ),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    async def list_effective_permissions_by_external_id(
        self,
        organization_membership_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[AuthorizationPermission]:
        """List effective permissions for an organization membership on a resource by external ID

        Returns all permissions the organization membership effectively has on a resource identified by its external ID, including permissions inherited through roles assigned to ancestor resources.

        Args:
            organization_membership_id: The ID of the organization membership.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizationPermission]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "permissions",
            ),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    async def list_role_assignments(
        self,
        organization_membership_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        resource_id: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[UserRoleAssignment]:
        """List role assignments

        List all role assignments for an organization membership. This returns all roles that have been assigned to the user on resources, including organization-level and sub-resource roles.

        Args:
            organization_membership_id: The ID of the organization membership.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            resource_id: Filter assignments by the ID of the resource.
            resource_external_id: Filter assignments by the external ID of the resource.
            resource_type_slug: Filter assignments by the slug of the resource type.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "resource_id": resource_id,
                "resource_external_id": resource_external_id,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    async def assign_role(
        self,
        organization_membership_id: str,
        *,
        role_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> UserRoleAssignment:
        """Assign a role

        Assign a role to an organization membership on a specific resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_slug: The slug of the role to assign.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserRoleAssignment

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_slug": role_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        return await self._client.request(
            method="post",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            body=body,
            model=UserRoleAssignment,
            request_options=request_options,
        )

    async def remove_role(
        self,
        organization_membership_id: str,
        *,
        role_slug: str,
        resource_target: Union[ResourceTargetById, ResourceTargetByExternalId],
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a role assignment

        Remove a role assignment by role slug and resource.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_slug: The slug of the role to remove.
            resource_target: Identifies the resource target. One of: ResourceTargetById, ResourceTargetByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "role_slug": role_slug,
        }
        if isinstance(resource_target, ResourceTargetById):
            body["resource_id"] = resource_target.resource_id
        elif isinstance(resource_target, ResourceTargetByExternalId):
            body["resource_external_id"] = resource_target.resource_external_id
            body["resource_type_slug"] = resource_target.resource_type_slug
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
            ),
            body=body,
            request_options=request_options,
        )

    async def remove_role_assignment(
        self,
        organization_membership_id: str,
        role_assignment_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a role assignment by ID

        Remove a role assignment using its ID.

        Args:
            organization_membership_id: The ID of the organization membership.
            role_assignment_id: The ID of the role assignment to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "organization_memberships",
                str(organization_membership_id),
                "role_assignments",
                str(role_assignment_id),
            ),
            request_options=request_options,
        )

    async def list_organization_roles(
        self,
        organization_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> RoleList:
        """List custom roles

        Get a list of all roles that apply to an organization. This includes both environment roles and custom roles, returned in priority order.

        Args:
            organization_id: The ID of the organization.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            RoleList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=("authorization", "organizations", str(organization_id), "roles"),
            model=RoleList,
            request_options=request_options,
        )

    async def create_organization_role(
        self,
        organization_id: str,
        *,
        name: str,
        slug: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Create a custom role

        Create a new custom role for this organization.

        Args:
            organization_id: The ID of the organization.
            slug: A unique identifier for the role within the organization. When provided, must begin with 'org-' and contain only lowercase letters, numbers, hyphens, and underscores. When omitted, a slug is auto-generated from the role name and a random suffix.
            name: A descriptive name for the role.
            description: An optional description of the role's purpose.
            resource_type_slug: The slug of the resource type the role is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="post",
            path=("authorization", "organizations", str(organization_id), "roles"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def get_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Get a custom role

        Retrieve a role that applies to an organization by its slug. This can return either an environment role or a custom role.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            model=Role,
            request_options=request_options,
        )

    async def update_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Update a custom role

        Update an existing custom role. Only the fields provided in the request body will be updated.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            name: A descriptive name for the role.
            description: An optional description of the role's purpose.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="patch",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def delete_organization_role(
        self,
        organization_id: str,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a custom role

        Delete an existing custom role.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
            ),
            request_options=request_options,
        )

    async def add_organization_role_permission(
        self,
        organization_id: str,
        slug: str,
        *,
        body_slug: str,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Add a permission to a custom role

        Add a single permission to a custom role. If the permission is already assigned to the role, this operation has no effect.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            body_slug: The slug of the permission to add to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "slug": body_slug,
        }
        return await self._client.request(
            method="post",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def set_organization_role_permissions(
        self,
        organization_id: str,
        slug: str,
        *,
        permissions: List[str],
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Set permissions for a custom role

        Replace all permissions on a custom role with the provided list.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            permissions: The permission slugs to assign to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permissions": permissions,
        }
        return await self._client.request(
            method="put",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
            ),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def remove_organization_role_permission(
        self,
        organization_id: str,
        slug: str,
        permission_slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Remove a permission from a custom role

        Remove a single permission from a custom role by its slug.

        Args:
            organization_id: The ID of the organization.
            slug: The slug of the role.
            permission_slug: The slug of the permission to remove.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "roles",
                str(slug),
                "permissions",
                str(permission_slug),
            ),
            request_options=request_options,
        )

    async def get_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Get a resource by external ID

        Retrieve the details of an authorization resource by its external ID, organization, and resource type. This is useful when you only have the external ID from your system and need to fetch the full resource details.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            model=AuthorizationResource,
            request_options=request_options,
        )

    async def update_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Update a resource by external ID

        Update an existing authorization resource using its external ID.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            name: A display name for the resource.
            description: An optional description of the resource.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return await self._client.request(
            method="patch",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    async def delete_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        cascade_delete: Optional[bool] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete an authorization resource by external ID

        Delete an authorization resource by organization, resource type, and external ID. This also deletes all descendant resources.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            cascade_delete: If true, deletes all descendant resources and role assignments. If not set and the resource has children or assignments, the request will fail. Defaults to `false`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params: Dict[str, Any] = {
            k: v
            for k, v in {
                "cascade_delete": cascade_delete,
            }.items()
            if v is not None
        }
        await self._client.request(
            method="delete",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
            ),
            params=params,
            request_options=request_options,
        )

    async def list_memberships_for_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        assignment: Optional[Union[AuthorizationAssignment, str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[UserOrganizationMembershipBaseListData]:
        """List memberships for a resource by external ID

        Returns all organization memberships that have a specific permission on a resource, using the resource's external ID. This is useful for answering "Who can access this resource?" when you only have the external ID.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type this resource belongs to.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only users with this permission on the resource are returned.
            assignment: Filter by assignment type. Use "direct" for direct assignments only, or "indirect" to include inherited assignments.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserOrganizationMembershipBaseListData]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
                "assignment": enum_value(assignment)
                if assignment is not None
                else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "organization_memberships",
            ),
            model=UserOrganizationMembershipBaseListData,
            params=params,
            request_options=request_options,
        )

    async def list_role_assignments_for_resource_by_external_id(
        self,
        organization_id: str,
        resource_type_slug: str,
        external_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        role_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[UserRoleAssignment]:
        """List role assignments for a resource by external ID

        List all role assignments granted on a resource, identified by its external ID. Each assignment includes the organization membership it was granted to.

        Args:
            organization_id: The ID of the organization that owns the resource.
            resource_type_slug: The slug of the resource type.
            external_id: An identifier you provide to reference the resource in your system.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            role_slug: Filter assignments by the slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "role_slug": role_slug,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "organizations",
                str(organization_id),
                "resources",
                str(resource_type_slug),
                str(external_id),
                "role_assignments",
            ),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    async def list_resources(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        organization_id: Optional[str] = None,
        resource_type_slug: Optional[str] = None,
        resource_external_id: Optional[str] = None,
        parent: Optional[Union[ParentById, ParentByExternalId]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[AuthorizationResource]:
        """List resources

        Get a paginated list of authorization resources.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            organization_id: Filter resources by organization ID.
            resource_type_slug: Filter resources by resource type slug.
            resource_external_id: Filter resources by external ID.
            parent: Identifies the parent. One of: ParentById, ParentByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizationResource]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "organization_id": organization_id,
                "resource_type_slug": resource_type_slug,
                "resource_external_id": resource_external_id,
            }.items()
            if v is not None
        }
        if parent is not None:
            if isinstance(parent, ParentById):
                params["parent_resource_id"] = parent.parent_resource_id
            elif isinstance(parent, ParentByExternalId):
                params["parent_resource_type_slug"] = parent.parent_resource_type_slug
                params["parent_external_id"] = parent.parent_external_id
        return await self._client.request_page(
            method="get",
            path=("authorization", "resources"),
            model=AuthorizationResource,
            params=params,
            request_options=request_options,
        )

    async def create_resource(
        self,
        *,
        external_id: str,
        name: str,
        resource_type_slug: str,
        organization_id: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Create an authorization resource

        Create a new authorization resource.

        Args:
            external_id: An external identifier for the resource.
            name: A display name for the resource.
            description: An optional description of the resource.
            resource_type_slug: The slug of the resource type.
            organization_id: The ID of the organization this resource belongs to.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "external_id": external_id,
            "name": name,
            "resource_type_slug": resource_type_slug,
            "organization_id": organization_id,
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return await self._client.request(
            method="post",
            path=("authorization", "resources"),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    async def get_resource(
        self,
        resource_id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Get a resource

        Retrieve the details of an authorization resource by its ID.

        Args:
            resource_id: The ID of the authorization resource.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=("authorization", "resources", str(resource_id)),
            model=AuthorizationResource,
            request_options=request_options,
        )

    async def update_resource(
        self,
        resource_id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        parent_resource: Optional[
            Union[ParentResourceById, ParentResourceByExternalId]
        ] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationResource:
        """Update a resource

        Update an existing authorization resource.

        Args:
            resource_id: The ID of the authorization resource.
            name: A display name for the resource.
            description: An optional description of the resource.
            parent_resource: Identifies the parent resource. One of: ParentResourceById, ParentResourceByExternalId.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationResource

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if parent_resource is not None:
            if isinstance(parent_resource, ParentResourceById):
                body["parent_resource_id"] = parent_resource.parent_resource_id
            elif isinstance(parent_resource, ParentResourceByExternalId):
                body["parent_resource_external_id"] = (
                    parent_resource.parent_resource_external_id
                )
                body["parent_resource_type_slug"] = (
                    parent_resource.parent_resource_type_slug
                )
        return await self._client.request(
            method="patch",
            path=("authorization", "resources", str(resource_id)),
            body=body,
            model=AuthorizationResource,
            request_options=request_options,
        )

    async def delete_resource(
        self,
        resource_id: str,
        *,
        cascade_delete: Optional[bool] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete an authorization resource

        Delete an authorization resource and all its descendants.

        Args:
            resource_id: The ID of the authorization resource.
            cascade_delete: If true, deletes all descendant resources and role assignments. If not set and the resource has children or assignments, the request will fail. Defaults to `false`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params: Dict[str, Any] = {
            k: v
            for k, v in {
                "cascade_delete": cascade_delete,
            }.items()
            if v is not None
        }
        await self._client.request(
            method="delete",
            path=("authorization", "resources", str(resource_id)),
            params=params,
            request_options=request_options,
        )

    async def list_memberships_for_resource(
        self,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        permission_slug: str,
        assignment: Optional[Union[AuthorizationAssignment, str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[UserOrganizationMembershipBaseListData]:
        """List organization memberships for resource

        Returns all organization memberships that have a specific permission on a resource instance. This is useful for answering "Who can access this resource?".

        Args:
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            permission_slug: The permission slug to filter by. Only users with this permission on the resource are returned.
            assignment: Filter by assignment type. Use `direct` for direct assignments only, or `indirect` to include inherited assignments.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserOrganizationMembershipBaseListData]

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "permission_slug": permission_slug,
                "assignment": enum_value(assignment)
                if assignment is not None
                else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=(
                "authorization",
                "resources",
                str(resource_id),
                "organization_memberships",
            ),
            model=UserOrganizationMembershipBaseListData,
            params=params,
            request_options=request_options,
        )

    async def list_role_assignments_for_resource(
        self,
        resource_id: str,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        role_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[UserRoleAssignment]:
        """List role assignments for a resource

        List all role assignments granted on a specific resource instance. Each assignment includes the organization membership it was granted to.

        Args:
            resource_id: The ID of the authorization resource.
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            role_slug: Filter assignments by the slug of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserRoleAssignment]

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "role_slug": role_slug,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("authorization", "resources", str(resource_id), "role_assignments"),
            model=UserRoleAssignment,
            params=params,
            request_options=request_options,
        )

    async def list_environment_roles(
        self,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> RoleList:
        """List environment roles

        List all environment roles in priority order.

        Returns:
            RoleList

        Raises:
            AuthorizationError: If the request is forbidden (403).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=("authorization", "roles"),
            model=RoleList,
            request_options=request_options,
        )

    async def create_environment_role(
        self,
        *,
        slug: str,
        name: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Create an environment role

        Create a new environment role.

        Args:
            slug: A unique slug for the role.
            name: A descriptive name for the role.
            description: An optional description of the role.
            resource_type_slug: The slug of the resource type the role is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="post",
            path=("authorization", "roles"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def get_environment_role(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Get an environment role

        Get an environment role by its slug.

        Args:
            slug: The slug of the environment role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=("authorization", "roles", str(slug)),
            model=Role,
            request_options=request_options,
        )

    async def update_environment_role(
        self,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Update an environment role

        Update an existing environment role.

        Args:
            slug: The slug of the environment role.
            name: A descriptive name for the role.
            description: An optional description of the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="patch",
            path=("authorization", "roles", str(slug)),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def add_environment_role_permission(
        self,
        slug: str,
        *,
        body_slug: str,
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Add a permission to an environment role

        Add a single permission to an environment role. If the permission is already assigned to the role, this operation has no effect.

        Args:
            slug: The slug of the environment role.
            body_slug: The slug of the permission to add to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "slug": body_slug,
        }
        return await self._client.request(
            method="post",
            path=("authorization", "roles", str(slug), "permissions"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def set_environment_role_permissions(
        self,
        slug: str,
        *,
        permissions: List[str],
        request_options: Optional[RequestOptions] = None,
    ) -> Role:
        """Set permissions for an environment role

        Replace all permissions on an environment role with the provided list.

        Args:
            slug: The slug of the environment role.
            permissions: The permission slugs to assign to the role.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Role

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            "permissions": permissions,
        }
        return await self._client.request(
            method="put",
            path=("authorization", "roles", str(slug), "permissions"),
            body=body,
            model=Role,
            request_options=request_options,
        )

    async def list_permissions(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[AuthorizationPermission]:
        """List permissions

        Get a list of all permissions in your WorkOS environment.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizationPermission]

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("authorization", "permissions"),
            model=AuthorizationPermission,
            params=params,
            request_options=request_options,
        )

    async def create_permission(
        self,
        *,
        slug: str,
        name: str,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        resource_type_slug: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> Permission:
        """Create a permission

        Create a new permission in your WorkOS environment. The permission can then be assigned to environment roles and custom roles.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            name: A descriptive name for the Permission.
            description: An optional description of the Permission.
            resource_type_slug: The slug of the resource type this permission is scoped to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            Permission

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "slug": slug,
                "name": name,
                "resource_type_slug": resource_type_slug,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="post",
            path=("authorization", "permissions"),
            body=body,
            model=Permission,
            request_options=request_options,
        )

    async def get_permission(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationPermission:
        """Get a permission

        Retrieve a permission by its unique slug.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationPermission

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="get",
            path=("authorization", "permissions", str(slug)),
            model=AuthorizationPermission,
            request_options=request_options,
        )

    async def update_permission(
        self,
        slug: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> AuthorizationPermission:
        """Update a permission

        Update an existing permission. Only the fields provided in the request body will be updated.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            name: A descriptive name for the Permission.
            description: An optional description of the Permission.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthorizationPermission

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        return await self._client.request(
            method="patch",
            path=("authorization", "permissions", str(slug)),
            body=body,
            model=AuthorizationPermission,
            request_options=request_options,
        )

    async def delete_permission(
        self,
        slug: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a permission

        Delete an existing permission. System permissions cannot be deleted.

        Args:
            slug: A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=("authorization", "permissions", str(slug)),
            request_options=request_options,
        )
