> ## Documentation Index
> Fetch the complete documentation index at: https://docs.basaltic.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# List service account policies

> Manage the organization policies delegated to this account identity. The identity must belong to the authenticated organization. Changing attachments requires organization policy-assignment permission and authority to manage the target identity.

<Info>
  Primary IAM action: **`workspace:ListServiceAccountPolicies`**.
  The same caller must also have `iam:GetServiceAccount` on the receiving account principal. The Workspace action applies to the target principal; permissions are not combined across separate credentials.
  See [WORKSPACE permissions](/workspace/permissions) for policy examples.
</Info>


## OpenAPI

````yaml /api-reference/specs/workspace.yaml get /v1/service-accounts/{service_account_id}/policies
openapi: 3.0.3
info:
  title: Basaltic Workspace API
  version: 1.0.0
  description: >
    Organization management: organizations, accounts, human users, users-only
    groups, and organization policies. Account IAM identities may receive
    explicitly delegated organization policies through this API. Personal
    authentication remains at the IAM endpoint.


    Organization resources are global and are resolved in the authenticated
    organization. Canonical CRNs are
    crn:workspace:::organization/<organization-uuid>/<type>/<name-or-uuid>.
    Organization policies are separate from account policies; shared system
    policies use crn:workspace:::policy/<name>.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://workspace.basaltic.sh
    description: Global API endpoint
security:
  - BearerAuth: []
paths:
  /v1/service-accounts/{service_account_id}/policies:
    get:
      tags:
        - Workspace
      summary: List service account policies
      description: >-
        Manage the organization policies delegated to this account identity. The
        identity must belong to the authenticated organization. Changing
        attachments requires organization policy-assignment permission and
        authority to manage the target identity.
      operationId: listServiceAccountPolicies
      parameters:
        - $ref: '#/components/parameters/IAMNameFilter'
        - $ref: '#/components/parameters/IAMCRNFilter'
        - $ref: '#/components/parameters/ServiceAccountId'
      responses:
        '200':
          description: List of attached policies
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrincipalPoliciesListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
components:
  parameters:
    IAMNameFilter:
      name: name
      in: query
      allowEmptyValue: true
      description: >-
        Exact resource name, combined with crn using AND before pagination.
        Empty values are filters. Resources without a name never match.
      schema:
        type: string
    IAMCRNFilter:
      name: crn
      in: query
      allowEmptyValue: true
      description: >-
        Exact returned CRN, combined with name using AND before pagination.
        Malformed or empty CRNs return 400; valid mismatched or foreign CRNs
        return an empty page. Resources without a CRN never match.
        Organization-scoped CRNs use the authenticated organization.
      schema:
        type: string
    ServiceAccountId:
      name: service_account_id
      in: path
      description: Service Account ID
      required: true
      schema:
        type: string
        format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    PrincipalPoliciesListResponse:
      type: object
      properties:
        policies:
          type: array
          items:
            $ref: '#/components/schemas/Policy'
    Policy:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
          example: c3d4e5f6-a7b8-9012-3456-7890abcdef12
        crn:
          type: string
          readOnly: true
          description: >-
            Managed policy CRN; absent on inline policy projections in
            effective-policy lists.
          example: >-
            crn:workspace:::organization/550e8400-e29b-41d4-a716-446655440000/policy/BillingReader
        name:
          description: >-
            Resource names must not start with the literal crn: prefix or be
            UUIDs (canonical, compact, braced, or urn:uuid: forms, in either
            case).
          type: string
          example: OrganizationUserReader
        description:
          type: string
          example: Read users in the organization
        tags:
          $ref: '#/components/schemas/Tags'
        is_system:
          type: boolean
          readOnly: true
          description: >-
            Whether this is a system-managed policy (cannot be modified or
            deleted)
          example: false
        document:
          $ref: '#/components/schemas/PolicyDocument'
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: Creation timestamp (not present for system policies)
          example: '2026-01-15T09:30:00Z'
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: Last update timestamp (not present for system policies)
          example: '2026-01-16T14:20:00Z'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: Error code identifying the type of error
              example: INVALID_INPUT
            message:
              type: string
              description: Human-readable error message
              example: Invalid request parameters
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
    Tags:
      type: object
      additionalProperties:
        type: string
      example:
        environment: production
        team: backend
    PolicyDocument:
      type: object
      description: IAM-style policy document
      required:
        - version
        - statements
      properties:
        version:
          type: string
          enum:
            - '2024-01-01'
          example: '2024-01-01'
        statements:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PolicyStatement'
    PolicyStatement:
      type: object
      description: >
        A single statement. The action set is named either positively
        (`actions`)

        or by exclusion (`not_actions`), and the resource set likewise

        (`resources` / `not_resources`) — exactly one of each pair. A statement

        that sets both sides of a pair, or neither, is rejected with

        `INVALID_INPUT` when the document is saved.
      required:
        - effect
      allOf:
        - oneOf:
            - required:
                - actions
            - required:
                - not_actions
        - oneOf:
            - required:
                - resources
            - required:
                - not_resources
      properties:
        sid:
          type: string
          description: Statement identifier
          example: ReadOrganizationUsers
        effect:
          type: string
          enum:
            - allow
            - deny
          example: allow
        actions:
          type: array
          minItems: 1
          items:
            type: string
          description: Actions in service:action format
          example:
            - workspace:GetUser
            - workspace:ListUsers
        not_actions:
          type: array
          minItems: 1
          items:
            type: string
          description: >
            The statement covers every action *except* these. Pairs naturally
            with

            `effect: deny` to carve a hole out of a broad allow; with

            `effect: allow` it grants everything the listed patterns don't name,

            including actions added by future services.
          example:
            - workspace:*
        resources:
          type: array
          minItems: 1
          items:
            type: string
          description: Resource identifiers or patterns
          example:
            - >-
              crn:workspace:::organization/550e8400-e29b-41d4-a716-446655440000/user/*
        not_resources:
          type: array
          minItems: 1
          items:
            type: string
          description: >
            The statement covers every resource *except* these. Same trade-off
            as

            `not_actions`: with `effect: allow` it reaches resources that do not

            exist yet.
          example:
            - >-
              crn:workspace:::organization/550e8400-e29b-41d4-a716-446655440000/user/*
        conditions:
          type: array
          description: Optional conditions for the statement
          items:
            $ref: '#/components/schemas/PolicyCondition'
    PolicyCondition:
      type: object
      description: A condition that must be satisfied for the statement to apply
      required:
        - operator
        - key
        - values
      properties:
        operator:
          type: string
          enum:
            - equals
            - not_equals
            - starts_with
            - ends_with
            - contains
            - in
            - not_in
            - greater_than
            - less_than
            - greater_than_or_equals
            - less_than_or_equals
            - exists
            - not_exists
            - ip_address
            - not_ip_address
          description: The comparison operator
          example: equals
        key:
          type: string
          description: The condition key to evaluate
          example: s3:prefix
        values:
          type: array
          items:
            type: string
          description: Values to compare against
          example:
            - home/
            - shared/
        set_operator:
          type: string
          enum:
            - for_all_values
            - for_any_value
          description: >
            Evaluates `operator` against a multi-valued context key (a set, such
            as

            `basalt:TagKeys` — the tag keys a request carries) rather than a
            single

            value. Omit for an ordinary single-valued condition.


            - `for_all_values` — holds when every member of the request set
              satisfies `operator`. An absent or empty set holds vacuously, so a
              request carrying no tags is not fenced by a tag-key restriction.
            - `for_any_value` — holds when at least one member does. An absent
            or
              empty set does not hold.
          example: for_all_values
  responses:
    Unauthorized:
      description: Authentication required or token invalid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: UNAUTHORIZED
              message: Authentication required
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ACCESS_DENIED
              message: You don't have permission to perform this action
              request_id: 550e8400-e29b-41d4-a716-446655440000
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: Resource not found
              request_id: 550e8400-e29b-41d4-a716-446655440000
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: An internal error occurred
              request_id: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An OAuth 2.0 bearer token, sent as `Authorization: Bearer <token>`.
        This is the recommended way to authenticate.

        Get one by exchanging a service account's access key pair at
        `POST /v1/oauth/token` with `grant_type=client_credentials`. It is the
        standard client-credentials grant, so any OAuth-aware library will
        obtain and refresh it for you.

        ```
        curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
          https://iam.basaltic.sh/v1/oauth/token
        ```

        Tokens last an hour by default. The same access key pair is separately
        your AWS SigV4 credential for the S3-compatible object endpoint, which
        speaks nothing else.

````